diff options
author | Paul E. McKenney <paulmck@linux.vnet.ibm.com> | 2008-05-12 15:21:06 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-05-19 04:03:39 -0400 |
commit | 78b0e0e9b27b62c4b22f05a147f7a80fa58b1ae3 (patch) | |
tree | 84c7a3e28ffc1ed92530fec7837087ad918cc8db /include/linux/rculist.h | |
parent | d7c0651390b6a03ad53f99faec0ba88109d7191d (diff) |
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: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'include/linux/rculist.h')
-rw-r--r-- | include/linux/rculist.h | 48 |
1 files changed, 15 insertions, 33 deletions
diff --git a/include/linux/rculist.h b/include/linux/rculist.h index 8d2c81fccfe5..b0f39be08b6c 100644 --- a/include/linux/rculist.h +++ b/include/linux/rculist.h | |||
@@ -180,31 +180,14 @@ static inline void list_splice_init_rcu(struct list_head *list, | |||
180 | * as long as the traversal is guarded by rcu_read_lock(). | 180 | * as long as the traversal is guarded by rcu_read_lock(). |
181 | */ | 181 | */ |
182 | #define list_for_each_rcu(pos, head) \ | 182 | #define list_for_each_rcu(pos, head) \ |
183 | for (pos = (head)->next; \ | 183 | for (pos = rcu_dereference((head)->next); \ |
184 | prefetch(rcu_dereference(pos)->next), pos != (head); \ | 184 | prefetch(pos->next), pos != (head); \ |
185 | pos = pos->next) | 185 | pos = rcu_dereference(pos->next)) |
186 | 186 | ||
187 | #define __list_for_each_rcu(pos, head) \ | 187 | #define __list_for_each_rcu(pos, head) \ |
188 | for (pos = (head)->next; \ | 188 | for (pos = rcu_dereference((head)->next); \ |
189 | rcu_dereference(pos) != (head); \ | 189 | pos != (head); \ |
190 | pos = pos->next) | 190 | pos = rcu_dereference(pos->next)) |
191 | |||
192 | /** | ||
193 | * list_for_each_safe_rcu | ||
194 | * @pos: the &struct list_head to use as a loop cursor. | ||
195 | * @n: another &struct list_head to use as temporary storage | ||
196 | * @head: the head for your list. | ||
197 | * | ||
198 | * Iterate over an rcu-protected list, safe against removal of list entry. | ||
199 | * | ||
200 | * This list-traversal primitive may safely run concurrently with | ||
201 | * the _rcu list-mutation primitives such as list_add_rcu() | ||
202 | * as long as the traversal is guarded by rcu_read_lock(). | ||
203 | */ | ||
204 | #define list_for_each_safe_rcu(pos, n, head) \ | ||
205 | for (pos = (head)->next; \ | ||
206 | n = rcu_dereference(pos)->next, pos != (head); \ | ||
207 | pos = n) | ||
208 | 191 | ||
209 | /** | 192 | /** |
210 | * list_for_each_entry_rcu - iterate over rcu list of given type | 193 | * 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, | |||
217 | * as long as the traversal is guarded by rcu_read_lock(). | 200 | * as long as the traversal is guarded by rcu_read_lock(). |
218 | */ | 201 | */ |
219 | #define list_for_each_entry_rcu(pos, head, member) \ | 202 | #define list_for_each_entry_rcu(pos, head, member) \ |
220 | for (pos = list_entry((head)->next, typeof(*pos), member); \ | 203 | for (pos = list_entry(rcu_dereference((head)->next), typeof(*pos), member); \ |
221 | prefetch(rcu_dereference(pos)->member.next), \ | 204 | prefetch(pos->member.next), &pos->member != (head); \ |
222 | &pos->member != (head); \ | 205 | pos = list_entry(rcu_dereference(pos->member.next), typeof(*pos), member)) |
223 | pos = list_entry(pos->member.next, typeof(*pos), member)) | ||
224 | 206 | ||
225 | 207 | ||
226 | /** | 208 | /** |
@@ -235,9 +217,9 @@ static inline void list_splice_init_rcu(struct list_head *list, | |||
235 | * as long as the traversal is guarded by rcu_read_lock(). | 217 | * as long as the traversal is guarded by rcu_read_lock(). |
236 | */ | 218 | */ |
237 | #define list_for_each_continue_rcu(pos, head) \ | 219 | #define list_for_each_continue_rcu(pos, head) \ |
238 | for ((pos) = (pos)->next; \ | 220 | for ((pos) = rcu_dereference((pos)->next); \ |
239 | prefetch(rcu_dereference((pos))->next), (pos) != (head); \ | 221 | prefetch((pos)->next), (pos) != (head); \ |
240 | (pos) = (pos)->next) | 222 | (pos) = rcu_dereference((pos)->next)) |
241 | 223 | ||
242 | /** | 224 | /** |
243 | * hlist_del_rcu - deletes entry from hash list without re-initialization | 225 | * 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, | |||
382 | * as long as the traversal is guarded by rcu_read_lock(). | 364 | * as long as the traversal is guarded by rcu_read_lock(). |
383 | */ | 365 | */ |
384 | #define hlist_for_each_entry_rcu(tpos, pos, head, member) \ | 366 | #define hlist_for_each_entry_rcu(tpos, pos, head, member) \ |
385 | for (pos = (head)->first; \ | 367 | for (pos = rcu_dereference((head)->first); \ |
386 | rcu_dereference(pos) && ({ prefetch(pos->next); 1; }) && \ | 368 | pos && ({ prefetch(pos->next); 1; }) && \ |
387 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ | 369 | ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ |
388 | pos = pos->next) | 370 | pos = rcu_dereference(pos->next)) |
389 | 371 | ||
390 | #endif /* __KERNEL__ */ | 372 | #endif /* __KERNEL__ */ |
391 | #endif | 373 | #endif |