Messages in this thread Patch in this message | | | Date | Mon, 21 Apr 2008 17:46:45 -0700 | From | "Paul E. McKenney" <> | Subject | [PATCH 2/5] Add memory barriers and comments to rcu_check_callbacks() |
| |
Add comments to the logic that infers quiescent states when interrupting from either user mode or the idle loop. Also add a memory barrier: it appears that James Huang was in fact onto something, as the scheduler is much less synchronization-happy than it once was, so we can no longer rely on its memory barriers in all cases.
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Reported-by: James Huang <jamesclhuang@yahoo.com> ---
rcuclassic.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-)
diff -urpNa -X dontdiff linux-2.6.25-C1-call_rcu_sched/kernel/rcuclassic.c linux-2.6.25-C2-rcuclassic-fixes/kernel/rcuclassic.c --- linux-2.6.25-C1-call_rcu_sched/kernel/rcuclassic.c 2008-04-16 19:49:44.000000000 -0700 +++ linux-2.6.25-C2-rcuclassic-fixes/kernel/rcuclassic.c 2008-04-21 10:50:12.000000000 -0700 @@ -502,10 +502,38 @@ void rcu_check_callbacks(int cpu, int us if (user || (idle_cpu(cpu) && !in_softirq() && hardirq_count() <= (1 << HARDIRQ_SHIFT))) { + + /* + * Get here if this CPU took its interrupt from user + * mode or from the idle loop, and if this is not a + * nested interrupt. In this case, the CPU is in + * a quiescent state, so count it. + * + * Also do a memory barrier. This is needed to handle + * the case where writes from a preempt-disable section + * of code get reordered into schedule() by this CPU's + * write buffer. The memory barrier makes sure that + * the rcu_qsctr_inc() and rcu_bh_qsctr_inc() are see + * by other CPUs to happen after any such write. + */ + + smp_mb(); /* See above block comment. */ rcu_qsctr_inc(cpu); rcu_bh_qsctr_inc(cpu); - } else if (!in_softirq()) + + } else if (!in_softirq()) { + + /* + * Get here if this CPU did not take its interrupt from + * softirq, in other words, if it is not interrupting + * a rcu_bh read-side critical section. This is an _bh + * critical section, so count it. The memory barrier + * is needed for the same reason as is the above one. + */ + + smp_mb(); /* See above block comment. */ rcu_bh_qsctr_inc(cpu); + } raise_rcu_softirq(); }
| |