|| ||Corey Minyard <firstname.lastname@example.org>|
|| ||Andrew Morton <email@example.com>,
Linux Kernel <firstname.lastname@example.org>|
|| ||[PATCH] add an RCU version of list splicing|
|| ||Wed, 3 Jan 2007 09:27:38 -0600|
|| ||Christoph Hellwig <email@example.com>,
OpenIPMI Developers <firstname.lastname@example.org>,
"Paul E. McKenney" <email@example.com>,
Carol Hebert <firstname.lastname@example.org>|
This patch is in support of the IPMI driver. I have tested this
with the IPMI driver changes coming in the next patch.
Add a list_splice_init_rcu() function to splice an RCU-protected list
into another list. This takes the sync function as an argument, so
one would do something like:
list_splice_init_rcu(&source, &dest, synchronize_rcu);
The idea being to keep the RCU API proliferation down to a dull roar.
Signed-off-by: Paul E. McKenney <email@example.com>
Signed-off-by: Corey Minyard <firstname.lastname@example.org>
list.h | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 58 insertions(+)
--- linux-2.6.19.orig/include/linux/list.h 2006-11-29 15:57:37.000000000 -0600
+++ linux-2.6.19/include/linux/list.h 2006-12-30 12:47:07.000000000 -0600
@@ -360,6 +360,63 @@
+ * list_splice_init_rcu - splice an RCU-protected list into an existing list.
+ * @list: the RCU-protected list to splice
+ * @head: the place in the list to splice the first list into
+ * @sync: function to sync: synchronize_rcu(), synchronize_sched(), ...
+ * @head can be RCU-read traversed concurrently with this function.
+ * Note that this function blocks.
+ * Important note: the caller must take whatever action is necessary to
+ * prevent any other updates to @head. In principle, it is possible
+ * to modify the list as soon as sync() begins execution.
+ * If this sort of thing becomes necessary, an alternative version
+ * based on call_rcu() could be created. But only if -really-
+ * needed -- there is no shortage of RCU API members.
+static inline void list_splice_init_rcu(struct list_head *list,
+ struct list_head *head,
+ void (*sync)(void))
+ struct list_head *first = list->next;
+ struct list_head *last = list->prev;
+ struct list_head *at = head->next;
+ if (list_empty(head))
+ /* "first" and "last" tracking list, so initialize it. */
+ * At this point, the list body still points to the source list.
+ * Wait for any readers to finish using the list before splicing
+ * the list body into the new list. Any new readers will see
+ * an empty list.
+ * Readers are finished with the source list, so perform splice.
+ * The order is important if the new list is global and accessible
+ * to concurrent RCU readers. Note that RCU readers are not
+ * permitted to traverse the prev pointers without excluding
+ * this function.
+ last->next = at;
+ head->next = first;
+ first->prev = head;
+ at->prev = last;
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys - and earn cash