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

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

204 APPENDIX D. READ-COPY UPDATE IMPLEMENTATIONSthe size of the level array is thus specified byNUM_RCU_LVLS, which is computed as describedin Section D.3.1.5. The ->level field is oftenused in combination with ->node to scana level of the rcu_node hierarchy, for example,all of the leaf nodes. The elements of ->levelare filled in by the boot-time rcu_init_one()function.levelcnt: Thisfieldisanarraycontainingthenumberof rcu_node structures in each level of thehierarchy, including the number of rcu_datastructures referencing the leaf rcu_node structures,so that this array has one more elementthan does the ->level array. Note that->levelcnt[0] will always contain a value ofone, corresponding to the single root rcu_nodeat the top of the hierarchy. This array is initializedwith the values NUM_RCU_LVL_0, NUM_RCU_LVL_1, NUM_RCU_LVL_2, and NUM_RCU_LVL_3,which are C-preprocessor macros computed asdescribed in Section D.3.1.5. The ->levelcntfield is used to initialize other parts of the hierarchyand for debugging purposes.levelspread: Each element of this field containsthe desired number of children for thecorresponding level of the rcu_node hierarchy.This array’s element’s values are computedat runtime by one of the two rcu_init_levelspread() functions, selected by theCONFIG_RCU_FANOUT_EXACT kernel parameter.rda: Each element of this field contains a pointer tothe corresponding CPU’s rcu_data structure.ThisarrayisinitializedatboottimebytheRCU_DATA_PTR_INIT() macro.signaled: This field is used to maintain state usedby the force_quiescent_state() function, asdescribed in Section D.3.8. This field takes onvalues as follows:RCU_GP_INIT: This value indicates that thecurrent grace period is still in the processof being initialized, so that force_quiescent_state() should take no action.Of course, grace-period initializationwould need to stretch out for three jiffiesbefore this race could arise, but if you havea very large number of CPUs, this racecould in fact occur. Once grace-period initializationis complete, this value is set toeither RCU_SAVE_DYNTICK (if CONFIG_NO_HZ) or RCU_FORCE_QS otherwise.RCU_SAVE_DYNTICK: This value indicates thatforce_quiescent_state() should checkthe dynticks state of any CPUs that havenot yet reported quiescent states for thecurrent grace period. Quiescent states willbe reported on behalf of any CPUs thatare in dyntick-idle mode.RCU_FORCE_QS: This value indicates thatforce_quiescent_state() shouldrecheck dynticks state along with theonline/offline state of any CPUs that havenot yet reported quiescent states for thecurrent grace period. The rechecking ofdynticks states allows the implementationto handle cases where a given CPU mightbe in dynticks-idle state, but have been inan irq or NMI handler both times it waschecked. <strong>If</strong> all else fails, a reschedule IPIwill be sent to the laggart CPU.This field is guarded by the root rcu_nodestructure’s lock.Quick Quiz D.26: <strong>So</strong> what guards the earlierfields in this structure?gpnum: Thisfieldcontains thenumberofthecurrentgrace period, or that of the last grace periodif no grace period is currently in effect. Thisfield is guarded by the root rcu_node structure’slock,butisfrequentlyaccessed(butnevermodified) without holding this lock.completed: This field contains the number of thelast completed grace period. As such, it is equalto ->gpnum when there is no grace period inprogress, or one less than ->gpnum when thereis a grace period in progress. In principle, onecould replace this pair of fields with a singleboolean, as is done in Classic RCU in some versionsof Linux, but in practice race resolution ismuch simpler given the pair of numbers. Thisfield is guarded by the root rcu_node structure’slock,butisfrequentlyaccessed(butnevermodified) without holding this lock.onofflock: This field prevents online/offline processingfrom running concurrently with graceperiodinitialization. There is one exception tothis: if the rcu_node hierarchy consists of buta single structure, then that single structure’s->lock field will instead take on this job.fqslock: This field prevents more than one taskfrom forcing quiescent states with force_quiescent_state().

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

Saved successfully!

Ooh no, something went wrong!