]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
rcu: Provide rcu_irq_exit_check_preempt()
authorThomas Gleixner <tglx@linutronix.de>
Thu, 21 May 2020 20:05:16 +0000 (22:05 +0200)
committerIngo Molnar <mingo@kernel.org>
Tue, 26 May 2020 17:05:11 +0000 (19:05 +0200)
Provide a debug check which can be invoked from exception return to kernel
mode before an attempt is made to schedule. Warn if RCU is not ready for
this.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Paul E. McKenney <paulmck@kernel.org>
Link: https://lore.kernel.org/r/20200521202117.089709607@linutronix.de
include/linux/rcutiny.h
include/linux/rcutree.h
kernel/rcu/tree.c

index c869fb20cc510143180d5f1c0fd6751e0242574f..8512caeb768226be38de353f6524e36f93ccc7e3 100644 (file)
@@ -72,6 +72,7 @@ static inline void rcu_irq_exit_irqson(void) { }
 static inline void rcu_irq_enter_irqson(void) { }
 static inline void rcu_irq_exit(void) { }
 static inline void rcu_irq_exit_preempt(void) { }
+static inline void rcu_irq_exit_check_preempt(void) { }
 static inline void exit_rcu(void) { }
 static inline bool rcu_preempt_need_deferred_qs(struct task_struct *t)
 {
index 9366fa4d0717b9fde41358f8e5cf8dc7adcb0205..d5cc9d6759879465776a5478c72c326520d25656 100644 (file)
@@ -51,6 +51,12 @@ void rcu_irq_exit_preempt(void);
 void rcu_irq_enter_irqson(void);
 void rcu_irq_exit_irqson(void);
 
+#ifdef CONFIG_PROVE_RCU
+void rcu_irq_exit_check_preempt(void);
+#else
+static inline void rcu_irq_exit_check_preempt(void) { }
+#endif
+
 void exit_rcu(void);
 
 void rcu_scheduler_starting(void);
index b7f8c494d1d16e3b2ce51bee90bfb45eb792519b..d8e9dbbefcfae03c321f0749ce6379ca1f5bd9d3 100644 (file)
@@ -765,6 +765,24 @@ void rcu_irq_exit_preempt(void)
                         "RCU in extended quiescent state!");
 }
 
+#ifdef CONFIG_PROVE_RCU
+/**
+ * rcu_irq_exit_check_preempt - Validate that scheduling is possible
+ */
+void rcu_irq_exit_check_preempt(void)
+{
+       lockdep_assert_irqs_disabled();
+
+       RCU_LOCKDEP_WARN(__this_cpu_read(rcu_data.dynticks_nesting) <= 0,
+                        "RCU dynticks_nesting counter underflow/zero!");
+       RCU_LOCKDEP_WARN(__this_cpu_read(rcu_data.dynticks_nmi_nesting) !=
+                        DYNTICK_IRQ_NONIDLE,
+                        "Bad RCU  dynticks_nmi_nesting counter\n");
+       RCU_LOCKDEP_WARN(rcu_dynticks_curr_cpu_in_eqs(),
+                        "RCU in extended quiescent state!");
+}
+#endif /* #ifdef CONFIG_PROVE_RCU */
+
 /*
  * Wrapper for rcu_irq_exit() where interrupts are enabled.
  *