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.

F.7. CHAPTER 8: DEFERRED PROCESSING 295the reference counter value equal to one. Supposethat a release operation executes, decrementingthe reference counter to zero and therefore startingcleanup operations. But now the “then” clausecan increment the counter back to a value of one,allowing the object to be used after it has beencleaned up.Quick Quiz 8.6:But doesn’t seqlock also permit readers and updatersto get work done concurrently?Answer:Yes and no. Although seqlock readers can runconcurrently with seqlock writers, whenever thishappens, the read seqretry() primitive will forcethe reader to retry. This means that any work doneby a seqlock reader running concurrently with aseqlock updater will be discarded and redone. <strong>So</strong>seqlock readers can run concurrently with updaters,but they cannot actually get any work done in thiscase.In contrast, RCU readers can perform useful workeven in presence of concurrent RCU updaters.Quick Quiz 8.7:<strong>What</strong> prevents the list for each entry rcu()from getting a segfault if it happens to executeatexactlythesametimeasthelist add rcu()?Answer:On all systems running Linux, loads from andstores to pointers are atomic, that is, if a storeto a pointer occurs at the same time as a loadfrom that same pointer, the load will return eitherthe initial value or the value stored, neversome bitwise mashup of the two. In addition,the list for each entry rcu() always proceedsforward through the list, never looking back. Therefore,the list for each entry rcu() will eithersee the element being added by list add rcu()or it will not, but either way, it will see a validwell-formed list.Quick Quiz 8.8:Why do we need to pass two pointers intohlist for each entry rcu() when only one isneeded for list for each entry rcu()?Answer:Because in an hlist it is necessary to check for NULLrather than for encountering the head. (Try codingup a single-pointer hlist for each entry rcu()<strong>If</strong> you come up with a nice solution, it would be avery good thing!)Quick Quiz 8.9:How would you modify the deletion example topermit more than two versions of the list to beactive?Answer:One way of accomplishing this is as shown inFigure F.4.1 spin_lock(&mylock);2 p = search(head, key);3 if (p == NULL)4 spin_unlock(&mylock);5 else {6 list_del_rcu(&p->list);7 spin_unlock(&mylock);8 synchronize_rcu();9 kfree(p);10 }Figure F.4: Concurrent RCU DeletionNote that this means that multiple concurrentdeletions might be waiting in synchronize rcu().Quick Quiz 8.10:How many RCU versions of a given list can beactive at any given time?Answer:That depends on the synchronization design. <strong>If</strong>a semaphore protecting the update is held acrossthe grace period, then there can be at most twoversions, the old and the new.However, if only the search, the update, and thelist replace rcu() were protected by a lock, thenthere could be an arbitrary number of versions active,limited only by memory and by how many updatescould be completed within a grace period. Butplease note that data structures that are updatedso frequently probably are not good candidates forRCU. That said, RCU can handle high update rateswhen necessary.Quick Quiz 8.11:How can RCU updaters possibly delay RCU

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

Saved successfully!

Ooh no, something went wrong!