Rev 4103 | Rev 5270 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4103 | Rev 5056 | ||
---|---|---|---|
Line 38... | Line 38... | ||
38 | new->prev = prev; |
38 | new->prev = prev; |
39 | rcu_assign_pointer(list_next_rcu(prev), new); |
39 | rcu_assign_pointer(list_next_rcu(prev), new); |
40 | next->prev = new; |
40 | next->prev = new; |
41 | } |
41 | } |
42 | #else |
42 | #else |
43 | extern void __list_add_rcu(struct list_head *new, |
43 | void __list_add_rcu(struct list_head *new, |
44 | struct list_head *prev, struct list_head *next); |
44 | struct list_head *prev, struct list_head *next); |
45 | #endif |
45 | #endif |
Line 46... | Line 46... | ||
46 | 46 | ||
47 | /** |
47 | /** |
Line 189... | Line 189... | ||
189 | struct list_head *at = head->next; |
189 | struct list_head *at = head->next; |
Line 190... | Line 190... | ||
190 | 190 | ||
191 | if (list_empty(list)) |
191 | if (list_empty(list)) |
Line -... | Line 192... | ||
- | 192 | return; |
|
192 | return; |
193 | |
- | 194 | /* |
|
- | 195 | * "first" and "last" tracking list, so initialize it. RCU readers |
|
- | 196 | * have access to this list, so we must use INIT_LIST_HEAD_RCU() |
|
Line 193... | Line 197... | ||
193 | 197 | * instead of INIT_LIST_HEAD(). |
|
Line 194... | Line 198... | ||
194 | /* "first" and "last" tracking list, so initialize it. */ |
198 | */ |
195 | 199 | ||
Line 226... | Line 230... | ||
226 | * |
230 | * |
227 | * This primitive may safely run concurrently with the _rcu list-mutation |
231 | * This primitive may safely run concurrently with the _rcu list-mutation |
228 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). |
232 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). |
229 | */ |
233 | */ |
230 | #define list_entry_rcu(ptr, type, member) \ |
234 | #define list_entry_rcu(ptr, type, member) \ |
- | 235 | ({ \ |
|
231 | ({typeof (*ptr) __rcu *__ptr = (typeof (*ptr) __rcu __force *)ptr; \ |
236 | typeof(*ptr) __rcu *__ptr = (typeof(*ptr) __rcu __force *)ptr; \ |
232 | container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ |
237 | container_of((typeof(ptr))rcu_dereference_raw(__ptr), type, member); \ |
233 | }) |
238 | }) |
Line 234... | Line 239... | ||
234 | 239 | ||
235 | /** |
240 | /** |
Line 264... | Line 269... | ||
264 | * |
269 | * |
265 | * This primitive may safely run concurrently with the _rcu list-mutation |
270 | * This primitive may safely run concurrently with the _rcu list-mutation |
266 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). |
271 | * primitives such as list_add_rcu() as long as it's guarded by rcu_read_lock(). |
267 | */ |
272 | */ |
268 | #define list_first_or_null_rcu(ptr, type, member) \ |
273 | #define list_first_or_null_rcu(ptr, type, member) \ |
- | 274 | ({ \ |
|
269 | ({struct list_head *__ptr = (ptr); \ |
275 | struct list_head *__ptr = (ptr); \ |
270 | struct list_head *__next = ACCESS_ONCE(__ptr->next); \ |
276 | struct list_head *__next = ACCESS_ONCE(__ptr->next); \ |
271 | likely(__ptr != __next) ? \ |
- | |
272 | list_entry_rcu(__next, type, member) : NULL; \ |
277 | likely(__ptr != __next) ? list_entry_rcu(__next, type, member) : NULL; \ |
273 | }) |
278 | }) |
Line 274... | Line 279... | ||
274 | 279 | ||
275 | /** |
280 | /** |
276 | * list_for_each_entry_rcu - iterate over rcu list of given type |
281 | * list_for_each_entry_rcu - iterate over rcu list of given type |
Line 410... | Line 415... | ||
410 | rcu_assign_pointer(hlist_pprev_rcu(n), n); |
415 | rcu_assign_pointer(hlist_pprev_rcu(n), n); |
411 | next->pprev = &n->next; |
416 | next->pprev = &n->next; |
412 | } |
417 | } |
Line 413... | Line 418... | ||
413 | 418 | ||
414 | /** |
419 | /** |
415 | * hlist_add_after_rcu |
- | |
416 | * @prev: the existing element to add the new element after. |
420 | * hlist_add_behind_rcu |
- | 421 | * @n: the new element to add to the hash list. |
|
417 | * @n: the new element to add to the hash list. |
422 | * @prev: the existing element to add the new element after. |
418 | * |
423 | * |
419 | * Description: |
424 | * Description: |
420 | * Adds the specified element to the specified hlist |
425 | * Adds the specified element to the specified hlist |
421 | * after the specified node while permitting racing traversals. |
426 | * after the specified node while permitting racing traversals. |
Line 427... | Line 432... | ||
427 | * However, it is perfectly legal to run concurrently with |
432 | * However, it is perfectly legal to run concurrently with |
428 | * the _rcu list-traversal primitives, such as |
433 | * the _rcu list-traversal primitives, such as |
429 | * hlist_for_each_entry_rcu(), used to prevent memory-consistency |
434 | * hlist_for_each_entry_rcu(), used to prevent memory-consistency |
430 | * problems on Alpha CPUs. |
435 | * problems on Alpha CPUs. |
431 | */ |
436 | */ |
432 | static inline void hlist_add_after_rcu(struct hlist_node *prev, |
437 | static inline void hlist_add_behind_rcu(struct hlist_node *n, |
433 | struct hlist_node *n) |
438 | struct hlist_node *prev) |
434 | { |
439 | { |
435 | n->next = prev->next; |
440 | n->next = prev->next; |
436 | n->pprev = &prev->next; |
441 | n->pprev = &prev->next; |
437 | rcu_assign_pointer(hlist_next_rcu(prev), n); |
442 | rcu_assign_pointer(hlist_next_rcu(prev), n); |
438 | if (n->next) |
443 | if (n->next) |