diff options
Diffstat (limited to 'patches/rcutorture__Avoid_problematic_critical_section_nesting_on_RT.patch')
-rw-r--r-- | patches/rcutorture__Avoid_problematic_critical_section_nesting_on_RT.patch | 43 |
1 files changed, 14 insertions, 29 deletions
diff --git a/patches/rcutorture__Avoid_problematic_critical_section_nesting_on_RT.patch b/patches/rcutorture__Avoid_problematic_critical_section_nesting_on_RT.patch index 55c7406a11d7..852b23cfed8d 100644 --- a/patches/rcutorture__Avoid_problematic_critical_section_nesting_on_RT.patch +++ b/patches/rcutorture__Avoid_problematic_critical_section_nesting_on_RT.patch @@ -7,19 +7,7 @@ From: Scott Wood <swood@redhat.com> rcutorture was generating some nesting scenarios that are not reasonable. Constrain the state selection to avoid them. -Example #1: - -1. preempt_disable() -2. local_bh_disable() -3. preempt_enable() -4. local_bh_enable() - -On PREEMPT_RT, BH disabling takes a local lock only when called in -non-atomic context. Thus, atomic context must be retained until after BH -is re-enabled. Likewise, if BH is initially disabled in non-atomic -context, it cannot be re-enabled in atomic context. - -Example #2: +Example: 1. rcu_read_lock() 2. local_irq_disable() @@ -36,13 +24,13 @@ kernels, until debug checks are added to ensure that they are not happening elsewhere. Signed-off-by: Scott Wood <swood@redhat.com> +[valentin.schneider@arm.com: Don't disable BH in atomic context] +[bigeasy: remove 'preempt_disable(); local_bh_disable(); preempt_enable(); + local_bh_enable();' from the examples because this works on RT now. ] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> -Signed-off-by: Thomas Gleixner <tglx@linutronix.de> - - --- - kernel/rcu/rcutorture.c | 97 +++++++++++++++++++++++++++++++++++++++++------- - 1 file changed, 83 insertions(+), 14 deletions(-) + kernel/rcu/rcutorture.c | 94 ++++++++++++++++++++++++++++++++++++++++-------- + 1 file changed, 80 insertions(+), 14 deletions(-) --- --- a/kernel/rcu/rcutorture.c +++ b/kernel/rcu/rcutorture.c @@ -136,7 +124,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> WARN_ON_ONCE(mask >> RCUTORTURE_RDR_SHIFT); /* Mostly only one bit (need preemption!), sometimes lots of bits. */ -@@ -1503,11 +1534,49 @@ rcutorture_extend_mask(int oldmask, stru +@@ -1503,11 +1534,46 @@ rcutorture_extend_mask(int oldmask, stru mask = mask & randmask2; else mask = mask & (1 << (randmask2 % RCUTORTURE_RDR_NBITS)); @@ -160,6 +148,13 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + */ + if (IS_ENABLED(CONFIG_PREEMPT_RT)) { + /* ++ * Can't disable bh in atomic context if bh was already ++ * disabled by another task on the same CPU. Instead of ++ * attempting to track this, just avoid disabling bh in atomic ++ * context. ++ */ ++ mask &= ~atomic_bhs; ++ /* + * Can't release the outermost rcu lock in an irq disabled + * section without preemption also being disabled, if irqs + * had ever been enabled during this RCU critical section @@ -170,16 +165,6 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de> + !(mask & preempts)) + mask |= RCUTORTURE_RDR_RCU; + -+ /* Can't modify atomic bh in non-atomic context */ -+ if ((oldmask & atomic_bhs) && (mask & atomic_bhs) && -+ !(mask & preempts_irq)) { -+ mask |= oldmask & preempts_irq; -+ if (mask & RCUTORTURE_RDR_IRQ) -+ mask |= oldmask & tmp; -+ } -+ if ((mask & atomic_bhs) && !(mask & preempts_irq)) -+ mask |= RCUTORTURE_RDR_PREEMPT; -+ + /* Can't modify non-atomic bh in atomic context */ + tmp = nonatomic_bhs; + if (oldmask & preempts_irq) |