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 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 ((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 first = hlist_bl_first(h); 78 79 n->next = first; 80 if (first) 81 first->pprev = &n->next; 82 n->pprev = &h->first; 83 84 /* need _rcu because we can have concurrent lock free readers */ 85 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 102
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.