From mboxrd@z Thu Jan 1 00:00:00 1970 Return-path: Received: from crystal.sipsolutions.net ([195.210.38.204]:41161 "EHLO sipsolutions.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758163AbXIJMEa (ORCPT ); Mon, 10 Sep 2007 08:04:30 -0400 Subject: [PATCH] list.h: add list_for_each_entry_continue_rcu From: Johannes Berg To: "John W. Linville" Cc: Linux Kernel list , linux-wireless , "Paul E. McKenney" Content-Type: text/plain Date: Mon, 10 Sep 2007 14:05:47 +0200 Message-Id: <1189425947.4506.78.camel@johannes.berg> Mime-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org List-ID: 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(). Additional help text was provided by Paul McKenney. Signed-off-by: Johannes Berg Cc: linux-kernel@vger.kernel.org Cc: Paul E. McKenney --- John, I don't know if you want to merge this or not. There's no clear list.h maintainer and this patch is requisite for the bugfix I'm going to send in a minute so it'd probably be best if this goes into the tree together. If you don't want to take it, however, I have no idea how to handle the situation :) include/linux/list.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) --- wireless-dev.orig/include/linux/list.h 2007-09-07 22:00:41.234425862 +0200 +++ wireless-dev/include/linux/list.h 2007-09-07 22:05:08.184425862 +0200 @@ -665,6 +665,32 @@ 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(). + * + * 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. + */ +#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