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