]> git.karo-electronics.de Git - karo-tx-linux.git/commit
rcu: Prevent initialization-time quiescent-state race
authorPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Mon, 17 Sep 2012 21:32:58 +0000 (14:32 -0700)
committerPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Mon, 17 Sep 2012 21:32:58 +0000 (14:32 -0700)
commit53b9b36cb0e85a8badc79e121ae61c31b730bb6c
treef9b2142d051c008b25cfd44c2647c71154c56502
parent2f275b9518f88a59ddee646947576db1e94ea125
rcu: Prevent initialization-time quiescent-state race

The next step in reducing RCU's grace-period initialization latency on
large systems will make this initialization preemptible.  Unfortunately,
making the grace-period initialization subject to interrupts (let alone
preemption) exposes the following race on systems whose rcu_node tree
contains more than one node:

1. CPU 31 starts initializing the grace period, including the
     first leaf rcu_node structures, and is then preempted.

2. CPU 0 refers to the first leaf rcu_node structure, and notes
     that a new grace period has started.  It passes through a
     quiescent state shortly thereafter, and informs the RCU core
     of this rite of passage.

3. CPU 0 enters an RCU read-side critical section, acquiring
     a pointer to an RCU-protected data item.

4. CPU 31 takes an interrupt whose handler removes the data item
referenced by CPU 0 from the data structure, and registers an
RCU callback in order to free it.

5. CPU 31 resumes initializing the grace period, including its
     own rcu_node structure.  In invokes rcu_start_gp_per_cpu(),
     which advances all callbacks, including the one registered
     in #4 above, to be handled by the current grace period.

6. The remaining CPUs pass through quiescent states and inform
     the RCU core, but CPU 0 remains in its RCU read-side critical
     section, still referencing the now-removed data item.

7. The grace period completes and all the callbacks are invoked,
     including the one that frees the data item that CPU 0 is still
     referencing.  Oops!!!

One way to avoid this race is to remove grace-period acceleration from
rcu_start_gp_per_cpu().  Now, the only reason for this acceleration was
to allow CPUs bringing RCU out of idle state to have their callbacks
invoked after only one grace period, rather than the two grace periods
that would otherwise be required.  But this acceleration does not
work when RCU grace-period initialization is moved to a kthread because
the CPU posting the callback is no longer necessarily the CPU that is
initializing the resulting grace period.

This commit therefore removes this now-pointless (and soon to be dangerous)
grace-period acceleration, thus avoiding the above race.

Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
kernel/rcutree.c