aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/rculist.h
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /include/linux/rculist.h
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'include/linux/rculist.h')
-rw-r--r--include/linux/rculist.h77
1 files changed, 48 insertions, 29 deletions
diff --git a/include/linux/rculist.h b/include/linux/rculist.h
index 4ec3b38ce9c5..e3beb315517a 100644
--- a/include/linux/rculist.h
+++ b/include/linux/rculist.h
@@ -10,6 +10,21 @@
10#include <linux/rcupdate.h> 10#include <linux/rcupdate.h>
11 11
12/* 12/*
13 * Why is there no list_empty_rcu()? Because list_empty() serves this
14 * purpose. The list_empty() function fetches the RCU-protected pointer
15 * and compares it to the address of the list head, but neither dereferences
16 * this pointer itself nor provides this pointer to the caller. Therefore,
17 * it is not necessary to use rcu_dereference(), so that list_empty() can
18 * be used anywhere you would want to use a list_empty_rcu().
19 */
20
21/*
22 * return the ->next pointer of a list_head in an rcu safe
23 * way, we must not access it directly
24 */
25#define list_next_rcu(list) (*((struct list_head __rcu **)(&(list)->next)))
26
27/*
13 * Insert a new entry between two known consecutive entries. 28 * Insert a new entry between two known consecutive entries.
14 * 29 *
15 * This is only for internal list manipulation where we know 30 * This is only for internal list manipulation where we know
@@ -20,7 +35,7 @@ static inline void __list_add_rcu(struct list_head *new,
20{ 35{
21 new->next = next; 36 new->next = next;
22 new->prev = prev; 37 new->prev = prev;
23 rcu_assign_pointer(prev->next, new); 38 rcu_assign_pointer(list_next_rcu(prev), new);
24 next->prev = new; 39 next->prev = new;
25} 40}
26 41
@@ -138,7 +153,7 @@ static inline void list_replace_rcu(struct list_head *old,
138{ 153{
139 new->next = old->next; 154 new->next = old->next;
140 new->prev = old->prev; 155 new->prev = old->prev;
141 rcu_assign_pointer(new->prev->next, new); 156 rcu_assign_pointer(list_next_rcu(new->prev), new);
142 new->next->prev = new; 157 new->next->prev = new;
143 old->prev = LIST_POISON2; 158 old->prev = LIST_POISON2;
144} 159}
@@ -193,7 +208,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
193 */ 208 */
194 209
195 last->next = at; 210 last->next = at;
196 rcu_assign_pointer(head->next, first); 211 rcu_assign_pointer(list_next_rcu(head), first);
197 first->prev = head; 212 first->prev = head;
198 at->prev = last; 213 at->prev = last;
199} 214}
@@ -208,7 +223,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
208 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). 223 * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock().
209 */ 224 */
210#define list_entry_rcu(ptr, type, member) \ 225#define list_entry_rcu(ptr, type, member) \
211 container_of(rcu_dereference_raw(ptr), type, member) 226 ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \
227 container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \
228 })
212 229
213/** 230/**
214 * list_first_entry_rcu - get the first element from a list 231 * list_first_entry_rcu - get the first element from a list
@@ -224,11 +241,6 @@ static inline void list_splice_init_rcu(struct list_head *list,
224#define list_first_entry_rcu(ptr, type, member) \ 241#define list_first_entry_rcu(ptr, type, member) \
225 list_entry_rcu((ptr)->next, type, member) 242 list_entry_rcu((ptr)->next, type, member)
226 243
227#define __list_for_each_rcu(pos, head) \
228 for (pos = rcu_dereference_raw((head)->next); \
229 pos != (head); \
230 pos = rcu_dereference_raw(pos->next))
231
232/** 244/**
233 * list_for_each_entry_rcu - iterate over rcu list of given type 245 * list_for_each_entry_rcu - iterate over rcu list of given type
234 * @pos: the type * to use as a loop cursor. 246 * @pos: the type * to use as a loop cursor.
@@ -241,7 +253,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
241 */ 253 */
242#define list_for_each_entry_rcu(pos, head, member) \ 254#define list_for_each_entry_rcu(pos, head, member) \
243 for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \ 255 for (pos = list_entry_rcu((head)->next, typeof(*pos), member); \
244 prefetch(pos->member.next), &pos->member != (head); \ 256 &pos->member != (head); \
245 pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) 257 pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
246 258
247 259
@@ -257,9 +269,9 @@ static inline void list_splice_init_rcu(struct list_head *list,
257 * as long as the traversal is guarded by rcu_read_lock(). 269 * as long as the traversal is guarded by rcu_read_lock().
258 */ 270 */
259#define list_for_each_continue_rcu(pos, head) \ 271#define list_for_each_continue_rcu(pos, head) \
260 for ((pos) = rcu_dereference_raw((pos)->next); \ 272 for ((pos) = rcu_dereference_raw(list_next_rcu(pos)); \
261 prefetch((pos)->next), (pos) != (head); \ 273 (pos) != (head); \
262 (pos) = rcu_dereference_raw((pos)->next)) 274 (pos) = rcu_dereference_raw(list_next_rcu(pos)))
263 275
264/** 276/**
265 * list_for_each_entry_continue_rcu - continue iteration over list of given type 277 * list_for_each_entry_continue_rcu - continue iteration over list of given type
@@ -272,7 +284,7 @@ static inline void list_splice_init_rcu(struct list_head *list,
272 */ 284 */
273#define list_for_each_entry_continue_rcu(pos, head, member) \ 285#define list_for_each_entry_continue_rcu(pos, head, member) \
274 for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \ 286 for (pos = list_entry_rcu(pos->member.next, typeof(*pos), member); \
275 prefetch(pos->member.next), &pos->member != (head); \ 287 &pos->member != (head); \
276 pos = list_entry_rcu(pos->member.next, typeof(*pos), member)) 288 pos = list_entry_rcu(pos->member.next, typeof(*pos), member))
277 289
278/** 290/**
@@ -314,12 +326,19 @@ static inline void hlist_replace_rcu(struct hlist_node *old,
314 326
315 new->next = next; 327 new->next = next;
316 new->pprev = old->pprev; 328 new->pprev = old->pprev;
317 rcu_assign_pointer(*new->pprev, new); 329 rcu_assign_pointer(*(struct hlist_node __rcu **)new->pprev, new);
318 if (next) 330 if (next)
319 new->next->pprev = &new->next; 331 new->next->pprev = &new->next;
320 old->pprev = LIST_POISON2; 332 old->pprev = LIST_POISON2;
321} 333}
322 334
335/*
336 * return the first or the next element in an RCU protected hlist
337 */
338#define hlist_first_rcu(head) (*((struct hlist_node __rcu **)(&(head)->first)))
339#define hlist_next_rcu(node) (*((struct hlist_node __rcu **)(&(node)->next)))
340#define hlist_pprev_rcu(node) (*((struct hlist_node __rcu **)((node)->pprev)))
341
323/** 342/**
324 * hlist_add_head_rcu 343 * hlist_add_head_rcu
325 * @n: the element to add to the hash list. 344 * @n: the element to add to the hash list.
@@ -346,7 +365,7 @@ static inline void hlist_add_head_rcu(struct hlist_node *n,
346 365
347 n->next = first; 366 n->next = first;
348 n->pprev = &h->first; 367 n->pprev = &h->first;
349 rcu_assign_pointer(h->first, n); 368 rcu_assign_pointer(hlist_first_rcu(h), n);
350 if (first) 369 if (first)
351 first->pprev = &n->next; 370 first->pprev = &n->next;
352} 371}
@@ -374,7 +393,7 @@ static inline void hlist_add_before_rcu(struct hlist_node *n,
374{ 393{
375 n->pprev = next->pprev; 394 n->pprev = next->pprev;
376 n->next = next; 395 n->next = next;
377 rcu_assign_pointer(*(n->pprev), n); 396 rcu_assign_pointer(hlist_pprev_rcu(n), n);
378 next->pprev = &n->next; 397 next->pprev = &n->next;
379} 398}
380 399
@@ -401,15 +420,15 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
401{ 420{
402 n->next = prev->next; 421 n->next = prev->next;
403 n->pprev = &prev->next; 422 n->pprev = &prev->next;
404 rcu_assign_pointer(prev->next, n); 423 rcu_assign_pointer(hlist_next_rcu(prev), n);
405 if (n->next) 424 if (n->next)
406 n->next->pprev = &n->next; 425 n->next->pprev = &n->next;
407} 426}
408 427
409#define __hlist_for_each_rcu(pos, head) \ 428#define __hlist_for_each_rcu(pos, head) \
410 for (pos = rcu_dereference((head)->first); \ 429 for (pos = rcu_dereference(hlist_first_rcu(head)); \
411 pos && ({ prefetch(pos->next); 1; }); \ 430 pos; \
412 pos = rcu_dereference(pos->next)) 431 pos = rcu_dereference(hlist_next_rcu(pos)))
413 432
414/** 433/**
415 * hlist_for_each_entry_rcu - iterate over rcu list of given type 434 * hlist_for_each_entry_rcu - iterate over rcu list of given type
@@ -422,11 +441,11 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
422 * the _rcu list-mutation primitives such as hlist_add_head_rcu() 441 * the _rcu list-mutation primitives such as hlist_add_head_rcu()
423 * as long as the traversal is guarded by rcu_read_lock(). 442 * as long as the traversal is guarded by rcu_read_lock().
424 */ 443 */
425#define hlist_for_each_entry_rcu(tpos, pos, head, member) \ 444#define hlist_for_each_entry_rcu(tpos, pos, head, member) \
426 for (pos = rcu_dereference_raw((head)->first); \ 445 for (pos = rcu_dereference_raw(hlist_first_rcu(head)); \
427 pos && ({ prefetch(pos->next); 1; }) && \ 446 pos && \
428 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ 447 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
429 pos = rcu_dereference_raw(pos->next)) 448 pos = rcu_dereference_raw(hlist_next_rcu(pos)))
430 449
431/** 450/**
432 * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type 451 * hlist_for_each_entry_rcu_bh - iterate over rcu list of given type
@@ -441,7 +460,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
441 */ 460 */
442#define hlist_for_each_entry_rcu_bh(tpos, pos, head, member) \ 461#define hlist_for_each_entry_rcu_bh(tpos, pos, head, member) \
443 for (pos = rcu_dereference_bh((head)->first); \ 462 for (pos = rcu_dereference_bh((head)->first); \
444 pos && ({ prefetch(pos->next); 1; }) && \ 463 pos && \
445 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ 464 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
446 pos = rcu_dereference_bh(pos->next)) 465 pos = rcu_dereference_bh(pos->next))
447 466
@@ -453,7 +472,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
453 */ 472 */
454#define hlist_for_each_entry_continue_rcu(tpos, pos, member) \ 473#define hlist_for_each_entry_continue_rcu(tpos, pos, member) \
455 for (pos = rcu_dereference((pos)->next); \ 474 for (pos = rcu_dereference((pos)->next); \
456 pos && ({ prefetch(pos->next); 1; }) && \ 475 pos && \
457 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ 476 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
458 pos = rcu_dereference(pos->next)) 477 pos = rcu_dereference(pos->next))
459 478
@@ -465,7 +484,7 @@ static inline void hlist_add_after_rcu(struct hlist_node *prev,
465 */ 484 */
466#define hlist_for_each_entry_continue_rcu_bh(tpos, pos, member) \ 485#define hlist_for_each_entry_continue_rcu_bh(tpos, pos, member) \
467 for (pos = rcu_dereference_bh((pos)->next); \ 486 for (pos = rcu_dereference_bh((pos)->next); \
468 pos && ({ prefetch(pos->next); 1; }) && \ 487 pos && \
469 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \ 488 ({ tpos = hlist_entry(pos, typeof(*tpos), member); 1; }); \
470 pos = rcu_dereference_bh(pos->next)) 489 pos = rcu_dereference_bh(pos->next))
471 490