aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-06-28 15:45:23 -0400
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>2018-08-30 19:02:36 -0400
commite11ec65cc8d63c41fc468363b65826a5ae4b8c66 (patch)
treecf8fc0b086e673a109889d308e906722d5d22c77 /kernel
parentfcc878e4dfb70128a73857c609d70570629b0d9e (diff)
rcu: Add warning to detect half-interrupts
RCU's dyntick-idle code is written to tolerate half-interrupts, that it, either an interrupt that invokes rcu_irq_enter() but never invokes the corresponding rcu_irq_exit() on the one hand, or an interrupt that never invokes rcu_irq_enter() but does invoke the "corresponding" rcu_irq_exit() on the other. These things really did happen at one time, as evidenced by this ca-2011 LKML post: http://lkml.kernel.org/r/20111014170019.GE2428@linux.vnet.ibm.com The reason why RCU tolerates half-interrupts is that usermode helpers used exceptions to invoke a system call from within the kernel such that the system call did a normal return (not a return from exception) to the calling context. This caused rcu_irq_enter() to be invoked without a matching rcu_irq_exit(). However, usermode helpers have since been rewritten to make much more housebroken use of workqueues, kernel threads, and do_execve(), and therefore should no longer produce half-interrupts. No one knows of any other source of half-interrupts, but then again, no one seems insane enough to go audit the entire kernel to verify that half-interrupts really are a relic of the past. This commit therefore adds a pair of WARN_ON_ONCE() calls that will trigger in the presence of half interrupts, which the code will continue to handle correctly. If neither of these WARN_ON_ONCE() trigger by mid-2021, then perhaps RCU can stop handling half-interrupts, which would be a considerable simplification. Reported-by: Steven Rostedt <rostedt@goodmis.org> Reported-by: Joel Fernandes <joel@joelfernandes.org> Reported-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/rcu/tree.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index 346624716d6e..0b42249e2e40 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -714,6 +714,7 @@ static void rcu_eqs_enter(bool user)
714 struct rcu_dynticks *rdtp; 714 struct rcu_dynticks *rdtp;
715 715
716 rdtp = this_cpu_ptr(&rcu_dynticks); 716 rdtp = this_cpu_ptr(&rcu_dynticks);
717 WARN_ON_ONCE(rdtp->dynticks_nmi_nesting != DYNTICK_IRQ_NONIDLE);
717 WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0); 718 WRITE_ONCE(rdtp->dynticks_nmi_nesting, 0);
718 WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && 719 WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) &&
719 rdtp->dynticks_nesting == 0); 720 rdtp->dynticks_nesting == 0);
@@ -896,6 +897,7 @@ static void rcu_eqs_exit(bool user)
896 trace_rcu_dyntick(TPS("End"), rdtp->dynticks_nesting, 1, rdtp->dynticks); 897 trace_rcu_dyntick(TPS("End"), rdtp->dynticks_nesting, 1, rdtp->dynticks);
897 WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !user && !is_idle_task(current)); 898 WARN_ON_ONCE(IS_ENABLED(CONFIG_RCU_EQS_DEBUG) && !user && !is_idle_task(current));
898 WRITE_ONCE(rdtp->dynticks_nesting, 1); 899 WRITE_ONCE(rdtp->dynticks_nesting, 1);
900 WARN_ON_ONCE(rdtp->dynticks_nmi_nesting);
899 WRITE_ONCE(rdtp->dynticks_nmi_nesting, DYNTICK_IRQ_NONIDLE); 901 WRITE_ONCE(rdtp->dynticks_nmi_nesting, DYNTICK_IRQ_NONIDLE);
900} 902}
901 903