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.

D.3. HIERARCHICAL RCU CODE WALKTHROUGH 207the leaf level is computed by dividing NR_CPUS byRCU_FANOUT, rounding up. The number of nodesat other levels is computed in a similar manner,but using (for example) RCU_FANOUT_SQ instead ofRCU_FANOUT.Line 28 then sums up all of the levels, resultingin the number of rcu_node structures plus the numberof rcu_data structures. Finally, line 29 subtractsNR_CPUS (which is the number of rcu_datastructures) from the sum, resulting in the numberof rcu_node structures, which is retained inNUM_RCU_NODES. This value is then used to size the->nodes array in the rcu_state structure.D.3.2 External InterfacesRCU’s external interfaces include not justthe standard RCU API, but also the internalinterfaces to the rest of the kernel thatare required for the RCU implementation itself.The interfaces are rcu_read_lock()),rcu_read_unlock()), rcu_read_lock_bh()),rcu_read_unlock_bh()), call_rcu() (which is awrapper around __call_rcu()), call_rcu_bh()(ditto), rcu_check_callbacks(), rcu_process_callbacks() (which is a wrapper around__rcu_process_callbacks(), rcu_pending()(which is a wrapper around __rcu_pending()),rcu_needs_cpu(), rcu_cpu_notify(), and__rcu_init(). Note that synchronize_rcu()and rcu_barrier() are common to all RCUimplementations, and are defined in terms ofcall_rcu(). Similarly, rcu_barrier_bh() iscommon to all RCU implementations and is definedin terms of call_rcu_bh().These external AP<strong>Is</strong> are each described in the followingsections.D.3.2.1 Read-Side Critical SectionsFigure D.21 shows the functions that demark RCUread-side critical sections. Lines 1-6 show __rcu_read_lock(), which begins an “rcu” read-side criticalsection. line 3 disables preemption, line 4 is asparse marker noting the beginning of an RCU readsidecriticalsection,andline5updateslockdepstate.Lines 8-13 show __rcu_read_unlock(), which isthe inverse of __rcu_read_lock(). Lines 15-20show __rcu_read_lock_bh() and lines 22-27 show__rcu_read_unlock_bh(), which are analogous tothe previous two functions, but disable and enablebottom-half processing rather than preemption.Quick Quiz D.27: I thought that RCU read-sideprocessing was supposed to be fast!!! The functions1 void __rcu_read_lock(void)2 {3 preempt_disable();4 __acquire(RCU);5 rcu_read_acquire();6 }78 void __rcu_read_unlock(void)9 {10 rcu_read_release();11 __release(RCU);12 preempt_enable();13 }1415 void __rcu_read_lock_bh(void)16 {17 local_bh_disable();18 __acquire(RCU_BH);19 rcu_read_acquire();20 }2122 void __rcu_read_unlock_bh(void)23 {24 rcu_read_release();25 __release(RCU_BH);26 local_bh_enable();27 }Figure D.21: RCU Read-Side Critical Sectionsshown in Figure D.21 have so much junk in themthat they just have to be slow!!! <strong>What</strong> gives here?D.3.2.2 call rcu()Figure D.22 shows the code for __call_rcu(),call_rcu(), and call_rcu_bh(). Note that call_rcu() and call_rcu_bh() are simple wrappers forcall_rcu(), and thus will not be considered furtherhere.Turningattentionto__call_rcu(), lines9-10initializethe specified rcu_head, and line 11 ensuresthat updates to RCU-protected data structures carriedout prior to invoking __call_rcu() are seenprior to callback registry. Lines 12 and 34 disableandre-enableinterruptstopreventdestructiveinterferenceby any calls to __call_rcu() from an interrupthandler. Line 13 obtains a reference to the currentCPU’srcu_data structure, line 14 invokesrcu_process_gp_end() in order to advance callbacks ifthecurrentgraceperiodhasnowended, whileline15invokes check_for_new_grace_period() to recordstate if a new grace period has started.Quick Quiz D.28: Why not simply use __get_cpu_var() to pick up a reference to the currentCPU’srcu_datastructureonline13inFigureD.22?Lines 16 and 17 enqueue the new callback. Lines18 and 19 check to see there is a grace periodin progress, and, if not, line 23 acquires the rootrcu_node structure’s lock and line 24 invokes rcu_

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

Saved successfully!

Ooh no, something went wrong!