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