D.3.8.3 Scanning for Holdout CPUs

Figure: Scanning for Holdout CPUs
\begin{figure}{ \scriptsize
\begin{verbatim}1 static int
2 rcu_process_dynti...
...(&rnp_cur->lock, flags);
38 }
39 return 0;
40 }\end{verbatim}
}\end{figure}

Figure: Scanning Leaf rcu_node Structures
\resizebox{6in}{!}{\includegraphics{appendix/rcuimpl/RCUTreeLeafScan}}

Figure [*] shows the code for rcu_process_dyntick(), which scans the leaf rcu_node structures in search of holdout CPUs, as illustrated by the blue arrow in Figure [*]. It invokes the function passed in through argument f on each such CPU's rcu_data structure, and returns non-zero if the grace period specified by the lastcomp argument has ended.

Lines 13 and 14 acquire references to the first and the last leaf rcu_node structures, respectively. Each pass through the loop spanning lines 15-38 processes one of the leaf rcu_node structures.

Line 16 sets the local variable mask to zero. This variable will be used to accumulate the CPUs within the current leaf rcu_node structure that are in extended quiescent states, and can thus be reported as such. Line 17 acquires the current leaf rcu_node structure's lock, and line 18 checks to see if the current grace period has completed, and, if so, line 19 releases the lock and line 20 returns non-zero. Otherwise, line 22 checks for holdout CPUs associated with this rcu_node structure, and, if there are none, line 23 releases the lock and line 24 restarts the loop from the beginning on the next lead rcu_node structure.

Execution reaches line 26 if there is at least one holdout CPU associated with this rcu_node structure. Lines 26 and 27 set local variables cpu and bit to reference the lowest-numbered CPU associated with this rcu_node structure. Each pass through the loop spanning lines 28-32 checks one of the CPUs associated with the current rcu_node structure. Line 29 checks to see if the this CPU is still holding out or if it has already passed through a quiescent state. If it is still a holdout, line 30 invokes the specified function (either dyntick_save_progress_counter() or rcu_implicit_dynticks_qs(), as specified by the caller), and if that function returns non-zero (indicating that the current CPU is in an extended quiescent state), then line 31 sets the current CPU's bit in mask.

Line 33 then checks to see if any CPUs were identified as being in extended quiescent states and if the current grace period is still in force, and, if so, line 34 invokes cpu_quiet_msk() to report that the grace period need no longer wait for those CPUs and then line 35 restarts the loop with the next rcu_node structure. (Note that cpu_quiet_msk() releases the current rcu_node structure's lock, and might well end the current grace period.) Otherwise, if all holdout CPUs really are still holding out, line 37 releases the current rcu_node structure's lock.

Once all of the leaf rcu_node structures have been processed, the loop exits, and line 39 returns zero to indicate that the current grace period is still in full force. (Recall that line 20 returns non-zero should the current grace period come to an end.)

Paul E. McKenney 2011-12-16