diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /include/linux/rculist.h | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.h | 77 |
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 | ||