10.07.2015 Views

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

Is Parallel Programming Hard, And, If So, What Can You Do About It?

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

D.3. HIERARCHICAL RCU CODE WALKTHROUGH 2251 static int2 dyntick_save_progress_counter(struct rcu_data *rdp)3 {4 int ret;5 int snap;6 int snap_nmi;78 snap = rdp->dynticks->dynticks;9 snap_nmi = rdp->dynticks->dynticks_nmi;10 smp_mb();11 rdp->dynticks_snap = snap;12 rdp->dynticks_nmi_snap = snap_nmi;13 ret = ((snap & 0x1) == 0) && ((snap_nmi & 0x1) == 0);14 if (ret)15 rdp->dynticks_fqs++;16 return ret;17 }Figure D.47: Code fordyntick save progress counter()Line16ofrcu_irq_exit()doestheby-nowtraditionalacquisition of a reference to the currently runningCPU’s rcu_dynticks structure. Line 17 decrementsthe ->dynticks_nesting field, and, if the resultis non-zero (in other words, RCU must still payattention to this CPU despite exiting this interrupthandler), then line 18 silently returns. Otherwise,line 19 executes a memory barrier so that any RCUread-side critical sections that might have been inthe interrupt handler are seen by all CPUs as havinghappened before the increment on line 20 of the->dynticks field (which must now have an evennumberedvalue). Lines 21 and 22 check to see if theinterrupt handler posted any “rcu” or “rcu bh” callbacks,and, if so, line 23 forces this CPU to reschedule,which has the side-effect of forcing it out ofdynticks-idle mode, as is required to allow RCU tohandle the grace period required by these callbacks.D.3.7.4 Checking for Dyntick-Idle ModeThe dyntick_save_progress_counter() and rcu_implicit_dynticks_qs() functions are used tocheck whether a CPU is in dynticks-idle mode. Thedyntick_save_progress_counter() function is invokedfirst, and returns non-zero if the CPU is currentlyin dynticks-idle mode. <strong>If</strong> the CPU was not indynticks-idle mode, for example, because it is currentlyhandling an interrupt or NMI, then the rcu_implicit_dynticks_qs() function is called somejiffies later. This function looks at the current statein conjunction with state stored away by the earliercall to dyntick_save_progress_counter(), againreturning non-zero if the CPU either is in dynticksidlemodeorwasindynticks-idlemodeduringtheinterveningtime. Thercu_implicit_dynticks_qs()function may be invoked repeatedly, if need be, untilis returns true.1 static int2 rcu_implicit_dynticks_qs(struct rcu_data *rdp)3 {4 long curr;5 long curr_nmi;6 long snap;7 long snap_nmi;89 curr = rdp->dynticks->dynticks;10 snap = rdp->dynticks_snap;11 curr_nmi = rdp->dynticks->dynticks_nmi;12 snap_nmi = rdp->dynticks_nmi_snap;13 smp_mb();14 if ((curr != snap || (curr & 0x1) == 0) &&15 (curr_nmi != snap_nmi || (curr_nmi & 0x1) == 0)) {16 rdp->dynticks_fqs++;17 return 1;18 }19 return rcu_implicit_offline_qs(rdp);20 }Figure D.48: Code forrcu implicit dynticks qs()Figure D.47 shows the code for dyntick_save_progress_counter(), which is passed a given CPUrcu_statepair’s rcu_data structure. Lines 8 and9 take snapshots of the CPU’s rcu_dynticks structure’s->dynticks and ->dynticks_nmi fields, andthen line 10 executes a memory barrier to ensurethat the snapshot is seen by all CPUs tohave happened before any later processing dependingon these values. This memory barrier pairsup with those in rcu_enter_nohz(), rcu_exit_nohz(), rcu_nmi_enter(), rcu_nmi_exit(), rcu_irq_enter(), and rcu_irq_exit(). Lines 11 and12 store these two snapshots away so that theycan be accessed by a later call to rcu_implicit_dynticks_qs(). Line 13 checks to see if both snapshotshave even-numbered values, indicating thatthe CPU in question was in neither non-idle processstate, an interrupt handler, nor an NMI handler. <strong>If</strong>so, lines 14 and 15 increment the statistical counter->dynticks_fqs, which is used only for tracing. Eitherway, line 16 returns the indication of whetherthe CPU was in dynticks-idle mode.Quick Quiz D.52: Why isn’t there a memorybarrier between lines 8 and 9 of Figure D.47?Couldn’t this cause the code to fetch even-numberedvalues from both the ->dynticks and ->dynticks_nmi fields, even though these two fields never werezero at the same time?Figure D.48 shows the code for rcu_implicit_dynticks_qs(). Lines 9-12 pick up both new valuesfor the CPU’s rcu_dynticks structure’s ->dynticks and ->dynticks_nmi fields, as well as thesnapshots taken by the last call to dyntick_save_progress_counter(). Line 13 then executes amemory barrier to ensure that the values are seen by

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!