Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rculist_bl: add hlist_bl_for_each_entry_continue_rcu

Change the old hlist_bl_first_rcu to hlist_bl_first_rcu_dereference
to indicate that it is a RCU dereference.

Add hlist_bl_next_rcu and hlist_bl_first_rcu to use RCU pointers
and use them to fix sparse warnings.

Add hlist_bl_for_each_entry_continue_rcu.

Signed-off-by: Julian Anastasov <ja@ssi.bg>
Signed-off-by: Florian Westphal <fw@strlen.de>

authored by

Julian Anastasov and committed by
Florian Westphal
1ac252ad 34a6a003

+40 -9
+40 -9
include/linux/rculist_bl.h
··· 8 8 #include <linux/list_bl.h> 9 9 #include <linux/rcupdate.h> 10 10 11 + /* return the first ptr or next element in an RCU protected list */ 12 + #define hlist_bl_first_rcu(head) \ 13 + (*((struct hlist_bl_node __rcu **)(&(head)->first))) 14 + #define hlist_bl_next_rcu(node) \ 15 + (*((struct hlist_bl_node __rcu **)(&(node)->next))) 16 + 11 17 static inline void hlist_bl_set_first_rcu(struct hlist_bl_head *h, 12 18 struct hlist_bl_node *n) 13 19 { 14 20 LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK); 15 21 LIST_BL_BUG_ON(((unsigned long)h->first & LIST_BL_LOCKMASK) != 16 22 LIST_BL_LOCKMASK); 17 - rcu_assign_pointer(h->first, 23 + rcu_assign_pointer(hlist_bl_first_rcu(h), 18 24 (struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK)); 19 25 } 20 26 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 - } 27 + #define hlist_bl_first_rcu_dereference(head) \ 28 + ({ \ 29 + struct hlist_bl_head *__head = (head); \ 30 + \ 31 + (struct hlist_bl_node *) \ 32 + ((unsigned long)rcu_dereference_check(hlist_bl_first_rcu(__head), \ 33 + hlist_bl_is_locked(__head)) & \ 34 + ~LIST_BL_LOCKMASK); \ 35 + }) 26 36 27 37 /** 28 38 * hlist_bl_del_rcu - deletes entry from hash list without re-initialization ··· 83 73 { 84 74 struct hlist_bl_node *first; 85 75 86 - /* don't need hlist_bl_first_rcu because we're under lock */ 76 + /* don't need hlist_bl_first_rcu* because we're under lock */ 87 77 first = hlist_bl_first(h); 88 78 89 79 n->next = first; ··· 103 93 * 104 94 */ 105 95 #define hlist_bl_for_each_entry_rcu(tpos, pos, head, member) \ 106 - for (pos = hlist_bl_first_rcu(head); \ 96 + for (pos = hlist_bl_first_rcu_dereference(head); \ 107 97 pos && \ 108 98 ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \ 109 - pos = rcu_dereference_raw(pos->next)) 99 + pos = rcu_dereference_raw(hlist_bl_next_rcu(pos))) 100 + 101 + /** 102 + * hlist_bl_for_each_entry_continue_rcu - continue iteration over list of given 103 + * type 104 + * @tpos: the type * to use as a loop cursor. 105 + * @pos: the &struct hlist_bl_node to use as a loop cursor. 106 + * @member: the name of the hlist_bl_node within the struct. 107 + * 108 + * Continue to iterate over list of given type, continuing after 109 + * the current position which must have been in the list when the RCU read 110 + * lock was taken. 111 + * This would typically require either that you obtained the node from a 112 + * previous walk of the list in the same RCU read-side critical section, or 113 + * that you held some sort of non-RCU reference (such as a reference count) 114 + * to keep the node alive *and* in the list. 115 + */ 116 + #define hlist_bl_for_each_entry_continue_rcu(tpos, pos, member) \ 117 + for (pos = rcu_dereference_raw(hlist_bl_next_rcu(&(tpos)->member)); \ 118 + pos && \ 119 + ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \ 120 + pos = rcu_dereference_raw(hlist_bl_next_rcu(pos))) 110 121 111 122 #endif