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.2. HIERARCHICAL RCU OVERVIEW 195Quick Quiz D.12: <strong>And</strong> what happens if allCPUs try to report going through a quiescent statebefore the bit-setting CPU has finished, thus endingthe new grace period before it starts?D.2.7.2 Pass Through a Quiescent StateThe rcu and rcu bh flavors of RCU have differentsets of quiescent states. Quiescent states for rcu arecontextswitch, idle(eitherdynticksortheidleloop),and user-mode execution, while quiescent states forrcu bhareanycodeoutsideofsoftirqwithinterruptsenabled. Notethatanquiescentstateforrcuisalsoaquiescent state for rcu bh. Quiescent states for rcuare recorded by invoking rcu_qsctr_inc(), whilequiescent states for rcu bh are recorded by invokingrcu_bh_qsctr_inc(). These two functions recordtheir state in the current CPU’srcu_data structure.These functions are invoked from the scheduler,from __do_softirq(), and from rcu_check_callbacks(). This latter function is invokedfrom the scheduling-clock interrupt, and analyzesstate to determine whether this interrupt occurredwithin a quiescent state, invoking rcu_qsctr_inc()and/or rcu_bh_qsctr_inc(), as appropriate. <strong>It</strong>also raises RCU_SOFTIRQ, which results in rcu_process_callbacks() being invoked on the currentCPU at some later time from softirq context.D.2.7.3 Announce a Quiescent State toRCUThe afore-mentioned rcu_process_callbacks()function has several duties:1. Determining when to take measures to end anover-long grace period (via force_quiescent_state()).2. Taking appropriate action when some otherCPU detected the end of a grace period (viarcu_process_gp_end()). “Appropriate action“includes advancing this CPU’s callbacksand recording the new grace period. This samefunctionupdatesstateinresponsetosomeotherCPU starting a new grace period.3. Reporting the current CPU’s quiescent statesto the core RCU mechanism (via rcu_check_quiescent_state(), which in turn invokescpu_quiet()). This of course might mark theend of the current grace period.4. Starting a new grace period if there is no graceperiod in progress and this CPU has RCU callbacksstill waiting for a grace period (via cpu_needs_another_gp() and rcu_start_gp()).5. Invoking any of this CPU’s callbacks whosegrace period has ended (via rcu_do_batch()).Theseinteractionsarecarefullyorchestratedinorderto avoid buggy behavior such as reporting a quiescentstate from the previous grace period againstthe current grace period.D.2.7.4 Enter and Leave Dynticks IdleModeThe scheduler invokes rcu_enter_nohz() to enterdynticks-idle mode, and invokes rcu_exit_nohz()to exit it. The rcu_enter_nohz() function incrementsa per-CPU dynticks_nesting variableand also a per-CPU dynticks counter, the latterof which which must then have an even-numberedvalue. The rcu_exit_nohz() function decrementsthissameper-CPUdynticks_nestingvariable, andagain increments the per-CPU dynticks counter,the latter of which must then have an odd-numberedvalue.The dynticks counter can be sampled by otherCPUs. <strong>If</strong> the value is even, the first CPU is in anextended quiescent state. Similarly, if the countervalue changes during a given grace period, the firstCPU must have been in an extended quiescent stateat some point during the grace period. However,there is another dynticks_nmi per-CPU variablethat must also be sampled, as will be discussed below.D.2.7.5 Interrupt from Dynticks Idle ModeInterrupts from dynticks idle mode are handledby rcu_irq_enter() and rcu_irq_exit(). Thercu_irq_enter() function increments the per-CPUdynticks_nesting variable, and, if the prior valuewas zero, also increments the dynticks per-CPUvariable (which must then have an odd-numberedvalue).The rcu_irq_exit() function decrements theper-CPU dynticks_nesting variable, and, if thenew value is zero, also increments the dynticksper-CPU variable (which must then have an evennumberedvalue).Note that entering an irq handler exits dynticksidle mode and vice versa. This enter/exit anticorrespondencecan cause much confusion. <strong>You</strong> havebeen warned.D.2.7.6 NMI from Dynticks Idle ModeNM<strong>Is</strong> from dynticks idle mode are handled by rcu_nmi_enter() and rcu_nmi_exit(). These functionsbothincrementthedynticks_nmicounter,but

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

Saved successfully!

Ooh no, something went wrong!