summaryrefslogtreecommitdiffstats
path: root/kernel/sched/sched.h
diff options
context:
space:
mode:
authorPeter Zijlstra <peterz@infradead.org>2020-05-11 14:13:00 +0200
committerPeter Zijlstra <peterz@infradead.org>2020-11-10 18:38:57 +0100
commit565790d28b1e33ee2f77bad5348b99f6dfc366fd (patch)
tree179b55e6e483c0daf2975f95ccf57401fad0e7d6 /kernel/sched/sched.h
parenta8b62fd0850503cf1e557d7e5a98d3f1f5c25eef (diff)
downloadlinux-565790d28b1e33ee2f77bad5348b99f6dfc366fd.tar.bz2
sched: Fix balance_callback()
The intent of balance_callback() has always been to delay executing balancing operations until the end of the current rq->lock section. This is because balance operations must often drop rq->lock, and that isn't safe in general. However, as noted by Scott, there were a few holes in that scheme; balance_callback() was called after rq->lock was dropped, which means another CPU can interleave and touch the callback list. Rework code to call the balance callbacks before dropping rq->lock where possible, and otherwise splice the balance list onto a local stack. This guarantees that the balance list must be empty when we take rq->lock. IOW, we'll only ever run our own balance callbacks. Reported-by: Scott Wood <swood@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Reviewed-by: Valentin Schneider <valentin.schneider@arm.com> Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com> Link: https://lkml.kernel.org/r/20201023102346.203901269@infradead.org
Diffstat (limited to 'kernel/sched/sched.h')
-rw-r--r--kernel/sched/sched.h3
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index df80bfcea92e..738a00b9237a 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -1221,6 +1221,9 @@ static inline void rq_pin_lock(struct rq *rq, struct rq_flags *rf)
rq->clock_update_flags &= (RQCF_REQ_SKIP|RQCF_ACT_SKIP);
rf->clock_update_flags = 0;
#endif
+#ifdef CONFIG_SMP
+ SCHED_WARN_ON(rq->balance_callback);
+#endif
}
static inline void rq_unpin_lock(struct rq *rq, struct rq_flags *rf)