Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linux RCU and double linked list

Tags:

c

linux

rcu

I'm reading about Read-copy-update (RCU). I'm not sure if I understood it correctly in case of SMP. As far as I know RCU ensures that Update is executed atomically. In case for example single linked list it is obvious that exchanging old element with the new one can be done in one operation, because it is done by changing pointer. But how to ensure that RCU will still be atomically executed in case of doubly-linked list? There are two pointers points to given element (next and prev), so every change on this element needs to change those two pointers. How to ensure that changing those two pointers will be done as atomic operation? How it is done in Linux?

like image 983
user2699113 Avatar asked Nov 01 '16 12:11

user2699113


People also ask

Does doubly linked list have head tail?

As in the singly linked list, the doubly linked list also has a head and a tail. The previous pointer of the head is set to NULL as this is the first node. The next pointer of the tail node is set to NULL as this is the last node. A basic layout of the doubly linked list is shown in the below diagram.

Why we use doubly linked list?

The most common reason to use a doubly linked list is because it is easier to implement than a singly linked list. While the code for the doubly linked implementation is a little longer than for the singly linked version, it tends to be a bit more “obvious” in its intention, and so easier to implement and debug.

What is an intrusive list in Linux kernel?

Intrusive linked lists are a variation of linked lists where the links are embedded in the structure that's being linked. In a typical linked list implementation, a list node contains a data pointer to the linked data and a next pointer to the next node in the list.

What is a doubly ended linked list?

A Doubly Linked List (DLL) contains an extra pointer, typically called the previous pointer, together with the next pointer and data which are there in the singly linked list. Prerequisites: Linked List Introduction, Inserting a node in Singly Linked List.


1 Answers

I was asking myself the same question, and a quick search brought a reply to a comment, extracted from an introduction article to RCU by Paul McKenney (who, from what I gather, is one of the multiple concurrent inventors of the ideas behind RCU).

The question:

I'm wondering whether the omission of the backlinks in the examples is a good thing. The omission makes the technique trivial, since publishing only involves one replacing one pointer.

What about the second, back, one? Without support for atomic two-pointer updates, how can both the p->prev->next = q and p->next->prev = q updates be performed without risking clients to see an inconsistent view of the doubly linked list? Or is that not a problem in practice?

Thanks for the article, though. Looking forward to the next installment!

The answer:

Glad you liked the article, and thank you for the excellent question! I could give any number of answers, including: In production systems, trivial techniques are a very good thing. Show me an example where it is useful to traverse the ->prev pointers under RCU protection. Given several such examples, we could work out how best to support this. Consistency is grossly overrated. (Not everyone agrees with me on this, though!) Even with atomic two-pointer updates, consider the following sequence of events: (1) task 1 does p=p->next (2) task 2 inserts a new element between the two that task 1 just dealt with (3) task 1 does p=p->prev and fails to end up where it started! Even double-pointer atomic update fails to banish inconsistency! ;-) If you need consistency, use locks. Given the example above, we could support a level of consistency equivalent to the double-pointer atomic update simply by assigning the pointers in sequence -- just remove the prev-pointer poisoning from list_del_rcu(), for example. But doing this would sacrifice the ability to catch those bugs that pointer-poisoning currently catches.

So, there might well come a time when the Linux kernel permits RCU-protected traversal of linked lists in both directions, but we need to see a compelling need for this before implementing it.

So basically, Linux "disallows" backwards traversal in both directions when doing RCU. As mentioned in the comment, you could use some newer hardware mechanisms like Double Compare And Swap, but they're not available everywhere, and as mentioned, you can still get memory consistency issues.

like image 84
Adrien Avatar answered Nov 15 '22 09:11

Adrien