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.4. PREEMPTABLE RCU 233Classic RCUcall_rcu()nextlist nexttailwaitlist waittaildonelist donetailPreemptible RCUcall_rcu()nextlist nexttailwaitlist[0] waittail[0]waitlist[1] waittail[1]rcu_read_unlock() rcu_read_lock()Grace Period Stage 0 Grace Period Stage 1CPU 0rcu_flipctr[0]"new""old"rcu_read_lock() rcu_read_unlock()CPU 0rcu_flipctr[0]"old"[1] [1]"new"rcu_process_callbacks()donelistdonetailFigure D.61: Preemptable RCU Counter Flip Operationrcu_process_callbacks()FigureD.60: Classicvs. PreemptableRCUCallbackProcessinggrace-period detection algorithm is required. Insteadofusingasinglewaitqueueofcallbacks(whichhas sufficed for earlier RCU implementations), thisimplementation uses an array of wait queues, sothat RCU callbacks are enqueued on each elementof this array in turn. This difference in callback flowis shown in Figure D.60 for a preemptible RCU implementationwith two waitlist stages per grace period(in contrast, the September 10 2007 patch to-rt [McK07c] uses four waitlist stages).Given two stages per grace period, any pair ofstages forms a full grace period. Similarly, in animplementation with four stages per grace period,any sequence of four stages would form a full graceperiod.To determine when a grace-period stage can end,preemptible RCU uses a per-CPU two-element rcu_flipctr array that tracks in-progress RCU readsidecritical sections. One element of a given CPU’srcu_flipctr array tracks old RCU read-side criticalsections, in other words, critical sections thatstarted before the current grace-period stage. Theother element tracks new RCU read-side criticalsections, namely those starting during the currentgrace-period stage. The array elements switch rolesat the beginning of each new grace-period stage, asshown in Figure D.61.During the first stage on the left-hand side of theabove figure, rcu_flipctr[0] tracks the new RCUread-side critical sections, and is therefore incrementedby rcu_read_lock() and decremented byrcu_read_unlock(). Similarly, rcu_flipctr[1]tracks the old RCU read-side critical sections (thosethat started during earlier stages), and is thereforedecremented by rcu_read_unlock() and never incrementedat all.Because each CPU’s old rcu_flipctr[1] elementsare never incremented, their sum across allCPUs must eventually go to zero, although preemptioninthemidst of anRCUread-sidecritical sectionmight cause any individual counter to remain nonzeroor even to go negative. For example, supposethat a task calls rcu_read_lock() on one CPU, ispreempted, resumes on another CPU, and then callsrcu_read_unlock(). The first CPU’s counter willthen be +1 and the second CPU’s counter will be-1, however, they will still sum to zero. Regardlessof possible preemption, when the sum of the oldcounterelementsdoesgotozero, itissafetomovetothe next grace-period stage, as shown on the righthandside of the above figure.In this second stage, the elements of each CPU’srcu_flipctr counter array switch roles. The rcu_flipctr[0] counter now tracks the old RCU readsidecritical sections, in other words, the ones thatstarted during grace period stage 0. Similarly, thercu_flipctr[1] counter now tracks the new RCUread-side critical sections that start in grace periodstage 1. Therefore, rcu_read_lock() now incrementsrcu_flipctr[1], while rcu_read_unlock()still might decrement either counter. Specifically,if the matching rcu_read_lock() executed duringgrace-period stage 0 (the old stage at this

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

Saved successfully!

Ooh no, something went wrong!