rculist_bl.h (3374B)
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 11static 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 21static 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 */ 46static 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 */ 71static 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