1#ifndef _LINUX_RCULIST_NULLS_H 2#define _LINUX_RCULIST_NULLS_H 3 4#ifdef __KERNEL__ 5 6/* 7 * RCU-protected list version 8 */ 9#include <linux/list_nulls.h> 10#include <linux/rcupdate.h> 11 12/** 13 * hlist_nulls_del_init_rcu - deletes entry from hash list with re-initialization 14 * @n: the element to delete from the hash list. 15 * 16 * Note: hlist_nulls_unhashed() on the node return true after this. It is 17 * useful for RCU based read lockfree traversal if the writer side 18 * must know if the list entry is still hashed or already unhashed. 19 * 20 * In particular, it means that we can not poison the forward pointers 21 * that may still be used for walking the hash list and we can only 22 * zero the pprev pointer so list_unhashed() will return true after 23 * this. 24 * 25 * The caller must take whatever precautions are necessary (such as 26 * holding appropriate locks) to avoid racing with another 27 * list-mutation primitive, such as hlist_nulls_add_head_rcu() or 28 * hlist_nulls_del_rcu(), running on this same list. However, it is 29 * perfectly legal to run concurrently with the _rcu list-traversal 30 * primitives, such as hlist_nulls_for_each_entry_rcu(). 31 */ 32static inline void hlist_nulls_del_init_rcu(struct hlist_nulls_node *n) 33{ 34 if (!hlist_nulls_unhashed(n)) { 35 __hlist_nulls_del(n); 36 n->pprev = NULL; 37 } 38} 39 40#define hlist_nulls_first_rcu(head) \ 41 (*((struct hlist_nulls_node __rcu __force **)&(head)->first)) 42 43#define hlist_nulls_next_rcu(node) \ 44 (*((struct hlist_nulls_node __rcu __force **)&(node)->next)) 45 46/** 47 * hlist_nulls_del_rcu - deletes entry from hash list without re-initialization 48 * @n: the element to delete from the hash list. 49 * 50 * Note: hlist_nulls_unhashed() on entry does not return true after this, 51 * the entry is in an undefined state. It is useful for RCU based 52 * lockfree traversal. 53 * 54 * In particular, it means that we can not poison the forward 55 * pointers that may still be used for walking the hash list. 56 * 57 * The caller must take whatever precautions are necessary 58 * (such as holding appropriate locks) to avoid racing 59 * with another list-mutation primitive, such as hlist_nulls_add_head_rcu() 60 * or hlist_nulls_del_rcu(), running on this same list. 61 * However, it is perfectly legal to run concurrently with 62 * the _rcu list-traversal primitives, such as 63 * hlist_nulls_for_each_entry(). 64 */ 65static inline void hlist_nulls_del_rcu(struct hlist_nulls_node *n) 66{ 67 __hlist_nulls_del(n); 68 n->pprev = LIST_POISON2; 69} 70 71/** 72 * hlist_nulls_add_head_rcu 73 * @n: the element to add to the hash list. 74 * @h: the list to add to. 75 * 76 * Description: 77 * Adds the specified element to the specified hlist_nulls, 78 * while permitting racing traversals. 79 * 80 * The caller must take whatever precautions are necessary 81 * (such as holding appropriate locks) to avoid racing 82 * with another list-mutation primitive, such as hlist_nulls_add_head_rcu() 83 * or hlist_nulls_del_rcu(), running on this same list. 84 * However, it is perfectly legal to run concurrently with 85 * the _rcu list-traversal primitives, such as 86 * hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency 87 * problems on Alpha CPUs. Regardless of the type of CPU, the 88 * list-traversal primitive must be guarded by rcu_read_lock(). 89 */ 90static inline void hlist_nulls_add_head_rcu(struct hlist_nulls_node *n, 91 struct hlist_nulls_head *h) 92{ 93 struct hlist_nulls_node *first = h->first; 94 95 n->next = first; 96 n->pprev = &h->first; 97 rcu_assign_pointer(hlist_nulls_first_rcu(h), n); 98 if (!is_a_nulls(first)) 99 first->pprev = &n->next; 100} 101/** 102 * hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type 103 * @tpos: the type * to use as a loop cursor. 104 * @pos: the &struct hlist_nulls_node to use as a loop cursor. 105 * @head: the head for your list. 106 * @member: the name of the hlist_nulls_node within the struct. 107 * 108 * The barrier() is needed to make sure compiler doesn't cache first element [1], 109 * as this loop can be restarted [2] 110 * [1] Documentation/atomic_ops.txt around line 114 111 * [2] Documentation/RCU/rculist_nulls.txt around line 146 112 */ 113#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \ 114 for (({barrier();}), \ 115 pos = rcu_dereference_raw(hlist_nulls_first_rcu(head)); \ 116 (!is_a_nulls(pos)) && \ 117 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \ 118 pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos))) 119 120#endif 121#endif 122