Branch data Line data Source code
1 : : #ifndef _LINUX_RCULIST_BL_H
2 : : #define _LINUX_RCULIST_BL_H
3 : :
4 : : /*
5 : : * RCU-protected bl list version. See include/linux/list_bl.h.
6 : : */
7 : : #include <linux/list_bl.h>
8 : : #include <linux/rcupdate.h>
9 : :
10 : : static inline void hlist_bl_set_first_rcu(struct hlist_bl_head *h,
11 : : struct hlist_bl_node *n)
12 : : {
13 : : LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK);
14 : : LIST_BL_BUG_ON(((unsigned long)h->first & LIST_BL_LOCKMASK) !=
15 : : LIST_BL_LOCKMASK);
16 : 930385 : rcu_assign_pointer(h->first,
17 : : (struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK));
18 : : }
19 : :
20 : : static inline struct hlist_bl_node *hlist_bl_first_rcu(struct hlist_bl_head *h)
21 : : {
22 : 15074906 : return (struct hlist_bl_node *)
23 : 15074906 : ((unsigned long)rcu_dereference_check(h->first, hlist_bl_is_locked(h)) & ~LIST_BL_LOCKMASK);
24 : : }
25 : :
26 : : /**
27 : : * hlist_bl_del_init_rcu - deletes entry from hash list with re-initialization
28 : : * @n: the element to delete from the hash list.
29 : : *
30 : : * Note: hlist_bl_unhashed() on the node returns true after this. It is
31 : : * useful for RCU based read lockfree traversal if the writer side
32 : : * must know if the list entry is still hashed or already unhashed.
33 : : *
34 : : * In particular, it means that we can not poison the forward pointers
35 : : * that may still be used for walking the hash list and we can only
36 : : * zero the pprev pointer so list_unhashed() will return true after
37 : : * this.
38 : : *
39 : : * The caller must take whatever precautions are necessary (such as
40 : : * holding appropriate locks) to avoid racing with another
41 : : * list-mutation primitive, such as hlist_bl_add_head_rcu() or
42 : : * hlist_bl_del_rcu(), running on this same list. However, it is
43 : : * perfectly legal to run concurrently with the _rcu list-traversal
44 : : * primitives, such as hlist_bl_for_each_entry_rcu().
45 : : */
46 : : static inline void hlist_bl_del_init_rcu(struct hlist_bl_node *n)
47 : : {
48 : : if (!hlist_bl_unhashed(n)) {
49 : : __hlist_bl_del(n);
50 : : n->pprev = NULL;
51 : : }
52 : : }
53 : :
54 : : /**
55 : : * hlist_bl_del_rcu - deletes entry from hash list without re-initialization
56 : : * @n: the element to delete from the hash list.
57 : : *
58 : : * Note: hlist_bl_unhashed() on entry does not return true after this,
59 : : * the entry is in an undefined state. It is useful for RCU based
60 : : * lockfree traversal.
61 : : *
62 : : * In particular, it means that we can not poison the forward
63 : : * pointers that may still be used for walking the hash list.
64 : : *
65 : : * The caller must take whatever precautions are necessary
66 : : * (such as holding appropriate locks) to avoid racing
67 : : * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
68 : : * or hlist_bl_del_rcu(), running on this same list.
69 : : * However, it is perfectly legal to run concurrently with
70 : : * the _rcu list-traversal primitives, such as
71 : : * hlist_bl_for_each_entry().
72 : : */
73 : : static inline void hlist_bl_del_rcu(struct hlist_bl_node *n)
74 : : {
75 : : __hlist_bl_del(n);
76 : : n->pprev = LIST_POISON2;
77 : : }
78 : :
79 : : /**
80 : : * hlist_bl_add_head_rcu
81 : : * @n: the element to add to the hash list.
82 : : * @h: the list to add to.
83 : : *
84 : : * Description:
85 : : * Adds the specified element to the specified hlist_bl,
86 : : * while permitting racing traversals.
87 : : *
88 : : * The caller must take whatever precautions are necessary
89 : : * (such as holding appropriate locks) to avoid racing
90 : : * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
91 : : * or hlist_bl_del_rcu(), running on this same list.
92 : : * However, it is perfectly legal to run concurrently with
93 : : * the _rcu list-traversal primitives, such as
94 : : * hlist_bl_for_each_entry_rcu(), used to prevent memory-consistency
95 : : * problems on Alpha CPUs. Regardless of the type of CPU, the
96 : : * list-traversal primitive must be guarded by rcu_read_lock().
97 : : */
98 : : static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
99 : : struct hlist_bl_head *h)
100 : : {
101 : : struct hlist_bl_node *first;
102 : :
103 : : /* don't need hlist_bl_first_rcu because we're under lock */
104 : : first = hlist_bl_first(h);
105 : :
106 : 930385 : n->next = first;
107 [ + + ]: 930385 : if (first)
108 : 167820 : first->pprev = &n->next;
109 : 930385 : n->pprev = &h->first;
110 : :
111 : : /* need _rcu because we can have concurrent lock free readers */
112 : : hlist_bl_set_first_rcu(h, n);
113 : : }
114 : : /**
115 : : * hlist_bl_for_each_entry_rcu - iterate over rcu list of given type
116 : : * @tpos: the type * to use as a loop cursor.
117 : : * @pos: the &struct hlist_bl_node to use as a loop cursor.
118 : : * @head: the head for your list.
119 : : * @member: the name of the hlist_bl_node within the struct.
120 : : *
121 : : */
122 : : #define hlist_bl_for_each_entry_rcu(tpos, pos, head, member) \
123 : : for (pos = hlist_bl_first_rcu(head); \
124 : : pos && \
125 : : ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
126 : : pos = rcu_dereference_raw(pos->next))
127 : :
128 : : #endif
|