aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2015-11-04 08:48:38 -0500
committerIngo Molnar <mingo@kernel.org>2015-11-09 10:13:11 -0500
commit2fd59077755c44dbbd9b2fa89cf988235a3a6a2b (patch)
treeb9a35f6555ce5dbebcbb4c1fd50760a221123b7a
parentbad9bc2d466445b0398b78a452b7706a05ebc182 (diff)
perf: Disable IRQs across RCU RS CS that acquires scheduler lock
The perf_lock_task_context() function disables preemption across its RCU read-side critical section because that critical section acquires a scheduler lock. If there was a preemption during that RCU read-side critical section, the rcu_read_unlock() could attempt to acquire scheduler locks, resulting in deadlock. However, recent optimizations to expedited grace periods mean that IPI handlers that execute during preemptible RCU read-side critical sections can now cause the subsequent rcu_read_unlock() to acquire scheduler locks. Disabling preemption does nothiing to prevent these IPI handlers from executing, so these optimizations introduced a deadlock. In theory, this deadlock could be avoided by pulling all wakeups and printk()s out from rnp->lock critical sections, but in practice this would re-introduce some RCU CPU stall warning bugs. Given that acquiring scheduler locks entails disabling interrupts, these deadlocks can be avoided by disabling interrupts (instead of disabling preemption) across any RCU read-side critical that acquires scheduler locks and holds them across the rcu_read_unlock(). This commit therefore makes this change for perf_lock_task_context(). Reported-by: Dave Jones <davej@codemonkey.org.uk> Reported-by: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Stephane Eranian <eranian@gmail.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/20151104134838.GR29027@linux.vnet.ibm.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--kernel/events/core.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ea02109aee77..f8e5c443d74e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1050,13 +1050,13 @@ retry:
1050 /* 1050 /*
1051 * One of the few rules of preemptible RCU is that one cannot do 1051 * One of the few rules of preemptible RCU is that one cannot do
1052 * rcu_read_unlock() while holding a scheduler (or nested) lock when 1052 * rcu_read_unlock() while holding a scheduler (or nested) lock when
1053 * part of the read side critical section was preemptible -- see 1053 * part of the read side critical section was irqs-enabled -- see
1054 * rcu_read_unlock_special(). 1054 * rcu_read_unlock_special().
1055 * 1055 *
1056 * Since ctx->lock nests under rq->lock we must ensure the entire read 1056 * Since ctx->lock nests under rq->lock we must ensure the entire read
1057 * side critical section is non-preemptible. 1057 * side critical section has interrupts disabled.
1058 */ 1058 */
1059 preempt_disable(); 1059 local_irq_save(*flags);
1060 rcu_read_lock(); 1060 rcu_read_lock();
1061 ctx = rcu_dereference(task->perf_event_ctxp[ctxn]); 1061 ctx = rcu_dereference(task->perf_event_ctxp[ctxn]);
1062 if (ctx) { 1062 if (ctx) {
@@ -1070,21 +1070,22 @@ retry:
1070 * if so. If we locked the right context, then it 1070 * if so. If we locked the right context, then it
1071 * can't get swapped on us any more. 1071 * can't get swapped on us any more.
1072 */ 1072 */
1073 raw_spin_lock_irqsave(&ctx->lock, *flags); 1073 raw_spin_lock(&ctx->lock);
1074 if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) { 1074 if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) {
1075 raw_spin_unlock_irqrestore(&ctx->lock, *flags); 1075 raw_spin_unlock(&ctx->lock);
1076 rcu_read_unlock(); 1076 rcu_read_unlock();
1077 preempt_enable(); 1077 local_irq_restore(*flags);
1078 goto retry; 1078 goto retry;
1079 } 1079 }
1080 1080
1081 if (!atomic_inc_not_zero(&ctx->refcount)) { 1081 if (!atomic_inc_not_zero(&ctx->refcount)) {
1082 raw_spin_unlock_irqrestore(&ctx->lock, *flags); 1082 raw_spin_unlock(&ctx->lock);
1083 ctx = NULL; 1083 ctx = NULL;
1084 } 1084 }
1085 } 1085 }
1086 rcu_read_unlock(); 1086 rcu_read_unlock();
1087 preempt_enable(); 1087 if (!ctx)
1088 local_irq_restore(*flags);
1088 return ctx; 1089 return ctx;
1089} 1090}
1090 1091