diff options
Diffstat (limited to '')
-rw-r--r-- | debian/patches-rt/0011-sched-fair-Robustify-CFS-bandwidth-timer-locking.patch | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/debian/patches-rt/0011-sched-fair-Robustify-CFS-bandwidth-timer-locking.patch b/debian/patches-rt/0011-sched-fair-Robustify-CFS-bandwidth-timer-locking.patch new file mode 100644 index 000000000..e250e2aa4 --- /dev/null +++ b/debian/patches-rt/0011-sched-fair-Robustify-CFS-bandwidth-timer-locking.patch @@ -0,0 +1,148 @@ +From e19a4689e9aa66751202caf5aeade89ecb118f2c Mon Sep 17 00:00:00 2001 +From: Peter Zijlstra <peterz@infradead.org> +Date: Mon, 7 Jan 2019 13:52:31 +0100 +Subject: [PATCH 011/347] sched/fair: Robustify CFS-bandwidth timer locking +Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/4.19/older/patches-4.19.246-rt110.tar.xz + +Traditionally hrtimer callbacks were run with IRQs disabled, but with +the introduction of HRTIMER_MODE_SOFT it is possible they run from +SoftIRQ context, which does _NOT_ have IRQs disabled. + +Allow for the CFS bandwidth timers (period_timer and slack_timer) to +be ran from SoftIRQ context; this entails removing the assumption that +IRQs are already disabled from the locking. + +While mainline doesn't strictly need this, -RT forces all timers not +explicitly marked with MODE_HARD into MODE_SOFT and trips over this. +And marking these timers as MODE_HARD doesn't make sense as they're +not required for RT operation and can potentially be quite expensive. + +Cc: Ingo Molnar <mingo@redhat.com> +Cc: Thomas Gleixner <tglx@linutronix.de> +Cc: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +Reported-by: Tom Putzeys <tom.putzeys@be.atlascopco.com> +Tested-by: Mike Galbraith <efault@gmx.de> +Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> +Link: https://lkml.kernel.org/r/20190107125231.GE14122@hirez.programming.kicks-ass.net +Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> +--- + kernel/sched/fair.c | 30 ++++++++++++++++-------------- + 1 file changed, 16 insertions(+), 14 deletions(-) + +diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c +index 84e7efda98da..e84a056f783f 100644 +--- a/kernel/sched/fair.c ++++ b/kernel/sched/fair.c +@@ -4597,7 +4597,7 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, u64 remaining) + struct rq *rq = rq_of(cfs_rq); + struct rq_flags rf; + +- rq_lock(rq, &rf); ++ rq_lock_irqsave(rq, &rf); + if (!cfs_rq_throttled(cfs_rq)) + goto next; + +@@ -4616,7 +4616,7 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, u64 remaining) + unthrottle_cfs_rq(cfs_rq); + + next: +- rq_unlock(rq, &rf); ++ rq_unlock_irqrestore(rq, &rf); + + if (!remaining) + break; +@@ -4632,7 +4632,7 @@ static u64 distribute_cfs_runtime(struct cfs_bandwidth *cfs_b, u64 remaining) + * period the timer is deactivated until scheduling resumes; cfs_b->idle is + * used to track this state. + */ +-static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun) ++static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun, unsigned long flags) + { + u64 runtime; + int throttled; +@@ -4672,10 +4672,10 @@ static int do_sched_cfs_period_timer(struct cfs_bandwidth *cfs_b, int overrun) + while (throttled && cfs_b->runtime > 0 && !cfs_b->distribute_running) { + runtime = cfs_b->runtime; + cfs_b->distribute_running = 1; +- raw_spin_unlock(&cfs_b->lock); ++ raw_spin_unlock_irqrestore(&cfs_b->lock, flags); + /* we can't nest cfs_b->lock while distributing bandwidth */ + runtime = distribute_cfs_runtime(cfs_b, runtime); +- raw_spin_lock(&cfs_b->lock); ++ raw_spin_lock_irqsave(&cfs_b->lock, flags); + + cfs_b->distribute_running = 0; + throttled = !list_empty(&cfs_b->throttled_cfs_rq); +@@ -4783,16 +4783,17 @@ static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq) + static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) + { + u64 runtime = 0, slice = sched_cfs_bandwidth_slice(); ++ unsigned long flags; + + /* confirm we're still not at a refresh boundary */ +- raw_spin_lock(&cfs_b->lock); ++ raw_spin_lock_irqsave(&cfs_b->lock, flags); + if (cfs_b->distribute_running) { +- raw_spin_unlock(&cfs_b->lock); ++ raw_spin_unlock_irqrestore(&cfs_b->lock, flags); + return; + } + + if (runtime_refresh_within(cfs_b, min_bandwidth_expiration)) { +- raw_spin_unlock(&cfs_b->lock); ++ raw_spin_unlock_irqrestore(&cfs_b->lock, flags); + return; + } + +@@ -4802,17 +4803,17 @@ static void do_sched_cfs_slack_timer(struct cfs_bandwidth *cfs_b) + if (runtime) + cfs_b->distribute_running = 1; + +- raw_spin_unlock(&cfs_b->lock); ++ raw_spin_unlock_irqrestore(&cfs_b->lock, flags); + + if (!runtime) + return; + + runtime = distribute_cfs_runtime(cfs_b, runtime); + +- raw_spin_lock(&cfs_b->lock); ++ raw_spin_lock_irqsave(&cfs_b->lock, flags); + cfs_b->runtime -= min(runtime, cfs_b->runtime); + cfs_b->distribute_running = 0; +- raw_spin_unlock(&cfs_b->lock); ++ raw_spin_unlock_irqrestore(&cfs_b->lock, flags); + } + + /* +@@ -4892,11 +4893,12 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer) + { + struct cfs_bandwidth *cfs_b = + container_of(timer, struct cfs_bandwidth, period_timer); ++ unsigned long flags; + int overrun; + int idle = 0; + int count = 0; + +- raw_spin_lock(&cfs_b->lock); ++ raw_spin_lock_irqsave(&cfs_b->lock, flags); + for (;;) { + overrun = hrtimer_forward_now(timer, cfs_b->period); + if (!overrun) +@@ -4932,11 +4934,11 @@ static enum hrtimer_restart sched_cfs_period_timer(struct hrtimer *timer) + count = 0; + } + +- idle = do_sched_cfs_period_timer(cfs_b, overrun); ++ idle = do_sched_cfs_period_timer(cfs_b, overrun, flags); + } + if (idle) + cfs_b->period_active = 0; +- raw_spin_unlock(&cfs_b->lock); ++ raw_spin_unlock_irqrestore(&cfs_b->lock, flags); + + return idle ? HRTIMER_NORESTART : HRTIMER_RESTART; + } +-- +2.36.1 + |