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.

306 APPENDIX F. ANSWERS TO QUICK QUIZZESGiven that grace periods are prohibited within RCUread-side critical sections, how can an RCU datastructure possibly be updated while in an RCUread-side critical section?Answer:This situation is one reason for the existenceof asynchronous grace-period primitives such ascall_rcu(). This primitive may be invoked withinan RCU read-side critical section, and the specifiedRCU callback will in turn be invoked at a latertime, after a grace period has elapsed.The ability to perform an RCU update whilewithin an RCU read-side critical section can be extremelyconvenient, and is analogous to a (mythical)unconditional read-to-write upgrade for readerwriterlocking.Quick Quiz 8.61:The statistical-counter implementation shown inFigure 4.8 (count_end.c) used a global lock toguard the summation in read_count(), which resultedin poor performance and negative scalability.How could you use RCU to provide read_count()with excellent performance and good scalability.(Keep in mind that read_count()’s scalabilitywill necessarily be limited by its need to scan allthreads’ counters.)Answer:Hint: place the global variable finalcount andthe array counterp[] into a single RCU-protectedstruct. At initialization time, this structure wouldbe allocated and set to all zero and NULL.The inc_count() function would be unchanged.Theread_count() function would usercu_read_lock() instead of acquiring final_mutex, andwould need to use rcu_dereference() to acquirea reference to the current structure.The count_register_thread() function wouldset the array element corresponding to the newlycreated thread to reference that thread’s per-threadcounter variable.The count_unregister_thread() functionwould need to allocate a new structure, acquirefinal_mutex, copy the old structure to the newone, add the outgoing thread’s counter variable tothe total, NULL the pointer to this same countervariable, use rcu_assign_pointer() to installthe new structure in place of the old one, releasefinal_mutex, wait for a grace period, and finallyfree the old structure.<strong>Do</strong>es this really work? Why or why not?Quick Quiz 8.62:Section 4.5 showed a fanciful pair of code fragmentsthat dealt with counting I/O accesses to removabledevices. These code fragments suffered from highoverhead on the fastpath (starting an I/O) due tothe need to acquire a reader-writer lock. How wouldyou use RCU to provide excellent performance andscalability? (Keep in mind that the performance ofthe common-case first code fragment that does I/Oaccesses is much more important than that of thedevice-removal code fragment.)Answer:Hint: replace the read-acquisitions of the readerwriterlock with RCU read-side critical sections,then adjust the device-removal code fragment tosuit.See Section 9.2 on Page 111 for one solution tothis problem.F.8 Chapter 9: Applying RCUQuick Quiz 9.1:Why on earth did we need that global lock in thefirst place???Answer:A given thread’s __thread variables vanish whenthat thread exits. <strong>It</strong> is therefore necessary to synchronizeany operation that accesses other threads’__thread variables with thread exit. Without suchsynchronization, accesses to __thread variable of ajust-exited thread will result in segmentation faults.Quick Quiz 9.2:Just what is the accuracy of read_count(), anyway?Answer:Refer to Figure 4.8 on Page 33. Clearly, if thereare no concurrent invocations of inc_count(),read_count() will return an exact result. However,if there are concurrent invocations of inc_count(),then the sum is in fact changing as read_count()performs its summation. That said, because threadcreation and exit are excluded by final_mutex, thepointers in counterp remain constant.Let’s imagine a mythical machine that is able to

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

Saved successfully!

Ooh no, something went wrong!