linux/include/linux/rculist_bl.h
<<
>>
Prefs
   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
 102