at v4.13 174 lines 6.3 kB view raw
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/** 103 * hlist_nulls_add_tail_rcu 104 * @n: the element to add to the hash list. 105 * @h: the list to add to. 106 * 107 * Description: 108 * Adds the specified element to the end of the specified hlist_nulls, 109 * while permitting racing traversals. NOTE: tail insertion requires 110 * list traversal. 111 * 112 * The caller must take whatever precautions are necessary 113 * (such as holding appropriate locks) to avoid racing 114 * with another list-mutation primitive, such as hlist_nulls_add_head_rcu() 115 * or hlist_nulls_del_rcu(), running on this same list. 116 * However, it is perfectly legal to run concurrently with 117 * the _rcu list-traversal primitives, such as 118 * hlist_nulls_for_each_entry_rcu(), used to prevent memory-consistency 119 * problems on Alpha CPUs. Regardless of the type of CPU, the 120 * list-traversal primitive must be guarded by rcu_read_lock(). 121 */ 122static inline void hlist_nulls_add_tail_rcu(struct hlist_nulls_node *n, 123 struct hlist_nulls_head *h) 124{ 125 struct hlist_nulls_node *i, *last = NULL; 126 127 for (i = hlist_nulls_first_rcu(h); !is_a_nulls(i); 128 i = hlist_nulls_next_rcu(i)) 129 last = i; 130 131 if (last) { 132 n->next = last->next; 133 n->pprev = &last->next; 134 rcu_assign_pointer(hlist_nulls_next_rcu(last), n); 135 } else { 136 hlist_nulls_add_head_rcu(n, h); 137 } 138} 139 140/** 141 * hlist_nulls_for_each_entry_rcu - iterate over rcu list of given type 142 * @tpos: the type * to use as a loop cursor. 143 * @pos: the &struct hlist_nulls_node to use as a loop cursor. 144 * @head: the head for your list. 145 * @member: the name of the hlist_nulls_node within the struct. 146 * 147 * The barrier() is needed to make sure compiler doesn't cache first element [1], 148 * as this loop can be restarted [2] 149 * [1] Documentation/atomic_ops.txt around line 114 150 * [2] Documentation/RCU/rculist_nulls.txt around line 146 151 */ 152#define hlist_nulls_for_each_entry_rcu(tpos, pos, head, member) \ 153 for (({barrier();}), \ 154 pos = rcu_dereference_raw(hlist_nulls_first_rcu(head)); \ 155 (!is_a_nulls(pos)) && \ 156 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); 1; }); \ 157 pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos))) 158 159/** 160 * hlist_nulls_for_each_entry_safe - 161 * iterate over list of given type safe against removal of list entry 162 * @tpos: the type * to use as a loop cursor. 163 * @pos: the &struct hlist_nulls_node to use as a loop cursor. 164 * @head: the head for your list. 165 * @member: the name of the hlist_nulls_node within the struct. 166 */ 167#define hlist_nulls_for_each_entry_safe(tpos, pos, head, member) \ 168 for (({barrier();}), \ 169 pos = rcu_dereference_raw(hlist_nulls_first_rcu(head)); \ 170 (!is_a_nulls(pos)) && \ 171 ({ tpos = hlist_nulls_entry(pos, typeof(*tpos), member); \ 172 pos = rcu_dereference_raw(hlist_nulls_next_rcu(pos)); 1; });) 173#endif 174#endif