From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751322AbbKJGks (ORCPT ); Tue, 10 Nov 2015 01:40:48 -0500 Received: from terminus.zytor.com ([198.137.202.10]:46678 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750897AbbKJGkq (ORCPT ); Tue, 10 Nov 2015 01:40:46 -0500 Date: Mon, 9 Nov 2015 22:39:48 -0800 From: "tip-bot for Paul E. McKenney" Message-ID: Cc: eranian@gmail.com, acme@redhat.com, davej@codemonkey.org.uk, tglx@linutronix.de, jolsa@redhat.com, linux-kernel@vger.kernel.org, paulmck@linux.vnet.ibm.com, torvalds@linux-foundation.org, peterz@infradead.org, hpa@zytor.com, mingo@kernel.org Reply-To: peterz@infradead.org, paulmck@linux.vnet.ibm.com, torvalds@linux-foundation.org, mingo@kernel.org, hpa@zytor.com, davej@codemonkey.org.uk, tglx@linutronix.de, acme@redhat.com, eranian@gmail.com, linux-kernel@vger.kernel.org, jolsa@redhat.com In-Reply-To: <20151104134838.GR29027@linux.vnet.ibm.com> References: <20151104134838.GR29027@linux.vnet.ibm.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/urgent] perf: Disable IRQs across RCU RS CS that acquires scheduler lock Git-Commit-ID: 2fd59077755c44dbbd9b2fa89cf988235a3a6a2b X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: 2fd59077755c44dbbd9b2fa89cf988235a3a6a2b Gitweb: http://git.kernel.org/tip/2fd59077755c44dbbd9b2fa89cf988235a3a6a2b Author: Paul E. McKenney AuthorDate: Wed, 4 Nov 2015 05:48:38 -0800 Committer: Ingo Molnar CommitDate: Mon, 9 Nov 2015 16:13:11 +0100 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 Reported-by: Peter Zijlstra Signed-off-by: Paul E. McKenney Signed-off-by: Peter Zijlstra (Intel) Cc: Arnaldo Carvalho de Melo Cc: Jiri Olsa Cc: Linus Torvalds Cc: Stephane Eranian Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/20151104134838.GR29027@linux.vnet.ibm.com Signed-off-by: Ingo Molnar --- kernel/events/core.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/kernel/events/core.c b/kernel/events/core.c index ea02109..f8e5c44 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -1050,13 +1050,13 @@ retry: /* * One of the few rules of preemptible RCU is that one cannot do * rcu_read_unlock() while holding a scheduler (or nested) lock when - * part of the read side critical section was preemptible -- see + * part of the read side critical section was irqs-enabled -- see * rcu_read_unlock_special(). * * Since ctx->lock nests under rq->lock we must ensure the entire read - * side critical section is non-preemptible. + * side critical section has interrupts disabled. */ - preempt_disable(); + local_irq_save(*flags); rcu_read_lock(); ctx = rcu_dereference(task->perf_event_ctxp[ctxn]); if (ctx) { @@ -1070,21 +1070,22 @@ retry: * if so. If we locked the right context, then it * can't get swapped on us any more. */ - raw_spin_lock_irqsave(&ctx->lock, *flags); + raw_spin_lock(&ctx->lock); if (ctx != rcu_dereference(task->perf_event_ctxp[ctxn])) { - raw_spin_unlock_irqrestore(&ctx->lock, *flags); + raw_spin_unlock(&ctx->lock); rcu_read_unlock(); - preempt_enable(); + local_irq_restore(*flags); goto retry; } if (!atomic_inc_not_zero(&ctx->refcount)) { - raw_spin_unlock_irqrestore(&ctx->lock, *flags); + raw_spin_unlock(&ctx->lock); ctx = NULL; } } rcu_read_unlock(); - preempt_enable(); + if (!ctx) + local_irq_restore(*flags); return ctx; }