Skip to contentSkip to conversation

list.h: add list_for_each_entry_continue_rcu

PATCH In review Johannes Berg 2 participants 5 messages Sep 7, 2007

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 list.h: add list_for_each_entry_continue_rcu

To implement the multicast list callback in mac80211 we need to do partial list iteration. Since I want to convert the interface list to an RCU list, I need a new list walking primitive:
list_for_each_entry_continue_rcu().

Cc Paul E. McKenney <[email protected]>
Cc Herbert Xu <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Pavel Emelianov <[email protected]>
Cc Zach Brown <[email protected]>
Cc Dave Jones <[email protected]>
Cc Oleg Nesterov <[email protected]>

---
How do we want to handle this? Is it ok to push this via net-2.6.24 so we can merge it along with the fix that needs it?

 include/linux/list.h |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
include/linux/list.h +20 -0
@@ -665,6 +665,26 @@ static inline void list_splice_init_rcu(
 		prefetch(rcu_dereference((pos))->next), (pos) != (head); \
         	(pos) = (pos)->next)
 
+
+/**
+ * list_for_each_entry_continue_rcu - continue iteration over rcu list
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Continue to iterate over rcu list of given type, continuing after
+ * the current position.
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define list_for_each_entry_continue_rcu(pos, head, member) \
+	for ((pos) = list_entry((pos)->member.next, typeof(*pos), member); \
+		prefetch(rcu_dereference((pos))->member.next), \
+			 &pos->member != (head); \
+        	(pos) = list_entry(pos->member.next, typeof(*pos), member))
+
 /*
  * Double linked lists with a single pointer list head.
  * Mostly useful for hash tables where the two pointer list head is
#1 lore raw
Quoted 27 lines · Johannes Berg

To implement the multicast list callback in mac80211 we need to do partial list iteration. Since I want to convert the interface list to an RCU list, I need a new list walking primitive:
list_for_each_entry_continue_rcu().

Cc Paul E. McKenney <[email protected]>
Cc Herbert Xu <[email protected]>
Cc Randy Dunlap <[email protected]>
Cc Pavel Emelianov <[email protected]>
Cc Zach Brown <[email protected]>
Cc Dave Jones <[email protected]>
Cc Oleg Nesterov <[email protected]>

---
How do we want to handle this? Is it ok to push this via net-2.6.24 so we can merge it along with the fix that needs it?

 include/linux/list.h |   20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
include/linux/list.h +0 -0
@@ -665,6 +665,26 @@ static inline void list_splice_init_rcu(
 		prefetch(rcu_dereference((pos))->next), (pos) != (head); \
         	(pos) = (pos)->next)

include/linux/list.h static inline void list_splice_init_rcu( · line 676

Quoted 10 lines
include/linux/list.h +9 -0
 
+
+/**
+ * list_for_each_entry_continue_rcu - continue iteration over rcu list
+ * @pos:	the type * to use as a loop cursor.
+ * @head:	the head for your list.
+ * @member:	the name of the list_struct within the struct.
+ *
+ * Continue to iterate over rcu list of given type, continuing after
+ * the current position.

Please add something like the following to this comment:

Note that the caller is responsible for making sure that the element remains in place between the earlier iterator and this one. One way to do this is to ensure that both iterators are covered by the same rcu_read_lock(), while others involve reference counts, flags, or mutexes.

Thanx, Paul

Quoted 16 lines
include/linux/list.h +11 -0
+ *
+ * This list-traversal primitive may safely run concurrently with
+ * the _rcu list-mutation primitives such as list_add_rcu()
+ * as long as the traversal is guarded by rcu_read_lock().
+ */
+#define list_for_each_entry_continue_rcu(pos, head, member) \
+	for ((pos) = list_entry((pos)->member.next, typeof(*pos), member); \
+		prefetch(rcu_dereference((pos))->member.next), \
+			 &pos->member != (head); \
+        	(pos) = list_entry(pos->member.next, typeof(*pos), member))
+
 /*
  * Double linked lists with a single pointer list head.
  * Mostly useful for hash tables where the two pointer list head is
#2 lore raw
Quoted 10 lines · Paul E. McKenney
Quoted 2 lines

+ * Continue to iterate over rcu list of given type, continuing after
+ * the current position.

Please add something like the following to this comment:

Note that the caller is responsible for making sure that the element remains in place between the earlier iterator and this one. One way to do this is to ensure that both iterators are covered by the same rcu_read_lock(), while others involve reference counts, flags, or mutexes.

Sure, will do. Should this comment also be added to list_for_each_continue_rcu()?

johannes

#3 lore raw
Quoted 7 lines · Johannes Berg
Quoted 5 lines · Paul E. McKenney
Quoted 2 lines

+ * Continue to iterate over rcu list of given type, continuing after
+ * the current position.

Please add something like the following to this comment:

Quoted 8 lines
Quoted 5 lines

Note that the caller is responsible for making sure that the element remains in place between the earlier iterator and this one. One way to do this is to ensure that both iterators are covered by the same rcu_read_lock(), while others involve reference counts, flags, or mutexes.

Sure, will do. Should this comment also be added to list_for_each_continue_rcu()?

Actually, list_for_each_continue_rcu() needs to be removed in favor of your new list_for_each_entry_continue_rcu(). There are currently only two users as of 2.6.22. One of them immediately does a list_entry(), and the other would convert easily as well. So please let me know when this gets accepted! ;-)

Thanx, Paul

#4 lore raw
Quoted 5 lines · Paul E. McKenney

Actually, list_for_each_continue_rcu() needs to be removed in favor of your new list_for_each_entry_continue_rcu(). There are currently only two users as of 2.6.22. One of them immediately does a list_entry(), and the other would convert easily as well. So please let me know when this gets accepted! ;-)

Heh, ok, I won't add the text to that macro if you want to remove it anyway. I guess I'll add your paragraph and ... hmm. what do I do with it? Who's responsible for list.h? Can I push this through John Linville and Dave Miller so I can get the fix into his tree easily without synchronisation?

johannes