root/include/linux/rculist_bl.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. hlist_bl_set_first_rcu
  2. hlist_bl_first_rcu
  3. hlist_bl_del_init_rcu
  4. hlist_bl_del_rcu
  5. hlist_bl_add_head_rcu

   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_init_rcu - deletes entry from hash list with re-initialization
  29  * @n: the element to delete from the hash list.
  30  *
  31  * Note: hlist_bl_unhashed() on the node returns true after this. It is
  32  * useful for RCU based read lockfree traversal if the writer side
  33  * must know if the list entry is still hashed or already unhashed.
  34  *
  35  * In particular, it means that we can not poison the forward pointers
  36  * that may still be used for walking the hash list and we can only
  37  * zero the pprev pointer so list_unhashed() will return true after
  38  * this.
  39  *
  40  * The caller must take whatever precautions are necessary (such as
  41  * holding appropriate locks) to avoid racing with another
  42  * list-mutation primitive, such as hlist_bl_add_head_rcu() or
  43  * hlist_bl_del_rcu(), running on this same list.  However, it is
  44  * perfectly legal to run concurrently with the _rcu list-traversal
  45  * primitives, such as hlist_bl_for_each_entry_rcu().
  46  */
  47 static inline void hlist_bl_del_init_rcu(struct hlist_bl_node *n)
  48 {
  49         if (!hlist_bl_unhashed(n)) {
  50                 __hlist_bl_del(n);
  51                 n->pprev = NULL;
  52         }
  53 }
  54 
  55 /**
  56  * hlist_bl_del_rcu - deletes entry from hash list without re-initialization
  57  * @n: the element to delete from the hash list.
  58  *
  59  * Note: hlist_bl_unhashed() on entry does not return true after this,
  60  * the entry is in an undefined state. It is useful for RCU based
  61  * lockfree traversal.
  62  *
  63  * In particular, it means that we can not poison the forward
  64  * pointers that may still be used for walking the hash list.
  65  *
  66  * The caller must take whatever precautions are necessary
  67  * (such as holding appropriate locks) to avoid racing
  68  * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
  69  * or hlist_bl_del_rcu(), running on this same list.
  70  * However, it is perfectly legal to run concurrently with
  71  * the _rcu list-traversal primitives, such as
  72  * hlist_bl_for_each_entry().
  73  */
  74 static inline void hlist_bl_del_rcu(struct hlist_bl_node *n)
  75 {
  76         __hlist_bl_del(n);
  77         n->pprev = LIST_POISON2;
  78 }
  79 
  80 /**
  81  * hlist_bl_add_head_rcu
  82  * @n: the element to add to the hash list.
  83  * @h: the list to add to.
  84  *
  85  * Description:
  86  * Adds the specified element to the specified hlist_bl,
  87  * while permitting racing traversals.
  88  *
  89  * The caller must take whatever precautions are necessary
  90  * (such as holding appropriate locks) to avoid racing
  91  * with another list-mutation primitive, such as hlist_bl_add_head_rcu()
  92  * or hlist_bl_del_rcu(), running on this same list.
  93  * However, it is perfectly legal to run concurrently with
  94  * the _rcu list-traversal primitives, such as
  95  * hlist_bl_for_each_entry_rcu(), used to prevent memory-consistency
  96  * problems on Alpha CPUs.  Regardless of the type of CPU, the
  97  * list-traversal primitive must be guarded by rcu_read_lock().
  98  */
  99 static inline void hlist_bl_add_head_rcu(struct hlist_bl_node *n,
 100                                         struct hlist_bl_head *h)
 101 {
 102         struct hlist_bl_node *first;
 103 
 104         /* don't need hlist_bl_first_rcu because we're under lock */
 105         first = hlist_bl_first(h);
 106 
 107         n->next = first;
 108         if (first)
 109                 first->pprev = &n->next;
 110         n->pprev = &h->first;
 111 
 112         /* need _rcu because we can have concurrent lock free readers */
 113         hlist_bl_set_first_rcu(h, n);
 114 }
 115 /**
 116  * hlist_bl_for_each_entry_rcu - iterate over rcu list of given type
 117  * @tpos:       the type * to use as a loop cursor.
 118  * @pos:        the &struct hlist_bl_node to use as a loop cursor.
 119  * @head:       the head for your list.
 120  * @member:     the name of the hlist_bl_node within the struct.
 121  *
 122  */
 123 #define hlist_bl_for_each_entry_rcu(tpos, pos, head, member)            \
 124         for (pos = hlist_bl_first_rcu(head);                            \
 125                 pos &&                                                  \
 126                 ({ tpos = hlist_bl_entry(pos, typeof(*tpos), member); 1; }); \
 127                 pos = rcu_dereference_raw(pos->next))
 128 
 129 #endif

/* [<][>][^][v][top][bottom][index][help] */