Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef _LINUX_RCULIST_BL_H
0003 #define _LINUX_RCULIST_BL_H
0004 
0005 /*
0006  * RCU-protected bl list version. See include/linux/list_bl.h.
0007  */
0008 #include <linux/list_bl.h>
0009 #include <linux/rcupdate.h>
0010 
0011 static inline void hlist_bl_set_first_rcu(struct hlist_bl_head *h,
0012                     struct hlist_bl_node *n)
0013 {
0014     LIST_BL_BUG_ON((unsigned long)n & LIST_BL_LOCKMASK);
0015     LIST_BL_BUG_ON(((unsigned long)h->first & LIST_BL_LOCKMASK) !=
0016                             LIST_BL_LOCKMASK);
0017     rcu_assign_pointer(h->first,
0018         (struct hlist_bl_node *)((unsigned long)n | LIST_BL_LOCKMASK));
0019 }
0020 
0021 static inline struct hlist_bl_node *hlist_bl_first_rcu(struct hlist_bl_head *h)
0022 {
0023     return (struct hlist_bl_node *)
0024         ((unsigned long)rcu_dereference_check(h->first, hlist_bl_is_locked(h)) & ~LIST_BL_LOCKMASK);
0025 }
0026 
0027 /**
0028  * hlist_bl_del_rcu - deletes entry from hash list without re-initialization
0029  * @n: the element to delete from the hash list.
0030  *
0031  * Note: hlist_bl_unhashed() on entry does not return true after this,
0032  * the entry is in an undefined state. It is useful for RCU based
0033  * lockfree traversal.
0034  *
0035  * In particular, it means that we can not poison the forward
0036  * pointers that may still be used for walking the hash list.
0037  *
0038  * The caller must take whatever precautions are necessary
0039  * (such as holding appropriate locks) to avoid racing
0040  * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
0041  * or hlist_bl_del_rcu(), running on this same list.
0042  * However, it is perfectly legal to run concurrently with
0043  * the _rcu list-traversal primitives, such as
0044  * hlist_bl_for_each_entry().
0045  */
0046 static inline void hlist_bl_del_rcu(struct hlist_bl_node *n)
0047 {
0048     __hlist_bl_del(n);
0049     n->pprev = LIST_POISON2;
0050 }
0051 
0052 /**
0053  * hlist_bl_add_head_rcu
0054  * @n: the element to add to the hash list.
0055  * @h: the list to add to.
0056  *
0057  * Description:
0058  * Adds the specified element to the specified hlist_bl,
0059  * while permitting racing traversals.
0060  *
0061  * The caller must take whatever precautions are necessary
0062  * (such as holding appropriate locks) to avoid racing
0063  * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
0064  * or hlist_bl_del_rcu(), running on this same list.
0065  * However, it is perfectly legal to run concurrently with
0066  * the _rcu list-traversal primitives, such as
0067  * hlist_bl_for_each_entry_rcu(), used to prevent memory-consistency
0068  * problems on Alpha CPUs.  Regardless of the type of CPU, the
0069  * list-traversal primitive must be guarded by rcu_read_lock().
0070  */
0071 static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
0072                     struct hlist_bl_head *h)
0073 {
0074     struct hlist_bl_node *first;
0075 
0076     /* don't need hlist_bl_first_rcu because we're under lock */
0077     first = hlist_bl_first(h);
0078 
0079     n->next = first;
0080     if (first)
0081         first->pprev = &n->next;
0082     n->pprev = &h->first;
0083 
0084     /* need _rcu because we can have concurrent lock free readers */
0085     hlist_bl_set_first_rcu(h, n);
0086 }
0087 /**
0088  * hlist_bl_for_each_entry_rcu - iterate over rcu list of given type
0089  * @tpos:   the type * to use as a loop cursor.
0090  * @pos:    the &struct hlist_bl_node to use as a loop cursor.
0091  * @head:   the head for your list.
0092  * @member: the name of the hlist_bl_node within the struct.
0093  *
0094  */
0095 #define hlist_bl_for_each_entry_rcu(tpos, pos, head, member)        \
0096     for (pos = hlist_bl_first_rcu(head);                \
0097         pos &&                          \
0098         ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
0099         pos = rcu_dereference_raw(pos->next))
0100 
0101 #endif