Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 78b0e0e9 authored by Paul E. McKenney's avatar Paul E. McKenney Committed by Ingo Molnar
Browse files

RCU, rculist.h: fix list iterators



RCU list iterators: should prefetch ever be optimised out with no
side-effects, the current version will lose the barrier completely.

Pointed-out-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: default avatarPaul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent d7c06513
Loading
Loading
Loading
Loading
+15 −33
Original line number Diff line number Diff line
@@ -180,31 +180,14 @@ static inline void list_splice_init_rcu(struct list_head *list,
 * as long as the traversal is guarded by rcu_read_lock().
 */
#define list_for_each_rcu(pos, head) \
	for (pos = (head)->next; \
		prefetch(rcu_dereference(pos)->next), pos != (head); \
		pos = pos->next)
	for (pos = rcu_dereference((head)->next); \
		prefetch(pos->next), pos != (head); \
		pos = rcu_dereference(pos->next))

#define __list_for_each_rcu(pos, head) \
	for (pos = (head)->next; \
		rcu_dereference(pos) != (head); \
		pos = pos->next)

/**
 * list_for_each_safe_rcu
 * @pos:	the &struct list_head to use as a loop cursor.
 * @n:		another &struct list_head to use as temporary storage
 * @head:	the head for your list.
 *
 * Iterate over an rcu-protected list, safe against removal of list entry.
 *
 * 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_safe_rcu(pos, n, head) \
	for (pos = (head)->next; \
		n = rcu_dereference(pos)->next, pos != (head); \
		pos = n)
	for (pos = rcu_dereference((head)->next); \
		pos != (head); \
		pos = rcu_dereference(pos->next))

/**
 * list_for_each_entry_rcu	-	iterate over rcu list of given type
@@ -217,10 +200,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
 * as long as the traversal is guarded by rcu_read_lock().
 */
#define list_for_each_entry_rcu(pos, head, member) \
	for (pos = list_entry((head)->next, typeof(*pos), member); \
		prefetch(rcu_dereference(pos)->member.next), \
			&pos->member != (head); \
		pos = list_entry(pos->member.next, typeof(*pos), member))
	for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), member); \
		prefetch(pos->member.next), &pos->member != (head); \
		pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos), member))


/**
@@ -235,9 +217,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
 * as long as the traversal is guarded by rcu_read_lock().
 */
#define list_for_each_continue_rcu(pos, head) \
	for ((pos) = (pos)->next; \
		prefetch(rcu_dereference((pos))->next), (pos) != (head); \
		(pos) = (pos)->next)
	for ((pos) = rcu_dereference((pos)->next); \
		prefetch((pos)->next), (pos) != (head); \
		(pos) = rcu_dereference((pos)->next))

/**
 * hlist_del_rcu - deletes entry from hash list without re-initialization
@@ -382,10 +364,10 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
 * as long as the traversal is guarded by rcu_read_lock().
 */
#define hlist_for_each_entry_rcu(tpos, pos, head, member)		 \
	for (pos = (head)->first;					 \
	     rcu_dereference(pos) && ({ prefetch(pos->next); 1; }) &&	 \
	for (pos = rcu_dereference((head)->first);			 \
		pos && ({ prefetch(pos->next); 1; }) &&			 \
		({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
	     pos = pos->next)
		pos = rcu_dereference(pos->next))

#endif	/* __KERNEL__ */
#endif