CS510 Concurrent Systems

1 / 28

# CS510 Concurrent Systems - PowerPoint PPT Presentation

CS510 Concurrent Systems. “What is RCU, Fundamentally?” By Paul McKenney and Jonathan Walpole Daniel Mansour (Slides adapted from Professor Walpole’s). Review of Concurrency. The Story So Far Critical Sections Shared global objects Blocking/Non-Blocking Reader/Writers

I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.

## PowerPoint Slideshow about 'CS510 Concurrent Systems' - ugo

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.

- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

### CS510 Concurrent Systems

“What is RCU, Fundamentally?”

By Paul McKenney and Jonathan Walpole

Daniel Mansour

Review of Concurrency
• The Story So Far
• Critical Sections
• Shared global objects
• Blocking/Non-Blocking
• Writes are Fewer
• Hardware/Compiler Optimizations
• Operations are not always in order
• Memory Reclamation
• Deleted Objects can still be read
• Do not allow reads while writes are occurring
• RCU solves this by allowing multiple versions
• Insertion
• Publish-Subscribe Mechanism
• Deletion
• Wait for Readers to complete
• Non-Blocking
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;

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;

would get uninitialized values

Publish-Subscribe Mechanism
• Publish the Object
• rcu_assign_pointer

1 p->a = 1;

2 p->b = 2;

3 p->c = 3;

4 rcu_assign_pointer(gp, p);

Publish-Subscribe Mechanism
• Ordering can still be an issue
• 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 }

Publish-Subscribe Mechanism
• Subscribe to the object
• rcu_dereference
• Implements any necessary memory barriers

2 p = rcu_dereference(gp)

3 if (p != NULL {

4 do_something_with(p->a, p->b, p->c);

5 }

Implementation
• Publishing

1 struct foo {

3 int a;

4 int b;

5 int c;

6 };

8

9 /* . . . */

10

11 p = kmalloc(sizeof(*p), GFP_KERNEL);

12 p->a = 1;

13 p->b = 2;

14 p->c = 3;

Still needs to be

protected

• Subscribing

3 do_something_with(p->a, p->b, p->c);

4 }

• Linear list
• Publishing

1 struct foo {

2 structhlist_node *list;

3 int a;

4 int b;

5 int c;

6 };

8

9 /* . . . */

10

11 p = kmalloc(sizeof(*p), GFP_KERNEL);

12 p->a = 1;

13 p->b = 2;

14 p->c = 3;

• Subscribing

2 hlist_for_each_entry_rcu(p, q, head, list) {

3 do_something_with(p->a, p->b, p->c);

4 }

Iteration requires checking for null

Reclaiming Memory
• Waiting
• Must not block or sleep
Reclaiming Memory
• Basic Process
• Alter the data (replace/delete an element)
• Wait for all pre-existing RCU reads to completely finish
• synchronize_rcu
• New RCU reads have no way to access removed element
• Reclaim/Recycle memory
Reclaiming Memory
• Example

1 struct foo {

3 int a;

4 int b;

5 int c;

6 };

8

9 /* . . . */

10

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);

Reclaiming Memory
• synchronize_rcu
• Recall that code in rcu_read blocks can not sleep or block, preventing context switches
• When a context switch occurs, we can deduce that the read has completed
• synchronize_rcu waits for each cpu to context switch conceptually:

1 for_each_online_cpu(cpu)

2 run_on(cpu);

Maintaining Multiple Versions - Deletion
• During deletion
• Initial State

2 if (p != NULL) {

3 list_del_rcu(&p->list);

4 synchronize_rcu();

5 kfree(p);

6 }

Maintaining Multiple Versions - Deletion
• list_del_rcu(&p->list)
• p has been deleted, but other readers can still be accessing it
Maintaining Multiple Versions - Replacement
• During replacement
• Initial State

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);

Maintaining Multiple Versions - Replacement
• list_replace_rcu
• There are now two versions of the list, but both are well formed.
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