cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

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