1 / 20

RCU Implementation

RCU Implementation. The read-copy-update mechanism for supporting real-time applications on shared-memory multiprocessor systems with Linux Guniguntala et al. RCU Overview. Publish-Subscribe insertion reader-writer synchronization Wait for pre-existing readers to complete deletion

adanne
Download Presentation

RCU Implementation

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. RCU Implementation The read-copy-update mechanism for supporting real-time applications on shared-memory multiprocessor systems with Linux Guniguntala et al.

  2. RCU Overview • Publish-Subscribe • insertion • reader-writer synchronization • Wait for pre-existing readers to complete • deletion • change – wait for readers – free • safe memory reclamation • Maintain multiple versions of update objects • for readers

  3. RCU – List Update– Basic Strategy Starting List New Node Copy B to B’ and Modify Move A.Next to B’ B still visible, but not for new readers Readers complete, remove B RCU Semantics: A First Attempt McKenney & Walpole

  4. RCU – Reader, Writer, GC • Reader-Writer • rcu_assign_pointer() • rcu_dereference() • Memory barriers embedded in API • Writer-Collection • rcu_synchronize() blocks caller until safe to collect • call_rcu() is asychronous call for collection • Reader-Collection (?) p->a = 1; p->b = 2; p->c = 3; rcu_assign_pointer(gp, p);

  5. Memory Reclamation • General issues in non-blocking & swap-free • When is it safe to free memory? • Memory reclamation tracking can be relatively costly • Expensive atomic operations / memory barriers required • Non-blocking queue • Atomic operation expense • CAS (15-25 clock cycles on P4) • Retry on contention • Non-blocking synchronization • Atomic operation expense • store_conditional • Data structure copy expense

  6. RCU - Memory Reclamation • With interactions between reader, writer and collector, when is it time to reclaim memory? • Writer identifies what to collect and trigger collection to occur (synchronously or asynch) • Readers (indirectly) indicate when to collect by no longer referencing the freed object

  7. RCU – Memory Reclamation • One solution for collector: • Track copies of global pointer into thread-local memory • Each thread maintains a list of it’s currently active pointers • Collector checks the thread-local list prior to memory reclamation • Sounds a lot like the hazard pointer !

  8. RCU & Hazard Pointers • Hazard Pointer Disadvantages: • Required manual identification of hazard references • Expensive on the read path • Requires two memory barriers on the read path • Copy of the global pointer to local reference • Entry of hazard pointer into the list • Every read thread incurs this extra overhead as the cost for correct memory reclamation. Expensive for many-reader situations

  9. RCU – Memory Reclamation • RCU -> Collection based on ‘quiescent state’ • Threads prevent the occurrence of quiescent state while their local memory is alive • Collector indirectly observes state of all threads to infer when safe to reclaim memory • The definition chosen for ‘quiescent state’ will significantly impact performance • Best choice: Infer by operations that occur anyway

  10. RCU – Reader - Collection • Reader-Collection • rcu_read_lock() • rcu_read_unlock() • read-side critical section • Non-preemptible kernel • Programming convention is to avoid yielding in the read-side critical section • Memory reclamation on voluntary context switch • rcu_read_lock/unlock calls do nothing in non-preemptible kernel rcu_read_lock(); retval = rcu_dereference(gbl_foo)->a; rcu_read_unlock(); return retval;

  11. RCU – Memory Reclamation • ‘Simple case’: Non-preemptible kernel • All threads use read-side critical section with no voluntary yield • no context switch within a read-side critical section • Collector observes all CPU to determine when all threads have undergone a context switch • Indicates a pass into a quiescent state • All previous read-side critical sections are now guaranteed to have exited • Any new threads no longer have visibility to removed object • Safe–conservative-imprecise–degrades real-time • Detection of quiescent state occurs after last reader use • Collector waits for all readers to finish even if not all readers were accessing the memory to be reclaimed • Delay real-time response due to refusal to yield within read-side critical

  12. Preemptible kernels • Read-side critical section • Readers can now be preempted in their read-side critical • Disable preemption on entry and re-enable on exit • Memory freed using synchronize_sched() • Counts scheduler preemptions • Benefits and trade-offs • Allows use of RCU with preemptible kernel • Read-side critical section won’t be preempted by RT events, negative consequences for RT responsiveness • Additional read-side work to disable/enable preemption

  13. RCU – RT with counters • Global counter • Atomic increment in rcu_read_lock() • Atomic decrement in rcu_read_unlock() • Quiescent state defined as global counter=0 • Not practical • As CPU count increases, counter may never reach 0

  14. RCU – RT with counters • Use two-element array as counter • Atomically increment/decrement as matched pair of ‘current’ and ‘last’ counter • Grace period starts – swap sense of ‘current’ and ‘last’, proceed to only decrement the ‘last’ counter • Counter eventually reaches 0, marking end of grace period • High overhead due to memory contention / cache misses

  15. RCU – Avoiding the cache-miss • 2xN arrays, N=thread count (2 per thread) • Global index • Updated with rcu_read_lock() and rcu_read_unlock() • Requires a grace-period detection state machine

  16. RCU – Avoiding the cache-miss • Improves read-side performance • Avoids cache-miss • Does not require (expensive) atomic instructions • Does not require (expensive) memory barriers • Requires state-machine for grace period detection

  17. RCU – Priority inheritance • Indefinite delays in read-side critical sections • Extends grace period • Exhausts memory since no collection can occur • Writers cannot allocate memory • Need to prevent low-priority threads from being indefinitely preempted • Priority boost would work – but relatively expensive and not required for every reader • Solution is to defer priority boosting • Preempted read-side critical threads added to list • List serves as an ‘aging’ tracker

  18. RCU – Priority Inheritence • Issue List

  19. RCU – Sleepable RCU • Global definition of grace period • Single delayed thread in read-side critical section can stall memory reclamation for everyone • Stall occurs even though reader’s data is unrelated to memory trying to be reclaimed • RCU Control Block • Reader/updater invocations share defined control blocks • Readers won’t block reclamation for unrelated control blocks idx = srcu_read_lock(&scb) /* read-side critical */ srcu_read_unlock(&scb, idx) /* collection */ synchronize_srcu(&scb)

  20. RCU Performance Comparisons Fast concurrent reads Relatively slow writers Preemption & RT support requires increased read-side work

More Related