Skip to content

Commit 07325d4

Browse files
KAGA-KOKOIngo Molnar
authored andcommitted
rcu: Provide rcu_irq_exit_check_preempt()
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 <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Cc: Paul E. McKenney <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent aaf2bc5 commit 07325d4

File tree

3 files changed

+25
-0
lines changed

3 files changed

+25
-0
lines changed

include/linux/rcutiny.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ static inline void rcu_irq_exit_irqson(void) { }
7272
static inline void rcu_irq_enter_irqson(void) { }
7373
static inline void rcu_irq_exit(void) { }
7474
static inline void rcu_irq_exit_preempt(void) { }
75+
static inline void rcu_irq_exit_check_preempt(void) { }
7576
static inline void exit_rcu(void) { }
7677
static inline bool rcu_preempt_need_deferred_qs(struct task_struct *t)
7778
{

include/linux/rcutree.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,12 @@ void rcu_irq_exit_preempt(void);
5151
void rcu_irq_enter_irqson(void);
5252
void rcu_irq_exit_irqson(void);
5353

54+
#ifdef CONFIG_PROVE_RCU
55+
void rcu_irq_exit_check_preempt(void);
56+
#else
57+
static inline void rcu_irq_exit_check_preempt(void) { }
58+
#endif
59+
5460
void exit_rcu(void);
5561

5662
void rcu_scheduler_starting(void);

kernel/rcu/tree.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,24 @@ void rcu_irq_exit_preempt(void)
765765
"RCU in extended quiescent state!");
766766
}
767767

768+
#ifdef CONFIG_PROVE_RCU
769+
/**
770+
* rcu_irq_exit_check_preempt - Validate that scheduling is possible
771+
*/
772+
void rcu_irq_exit_check_preempt(void)
773+
{
774+
lockdep_assert_irqs_disabled();
775+
776+
RCU_LOCKDEP_WARN(__this_cpu_read(rcu_data.dynticks_nesting) <= 0,
777+
"RCU dynticks_nesting counter underflow/zero!");
778+
RCU_LOCKDEP_WARN(__this_cpu_read(rcu_data.dynticks_nmi_nesting) !=
779+
DYNTICK_IRQ_NONIDLE,
780+
"Bad RCU dynticks_nmi_nesting counter\n");
781+
RCU_LOCKDEP_WARN(rcu_dynticks_curr_cpu_in_eqs(),
782+
"RCU in extended quiescent state!");
783+
}
784+
#endif /* #ifdef CONFIG_PROVE_RCU */
785+
768786
/*
769787
* Wrapper for rcu_irq_exit() where interrupts are enabled.
770788
*

0 commit comments

Comments
 (0)