Skip to contentSkip to conversation

Make RCU lists use the RCU API

PATCH In review Franck Bui-Huu 3 participants 10 messages Jan 17, 2008 – Feb 3, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Make RCU lists use the RCU API

Hi,

After reading the nice article contributed by Paul on LWN, I took a look to the kernel RCU-protected list implementation to get a good idea on how RCU protection mechanism can be used.

And it appears that the implementation doesn't use the RCU API as much as it could: every updates of "->next" field could have been done by using rcu_assign_pointer(), the main point being readability.

So this patchset does that. However when cooking the patch, I noticed that it's hard to import RCU API without creating some circular dependencies. This is mainly explained by the fact that list.h defines a couple of very primitive types used all over the kernel.

The easiest thing I could come up with is to create a new header file rculist.h, which keeps all RCU-protected list definitions. list.h still keeps the basic list stuffs and still has very few dependencies. OTOH RCU-protected list is a more complex type of list and can have more dependencies. Therefore it needs more careful in including it.

I don't know if any header dependency rules exist for the kernel, so please any suggestions are welcome to deal with such issue.

"make allyesconfig" builds and boots fine on x86 architecture, this patchset being applied on top of Linus' v2.6.24-rc7 tag.

Please consider,

Franck

--

 arch/ia64/sn/kernel/irq.c                       |    1 +
 drivers/infiniband/hw/ipath/ipath_verbs_mcast.c |    3 +-
 include/linux/dcache.h                          |    1 +
 include/linux/list.h                            |  385 ----------------------
 include/linux/rculist.h                         |  391 +++++++++++++++++++++++
 lib/textsearch.c                                |    2 +-
 6 files changed, 395 insertions(+), 388 deletions(-)
#1 lore raw

PATCH 1/2 Split list.h and move rcu-protected lists into rculist.h

From: Franck Bui-Huu <[email protected]>

This patch moves rcu-protected lists from list.h into a new header file rculist.h.

This is done because list are a very used primitive structure all over the kernel and it's currently impossible to include other header files in this list.h without creating some circular dependencies.

For example, list.h implements rcu-protected list and uses rcu_dereference() without including rcupdate.h. It actually compiles because users of rcu_dereference() are macros. Others RCU functions could be used too but aren't probably because of this.

Therefore this patch creates rculist.h which includes rcupdates without to many changes/troubles.

---
 arch/ia64/sn/kernel/irq.c                       |    1 +
 drivers/infiniband/hw/ipath/ipath_verbs_mcast.c |    3 +-
 include/linux/dcache.h                          |    1 +
 include/linux/list.h                            |  385 ----------------------
 include/linux/rculist.h                         |  396 +++++++++++++++++++++++
 lib/textsearch.c                                |    2 +-
 6 files changed, 400 insertions(+), 388 deletions(-)
 create mode 100644 include/linux/rculist.h
arch/ia64/sn/kernel/irq.c +1 -0
index 53351c3..96c31b4 100644
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 #include <linux/spinlock.h>
 #include <linux/init.h>
+#include <linux/rculist.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
 #include <asm/sn/intr.h>
drivers/infiniband/hw/ipath/ipath_verbs_mcast.c +1 -2
index 9e5abf9..d73e322 100644
@@ -31,8 +31,7 @@
  * SOFTWARE.
  */
 
-#include <linux/list.h>
-#include <linux/rcupdate.h>
+#include <linux/rculist.h>
 
 #include "ipath_verbs.h"
 
include/linux/dcache.h +1 -0
index c2c153f..e4fa047 100644
@@ -5,6 +5,7 @@
 
 #include <asm/atomic.h>
 #include <linux/list.h>
+#include <linux/rculist.h>
 #include <linux/spinlock.h>
 #include <linux/cache.h>
 #include <linux/rcupdate.h>
include/linux/list.h +0 -385

445 lines not on this page · raw message

include/linux/rculist.h new file +396 -0

396 lines not on this page · raw message

lib/textsearch.c +1 -1
index be8bda3..f7652ec 100644
@@ -97,7 +97,7 @@
 #include <linux/types.h>
 #include <linux/string.h>
 #include <linux/init.h>
-#include <linux/rcupdate.h>
+#include <linux/rculist.h>
 #include <linux/err.h>
 #include <linux/textsearch.h>
 
Signature · 1 line
1.5.3.7
maintainer
#2 lore raw

Re: [PATCH 1/2] Split list.h and move rcu-protected lists into rculist.h

Quoted 2 lines · On Thu, 17 Jan 2008 21:47:38 +0100 Franck Bui-Huu <[email protected]> wrote:

This patch moves rcu-protected lists from list.h into a new header file rculist.h.

I'm getting way too many compilation errors from this, perhaps because of new rcu-list usages which weren't present in the old tree (ie: current Linus mainline) which you tested it against.

The most practical way to prepare a patch like this is to either make it back-compatible (for a while at least) or to prepare and carefully test it against latest -mm. That way you'll pick up everyone's new code.

#3 lore raw

Re: [PATCH 1/2] Split list.h and move rcu-protected lists into rculist.h

Quoted 10 lines · Andrew Morton
Quoted 2 lines · On Thu, 17 Jan 2008 21:47:38 +0100 Franck Bui-Huu <[email protected]> wrote:

This patch moves rcu-protected lists from list.h into a new header file rculist.h.

I'm getting way too many compilation errors from this, perhaps because of new rcu-list usages which weren't present in the old tree (ie: current Linus mainline) which you tested it against.

Not really suprising, sorry for the mess.

Quoted 4 lines

The most practical way to prepare a patch like this is to either make it back-compatible (for a while at least) or to prepare and carefully test it against latest -mm. That way you'll pick up everyone's new code.

I'll try to come up with something better: if rculist helpers are used from list.h then issue a warning otherwise every thing is fine since the helpers are imported from rculist.h.

Do you think it's better ?

In the meanwhile, could you drop the patches related to rculist from mm tree ?

Thanks
Franck

maintainer
#4 lore raw

Re: [PATCH 1/2] Split list.h and move rcu-protected lists into rculist.h

Quoted 19 lines · On Sat, 02 Feb 2008 14:32:41 +0100 Franck Bui-Huu <[email protected]> wrote:
Quoted 10 lines · Andrew Morton
Quoted 2 lines · On Thu, 17 Jan 2008 21:47:38 +0100 Franck Bui-Huu <[email protected]> wrote:

This patch moves rcu-protected lists from list.h into a new header file rculist.h.

I'm getting way too many compilation errors from this, perhaps because of new rcu-list usages which weren't present in the old tree (ie: current Linus mainline) which you tested it against.

Not really suprising, sorry for the mess.

Quoted 4 lines

The most practical way to prepare a patch like this is to either make it back-compatible (for a while at least) or to prepare and carefully test it against latest -mm. That way you'll pick up everyone's new code.

Quoted 5 lines

I'll try to come up with something better: if rculist helpers are used from list.h then issue a warning otherwise every thing is fine since the helpers are imported from rculist.h.

Do you think it's better ?

Could. I'd suggest that you redo the header-file split patch around the 2.6.25-rc1 timeframe, test it carefully then let's get it in then.

Quoted 2 lines

In the meanwhile, could you drop the patches related to rculist from mm tree ?

I have done so.

#5 lore raw

Re: [PATCH 1/2] Split list.h and move rcu-protected lists into rculist.h

Quoted 6 lines · Andrew Morton
Quoted 1 line · On Sat, 02 Feb 2008 14:32:41 +0100 Franck Bui-Huu <[email protected]> wrote:

Do you think it's better ?

Could. I'd suggest that you redo the header-file split patch around the 2.6.25-rc1 timeframe, test it carefully then let's get it in then.

Does the mm tree also have a calm down period during release candidates ?

I have modified the patchset so now if rcu helpers are used from rculist.h then fine otherwise gcc warns you that you're using the helpers from list.h like this:

init/foo.c:13: warning: ‘__deprecated_list_add_rcu’ is deprecated (declared at include/linux/rculist.h:76)

But the build process doesn't fail anymore.

For that I added some ugly hacks in list.h and rculist.h but they definitively should be removed for mainline inclusion. I'm sending them in response to this email.

If we include this now, then people can have a chance to notice that rculist.h exists and fix their stuffs until 2.6.25 release candidates but I'll redo the patchset and give it some test around the 2.6.25-rc1 timeframe anyway.

Franck

maintainer
#6 lore raw

Re: [PATCH 1/2] Split list.h and move rcu-protected lists into rculist.h

Quoted 9 lines · On Sun, 03 Feb 2008 09:45:25 +0100 Franck Bui-Huu <[email protected]> wrote:
Quoted 6 lines · Andrew Morton
Quoted 1 line · On Sat, 02 Feb 2008 14:32:41 +0100 Franck Bui-Huu <[email protected]> wrote:

Do you think it's better ?

Could. I'd suggest that you redo the header-file split patch around the 2.6.25-rc1 timeframe, test it carefully then let's get it in then.

Does the mm tree also have a calm down period during release candidates ?

Yes, I try to not merge too much material late in the -rcs and in the merge window. Often it's not practical to merge things anyway, because people prepare patches against mainline, which is ancient history...

Quoted 11 lines

I have modified the patchset so now if rcu helpers are used from rculist.h then fine otherwise gcc warns you that you're using the helpers from list.h like this:

init/foo.c:13: warning: ‘__deprecated_list_add_rcu’ is deprecated (declared at include/linux/rculist.h:76)

But the build process doesn't fail anymore.

For that I added some ugly hacks in list.h and rculist.h but they definitively should be removed for mainline inclusion. I'm sending them in response to this email.

I wouldn't bother, really. Let's just get it as good as we can and slam it in.

Quoted 4 lines

If we include this now, then people can have a chance to notice that rculist.h exists and fix their stuffs until 2.6.25 release candidates but I'll redo the patchset and give it some test around the 2.6.25-rc1 timeframe anyway.

I'm just about finished compilation-testing for 2.6.24-mm1 which is a shame. Please do a best-effort against 2.6.24-mm1 (hopefully I'll get that out tomorrow) and I'll slip it into -rc1 if it gets through cross-build testing without unfixable-with-my-patience-level problems.

#7 lore raw

Re: [PATCH 1/2] Split list.h and move rcu-protected lists into rculist.h

Quoted 34 lines · Andrew Morton
Quoted 7 lines · On Sun, 03 Feb 2008 09:45:25 +0100 Franck Bui-Huu <[email protected]> wrote:
Quoted 5 lines · Andrew Morton
Quoted 1 line · On Sat, 02 Feb 2008 14:32:41 +0100 Franck Bui-Huu <[email protected]> wrote:

Do you think it's better ?

Could. I'd suggest that you redo the header-file split patch around the 2.6.25-rc1 timeframe, test it carefully then let's get it in then.

Does the mm tree also have a calm down period during release candidates ?

Yes, I try to not merge too much material late in the -rcs and in the merge window. Often it's not practical to merge things anyway, because people prepare patches against mainline, which is ancient history...

Quoted 11 lines

I have modified the patchset so now if rcu helpers are used from rculist.h then fine otherwise gcc warns you that you're using the helpers from list.h like this:

init/foo.c:13: warning: ‘__deprecated_list_add_rcu’ is deprecated (declared at include/linux/rculist.h:76)

But the build process doesn't fail anymore.

For that I added some ugly hacks in list.h and rculist.h but they definitively should be removed for mainline inclusion. I'm sending them in response to this email.

I wouldn't bother, really. Let's just get it as good as we can and slam it in.

Quoted 4 lines

If we include this now, then people can have a chance to notice that rculist.h exists and fix their stuffs until 2.6.25 release candidates but I'll redo the patchset and give it some test around the 2.6.25-rc1 timeframe anyway.

Quoted 5 lines

I'm just about finished compilation-testing for 2.6.24-mm1 which is a shame. Please do a best-effort against 2.6.24-mm1 (hopefully I'll get that out tomorrow) and I'll slip it into -rc1 if it gets through cross-build testing without unfixable-with-my-patience-level problems.

OK.

I'm waiting for 2.6.24-mm1 and resend the patchset for 2.6.25-rc1 after some good testings on mm tree.

Thanks
Franck

#8 lore raw

PATCH 2/2 rculist.h: use the rcu API

In reply to Franck Bui-Huu

From: Franck Bui-Huu <[email protected]>

This patch makes almost all list mutation primitives use rcu_assign_pointer().

The main point of this being readability improvement.

---
 include/linux/rculist.h |   23 +++++++++--------------
 1 files changed, 9 insertions(+), 14 deletions(-)
include/linux/rculist.h +9 -14
index 8056d38..038b64f 100644
@@ -7,6 +7,7 @@
  * RCU-protected list version
  */
 #include <linux/list.h>
+#include <linux/rcupdate.h>
 
 /*
  * Insert a new entry between two known consecutive entries.
@@ -19,9 +20,8 @@ static inline void __list_add_rcu(struct list_head * new,
 {
 	new->next = next;
 	new->prev = prev;
-	smp_wmb();
+	rcu_assign_pointer(prev->next, new);
 	next->prev = new;
-	prev->next = new;
 }
 
 /**
@@ -110,9 +110,8 @@ static inline void list_replace_rcu(struct list_head *old,
 {
 	new->next = old->next;
 	new->prev = old->prev;
-	smp_wmb();
+	rcu_assign_pointer(new->prev->next, new);
 	new->next->prev = new;
-	new->prev->next = new;
 	old->prev = LIST_POISON2;
 }
 
@@ -166,8 +165,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
 	 */
 
 	last->next = at;
-	smp_wmb();
-	head->next = first;
+	rcu_assign_pointer(head->next, first);
 	first->prev = head;
 	at->prev = last;
 }
@@ -280,10 +278,9 @@ static inline void hlist_replace_rcu(struct hlist_node *old,
 
 	new->next = next;
 	new->pprev = old->pprev;
-	smp_wmb();
+	rcu_assign_pointer(*new->pprev, new);
 	if (next)
 		new->next->pprev = &new->next;
-	*new->pprev = new;
 	old->pprev = LIST_POISON2;
 }
 
@@ -310,12 +307,12 @@ static inline void hlist_add_head_rcu(struct hlist_node *n,
 					struct hlist_head *h)
 {
 	struct hlist_node *first = h->first;
+
 	n->next = first;
 	n->pprev = &h->first;
-	smp_wmb();
+	rcu_assign_pointer(h->first, n);
 	if (first)
 		first->pprev = &n->next;
-	h->first = n;
 }
 
 /**
@@ -341,9 +338,8 @@ static inline void hlist_add_before_rcu(struct hlist_node *n,
 {
 	n->pprev = next->pprev;
 	n->next = next;
-	smp_wmb();
+	rcu_assign_pointer(*(n->pprev), n);
 	next->pprev = &n->next;
-	*(n->pprev) = n;
 }
 
 /**
@@ -369,8 +365,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
 {
 	n->next = prev->next;
 	n->pprev = &prev->next;
-	smp_wmb();
-	prev->next = n;
+	rcu_assign_pointer(prev->next, n);
 	if (n->next)
 		n->next->pprev = &n->next;
 }
Signature · 1 line
1.5.3.7
Acked-by on v1 2/2
#9 lore raw

Re: [PATCH 2/2] rculist.h: use the rcu API

Quoted 6 lines · Franck Bui-Huu

From: Franck Bui-Huu <[email protected]>

This patch makes almost all list mutation primitives use rcu_assign_pointer().

The main point of this being readability improvement.

Looks better to me!

Quoted 100 lines
---
 include/linux/rculist.h |   23 +++++++++--------------
 1 files changed, 9 insertions(+), 14 deletions(-)
include/linux/rculist.h +9 -14
index 8056d38..038b64f 100644
@@ -7,6 +7,7 @@
  * RCU-protected list version
  */
 #include <linux/list.h>
+#include <linux/rcupdate.h>
 
 /*
  * Insert a new entry between two known consecutive entries.
@@ -19,9 +20,8 @@ static inline void __list_add_rcu(struct list_head * new,
 {
 	new->next = next;
 	new->prev = prev;
-	smp_wmb();
+	rcu_assign_pointer(prev->next, new);
 	next->prev = new;
-	prev->next = new;
 }
 
 /**
@@ -110,9 +110,8 @@ static inline void list_replace_rcu(struct list_head *old,
 {
 	new->next = old->next;
 	new->prev = old->prev;
-	smp_wmb();
+	rcu_assign_pointer(new->prev->next, new);
 	new->next->prev = new;
-	new->prev->next = new;
 	old->prev = LIST_POISON2;
 }
 
@@ -166,8 +165,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
 	 */
 
 	last->next = at;
-	smp_wmb();
-	head->next = first;
+	rcu_assign_pointer(head->next, first);
 	first->prev = head;
 	at->prev = last;
 }
@@ -280,10 +278,9 @@ static inline void hlist_replace_rcu(struct hlist_node *old,
 
 	new->next = next;
 	new->pprev = old->pprev;
-	smp_wmb();
+	rcu_assign_pointer(*new->pprev, new);
 	if (next)
 		new->next->pprev = &new->next;
-	*new->pprev = new;
 	old->pprev = LIST_POISON2;
 }
 
@@ -310,12 +307,12 @@ static inline void hlist_add_head_rcu(struct hlist_node *n,
 					struct hlist_head *h)
 {
 	struct hlist_node *first = h->first;
+
 	n->next = first;
 	n->pprev = &h->first;
-	smp_wmb();
+	rcu_assign_pointer(h->first, n);
 	if (first)
 		first->pprev = &n->next;
-	h->first = n;
 }
 
 /**
@@ -341,9 +338,8 @@ static inline void hlist_add_before_rcu(struct hlist_node *n,
 {
 	n->pprev = next->pprev;
 	n->next = next;
-	smp_wmb();
+	rcu_assign_pointer(*(n->pprev), n);
 	next->pprev = &n->next;
-	*(n->pprev) = n;
 }
 
 /**
@@ -369,8 +365,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
 {
 	n->next = prev->next;
 	n->pprev = &prev->next;
-	smp_wmb();
-	prev->next = n;
+	rcu_assign_pointer(prev->next, n);
 	if (n->next)
 		n->next->pprev = &n->next;
 }
Signature · 1 line
1.5.3.7