Presentation is loading. Please wait.

Presentation is loading. Please wait.

CS510 Concurrent Systems “What is RCU, Fundamentally?” By Paul McKenney and Jonathan Walpole Daniel Mansour (Slides adapted from Professor Walpole’s)

Similar presentations


Presentation on theme: "CS510 Concurrent Systems “What is RCU, Fundamentally?” By Paul McKenney and Jonathan Walpole Daniel Mansour (Slides adapted from Professor Walpole’s)"— Presentation transcript:

1 CS510 Concurrent Systems “What is RCU, Fundamentally?” By Paul McKenney and Jonathan Walpole Daniel Mansour (Slides adapted from Professor Walpole’s)

2 2 Review of Concurrency  The Story So Far o Critical Sections Shared global objects Blocking/Non-Blocking o Reader/Writers Reads are “safer” Writes are Fewer o Hardware/Compiler Optimizations Operations are not always in order o Memory Reclamation Deleted Objects can still be read

3 3 Read-Copy Update (RCU)  Read/Writes o Do not allow reads while writes are occurring o RCU solves this by allowing multiple versions  Insertion o Publish-Subscribe Mechanism  Deletion o Wait for Readers to complete o Non-Blocking

4 4 Publish-Subscribe Mechanism 1 struct foo { 2 int a; 3 int b; 4 int c; 5 }; 6 struct foo *gp = NULL; 7 8 /*... */ 9 10 p = kmalloc(sizeof(*p), GFP_KERNEL); 11 p->a = 1; 12 p->b = 2; 13 p->c = 3; 14 gp = p;

5 5 Publish-Subscribe Mechanism 1 struct foo { 2 int a; 3 int b; 4 int c; 5 }; 6 struct foo *gp = NULL; 7 8 /*... */ 9 10 p = kmalloc(sizeof(*p), GFP_KERNEL); 11 gp = p; 12 p->a = 1; 13 p->b = 2; 14 p->c = 3; Reordered, concurrent readers would get uninitialized values

6 6 Publish-Subscribe Mechanism  Publish the Object o rcu_assign_pointer 1 p->a = 1; 2 p->b = 2; 3 p->c = 3; 4 rcu_assign_pointer(gp, p);

7 7 Publish-Subscribe Mechanism  Readers o Ordering can still be an issue o p->a can be read before p in some compiler optimizations 1 p = gp; 2 if (p != NULL) { 3 do_something_with(p->a, p->b, p-c); 4 }

8 8 Publish-Subscribe Mechanism  Subscribe to the object o rcu_dereference o Implements any necessary memory barriers 1 rcu_read_lock() 2 p = rcu_dereference(gp) 3 if (p != NULL { 4 do_something_with(p->a, p->b, p->c); 5 } 6 rcu_read_unlock();

9 9 Implementation  Doubly Linked Lists o list_head o Head links to tail with prev and vice versa

10 10 Implementation - list_head  Publishing 1 struct foo { 2 struct list_head list; 3 int a; 4 int b; 5 int c; 6 }; 7 LIST_HEAD(head); 8 9 /*... */ 10 11 p = kmalloc(sizeof(*p), GFP_KERNEL); 12 p->a = 1; 13 p->b = 2; 14 p->c = 3; 15 list_add_rcu(&p->list, &head); Still needs to be protected

11 11 Implementation - list_head  Subscribing 1 rcu_read_lock(); 2 list_for_each_entry_rcu(p, head, list) { 3 do_something_with(p->a, p->b, p->c); 4 } 5 rcu_read_unlock();

12 12 Implementation - hlist_head/hlist_node  Doubly Linked Lists o hlist_head/hlist_node o Linear list

13 13 Implementation - hlist_head/hlist_node  Publishing 1 struct foo { 2 struct hlist_node *list; 3 int a; 4 int b; 5 int c; 6 }; 7 HLIST_HEAD(head); 8 9 /*... */ 10 11 p = kmalloc(sizeof(*p), GFP_KERNEL); 12 p->a = 1; 13 p->b = 2; 14 p->c = 3; 15 hlist_add_head_rcu(&p->list, &head);

14 14 Implementation - list_head  Subscribing 1 rcu_read_lock(); 2 hlist_for_each_entry_rcu(p, q, head, list) { 3 do_something_with(p->a, p->b, p->c); 4 } 5 rcu_read_unlock(); Iteration requires checking for null Instead of p = head

15 15 Reclaiming Memory  Waiting o rcu_read_lock and rcu_read_unlock Must not block or sleep

16 Reclaiming Memory  Basic Process 1. Alter the data (replace/delete an element) 2. Wait for all pre-existing RCU reads to completely finish synchronize_rcu New RCU reads have no way to access removed element 3. Reclaim/Recycle memory 16

17 Reclaiming Memory  Example 17 1 struct foo { 2 struct list_head list; 3 int a; 4 int b; 5 int c; 6 }; 7 LIST_HEAD(head); 8 9 /*... */ 10 11 p = search(head, key); 12 if (p == NULL) { 13 /* Take appropriate action, unlock, and return. */ 14 } 15 q = kmalloc(sizeof(*p), GFP_KERNEL); 16 *q = *p; 17 q->b = 2; 18 q->c = 3; 19 list_replace_rcu(&p->list, &q->list); 20 synchronize_rcu(); 21 kfree(p);

18 Reclaiming Memory  synchronize_rcu o rcu_read_lock and rcu_read_unlock do nothing on non- CONFIG-PREEMPT kernels o Recall that code in rcu_read blocks can not sleep or block, preventing context switches o When a context switch occurs, we can deduce that the read has completed o synchronize_rcu waits for each cpu to context switch conceptually: 18 1 for_each_online_cpu(cpu) 2 run_on(cpu);

19 Maintaining Multiple Versions - Deletion  During deletion  Initial State 19 1 p = search(head, key); 2 if (p != NULL) { 3 list_del_rcu(&p->list); 4 synchronize_rcu(); 5 kfree(p); 6 }

20 Maintaining Multiple Versions - Deletion  list_del_rcu(&p->list)  p has been deleted, but other readers can still be accessing it 20

21 Maintaining Multiple Versions - Deletion  synchronize_rcu()  kfree(p) 21

22 Maintaining Multiple Versions - Replacement  During replacement  Initial State 22 1 q = kmalloc(sizeof(*p), GFP_KERNEL); 2 *q = *p; 3 q->b = 2; 4 q->c = 3; 5 list_replace_rcu(&p->list, &q->list); 6 synchronize_rcu(); 7 kfree(p);

23 Maintaining Multiple Versions - Replacement  kmalloc() 23

24 Maintaining Multiple Versions - Replacement  *q = *p 24

25 Maintaining Multiple Versions - Replacement  q->b = 2; q->c = 3 25

26 Maintaining Multiple Versions - Replacement  list_replace_rcu  There are now two versions of the list, but both are well formed. 26

27 Maintaining Multiple Versions - Replacement  synchronize_rcu  kfree() 27

28 Issues  Very much a read/write implementation, not ideally suited for rapidly updated objects  Responsibility on the programmer to make sure that no sleeping/blocking occurs in rcu_read_locks  RCU updaters can still slow readers via cache invalidation 28


Download ppt "CS510 Concurrent Systems “What is RCU, Fundamentally?” By Paul McKenney and Jonathan Walpole Daniel Mansour (Slides adapted from Professor Walpole’s)"

Similar presentations


Ads by Google