The code implementing srcu_read_lock() is shown in
Figure .
This function has been carefully constructed to avoid the
need for memory barriers and atomic instructions.
Lines 5 and 11 disable and re-enable preemption, in order to force the sequence of code to execute unpreempted on a single CPU. Line 6 picks up the bottom bit of the grace-period counter, which will be used to select which rank of per-CPU counters is to be used for this SRCU read-side critical section. The barrier() call on line 7 is a directive to the compiler that ensures that the index is fetched but once,D.2so that the index used on line 9 is the same one returned on line 12. Lines 8-9 increment the selected counter for the current CPU.D.3Line 10 forces subsequent execution to occur after lines 8-9, in order to prevent to misordering of any code in a non-CONFIG_PREEMPT build, but only from the perspective of an intervening interrupt handler. However, in a CONFIG_PREEMPT kernel, the required barrier() call is embedded in the preempt_enable() on line 11, so the srcu_barrier() is a no-op in that case. Finally, line 12 returns the index so that it may be passed in to the corresponding srcu_read_unlock().
The code for srcu_read_unlock() is shown in
Figure .
Again, lines 3 and 7 disable and re-enable preemption so that the
whole code sequence executes unpreempted on a single CPU.
In CONFIG_PREEMPT kernels, the preempt_disable() on line 3
contains a barrier() primitive, otherwise, the barrier()
is supplied by line 4.
Again, this directive forces the subsequent code to execute after
the critical section from the perspective of intervening
interrupt handlers.
Lines 5 and 6 decrement the counter for this CPU, but with the same
index as was used by the corresponding srcu_read_lock().
The key point is that a given CPU's counters can be observed by other CPUs only in cooperation with that CPU's interrupt handlers. These interrupt handlers are responsible for ensuring that any needed memory barriers are executed prior to observing the counters.
Paul E. McKenney 2011-12-16