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.

90 CHAPTER 8. DEFERRED PROCESSINGLines 7-16 define the nmi_profile() function,which is called from within an NMI handler. Assuch, it cannot be preempted, nor can it be interruptedby a normal irq handler, however, it is stillsubject to delays due to cache misses, ECC errors,and cycle stealing by other hardware threads withinthe same core. Line 9 gets a local pointer to the profilebufferusingthercu_dereference()primitivetoensurememoryorderingonDECAlpha, andlines11and 12 exit from this function if there is no profilebuffer currently allocated, while lines 13 and 14 exitfrom this function if the pcvalue argument is outof range. Otherwise, line 15 increments the profilebufferentryindexedbythepcvalueargument.Notethat storing the size with the buffer guarantees thatthe range check matches the buffer, even if a largebuffer is suddenly replaced by a smaller one.Lines 18-27 define the nmi_stop() function,where the caller is responsible for mutual exclusion(for example, holding the correct lock). Line 20fetches a pointer to the profile buffer, and lines 22and 23 exit the function if there is no buffer.Otherwise, line 24 NULLs out the profile-bufferpointer (using the rcu_assign_pointer() primitiveto maintain memory ordering on weakly orderedmachines),andline25waitsforanRCUSchedgrace period to elapse, in particular, waiting forall non-preemptible regions of code, including NMIhandlers, to complete. Once execution continuesat line 26, we are guaranteed that any instance ofnmi_profile() that obtained a pointer to the oldbuffer has returned. <strong>It</strong> is therefore safe to free thebuffer, in this case using the kfree() primitive.Quick Quiz 8.21: Suppose that the nmi_profile() function was preemptible. <strong>What</strong> wouldneedtochangetomakethisexampleworkcorrectly?Inshort, RCUmakesiteasytodynamicallyswitchamong profile buffers (you just try doing this efficientlywith atomic operations, or at all with locking!).However, RCU is normally used at a higherlevel of abstraction, as was shown in the previoussections.8.3.2.8 RCU Usage SummaryAt its core, RCU is nothing more nor less than anAPI that provides:1. a publish-subscribe mechanism for adding newdata,2. a way of waiting for pre-existing RCU readersto finish, and3. a discipline of maintaining multiple versions topermit change without harming or unduly delayingconcurrent RCU readers.That said, it is possible to build higher-level constructson top of RCU, including the reader-writerlocking,reference-counting, and existence-guaranteeconstructs listed in the earlier sections. Furthermore,I have no doubt that the Linux communitywill continue to find interesting new uses for RCU,as well as for any of a number of other synchronizationprimitives.8.3.3 RCU Linux-Kernel APIThis section looks at RCU from the viewpoint ofits Linux-kernel API. Section 8.3.3.1 presents RCU’swait-to-finish AP<strong>Is</strong>, and Section 8.3.3.2 presentsRCU’s publish-subscribe and version-maintenanceAP<strong>Is</strong>. Finally, Section 8.3.3.4 presents concludingremarks.8.3.3.1 RCU has a Family of Wait-to-FinishAP<strong>Is</strong>The most straightforward answer to “what is RCU”is that RCU is an API used in the Linux kernel, assummarized by Tables 8.4 and 8.5, which shows thewait-for-RCU-readers portions of the non-sleepableand sleepable AP<strong>Is</strong>, respectively, and by Table 8.6,which shows the publish/subscribe portions of theAPI.<strong>If</strong> you are new to RCU, you might consider focusingon just one of the columns in Table 8.4, each ofwhich summarizes one member of the Linux kernel’sRCU API family.. For example, if you are primarilyinterested in understanding how RCU is used in theLinux kernel, “RCU Classic” would be the place tostart, as it is used most frequently. On the otherhand, if you want to understand RCU for its ownsake, “SRCU” has the simplest API. <strong>You</strong> can alwayscome back for the other columns later.<strong>If</strong> you are already familiar with RCU, these tablescan serve as a useful reference.Quick Quiz 8.22: Why do some of the cells inTable 8.4 have exclamation marks (“!”)?The “RCU Classic” column corresponds to theoriginal RCU implementation, in which RCU readsidecritical sections are delimited by rcu_read_lock() and rcu_read_unlock(), which may benested. The corresponding synchronous update-sideprimitives, synchronize_rcu(), along with its synonymsynchronize_net(), wait for any currentlyexecuting RCU read-side critical sections to complete.The length of this wait is known as a “grace

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

Saved successfully!

Ooh no, something went wrong!