Home | History | Annotate | Line # | Download | only in urcu
      1 // SPDX-FileCopyrightText: 2002 Free Software Foundation, Inc.
      2 // SPDX-FileCopyrightText: 2009 Pierre-Marc Fournier
      3 // SPDX-FileCopyrightText: 2010 Mathieu Desnoyers <mathieu.desnoyers (at) efficios.com>
      4 //
      5 // SPDX-License-Identifier: LGPL-2.1-or-later
      6 
      7 /*
      8  * (originally part of the GNU C Library)
      9  * Contributed by Ulrich Drepper <drepper (at) redhat.com>, 2002.
     10  */
     11 
     12 #ifndef _CDS_LIST_H
     13 #define _CDS_LIST_H	1
     14 
     15 #include <urcu/compiler.h>
     16 
     17 /*
     18  * The definitions of this file are adopted from those which can be
     19  * found in the Linux kernel headers to enable people familiar with the
     20  * latter find their way in these sources as well.
     21  */
     22 
     23 /* Basic type for the double-link list. */
     24 struct cds_list_head {
     25 	struct cds_list_head *next, *prev;
     26 };
     27 
     28 /* Define a variable with the head and tail of the list. */
     29 #define CDS_LIST_HEAD(name) \
     30 	struct cds_list_head name = { &(name), &(name) }
     31 
     32 /* Initialize a new list head. */
     33 #define CDS_INIT_LIST_HEAD(ptr) \
     34 	(ptr)->next = (ptr)->prev = (ptr)
     35 
     36 #define CDS_LIST_HEAD_INIT(name) { .next = &(name), .prev = &(name) }
     37 
     38 /* Add new element at the head of the list. */
     39 static inline
     40 void cds_list_add(struct cds_list_head *newp, struct cds_list_head *head)
     41 {
     42 	head->next->prev = newp;
     43 	newp->next = head->next;
     44 	newp->prev = head;
     45 	head->next = newp;
     46 }
     47 
     48 /* Add new element at the tail of the list. */
     49 static inline
     50 void cds_list_add_tail(struct cds_list_head *newp, struct cds_list_head *head)
     51 {
     52 	head->prev->next = newp;
     53 	newp->next = head;
     54 	newp->prev = head->prev;
     55 	head->prev = newp;
     56 }
     57 
     58 /* Remove element from list. */
     59 static inline
     60 void __cds_list_del(struct cds_list_head *prev, struct cds_list_head *next)
     61 {
     62 	next->prev = prev;
     63 	prev->next = next;
     64 }
     65 
     66 /* Remove element from list. */
     67 static inline
     68 void cds_list_del(struct cds_list_head *elem)
     69 {
     70 	__cds_list_del(elem->prev, elem->next);
     71 }
     72 
     73 /* Remove element from list, initializing the element's list pointers. */
     74 static inline
     75 void cds_list_del_init(struct cds_list_head *elem)
     76 {
     77 	cds_list_del(elem);
     78 	CDS_INIT_LIST_HEAD(elem);
     79 }
     80 
     81 /* Delete from list, add to another list as head. */
     82 static inline
     83 void cds_list_move(struct cds_list_head *elem, struct cds_list_head *head)
     84 {
     85 	__cds_list_del(elem->prev, elem->next);
     86 	cds_list_add(elem, head);
     87 }
     88 
     89 /* Replace an old entry. */
     90 static inline
     91 void cds_list_replace(const struct cds_list_head *old, struct cds_list_head *_new)
     92 {
     93 	_new->next = old->next;
     94 	_new->prev = old->prev;
     95 	_new->prev->next = _new;
     96 	_new->next->prev = _new;
     97 }
     98 
     99 /* Join two lists. */
    100 static inline
    101 void cds_list_splice(struct cds_list_head *add, struct cds_list_head *head)
    102 {
    103 	/* Do nothing if the list which gets added is empty. */
    104 	if (add != add->next) {
    105 		add->next->prev = head;
    106 		add->prev->next = head->next;
    107 		head->next->prev = add->prev;
    108 		head->next = add->next;
    109 	}
    110 }
    111 
    112 /* Get typed element from list at a given position. */
    113 #define cds_list_entry(ptr, type, member) 	caa_container_of(ptr, type, member)
    114 
    115 
    116 /* Get first entry from a list. */
    117 #define cds_list_first_entry(ptr, type, member) \
    118 	cds_list_entry((ptr)->next, type, member)
    119 
    120 /* Iterate forward over the elements of the list. */
    121 #define cds_list_for_each(pos, head) \
    122 	for (pos = (head)->next; (pos) != (head); pos = (pos)->next)
    123 
    124 /*
    125  * Iterate forward over the elements list. The list elements can be
    126  * removed from the list while doing this.
    127  */
    128 #define cds_list_for_each_safe(pos, p, head) \
    129 	for (pos = (head)->next, p = (pos)->next; \
    130 		(pos) != (head); \
    131 		pos = (p), p = (pos)->next)
    132 
    133 /* Iterate backward over the elements of the list. */
    134 #define cds_list_for_each_prev(pos, head) \
    135 	for (pos = (head)->prev; (pos) != (head); pos = (pos)->prev)
    136 
    137 /*
    138  * Iterate backwards over the elements list. The list elements can be
    139  * removed from the list while doing this.
    140  */
    141 #define cds_list_for_each_prev_safe(pos, p, head) \
    142 	for (pos = (head)->prev, p = (pos)->prev; \
    143 		(pos) != (head); \
    144 		pos = (p), p = (pos)->prev)
    145 
    146 #define cds_list_for_each_entry(pos, head, member) \
    147 	for (pos = cds_list_entry((head)->next, __typeof__(*(pos)), member); \
    148 		&(pos)->member != (head); \
    149 		pos = cds_list_entry((pos)->member.next, __typeof__(*(pos)), member))
    150 
    151 #define cds_list_for_each_entry_reverse(pos, head, member) \
    152 	for (pos = cds_list_entry((head)->prev, __typeof__(*(pos)), member); \
    153 		&(pos)->member != (head); \
    154 		pos = cds_list_entry((pos)->member.prev, __typeof__(*(pos)), member))
    155 
    156 #define cds_list_for_each_entry_safe(pos, p, head, member) \
    157 	for (pos = cds_list_entry((head)->next, __typeof__(*(pos)), member), \
    158 			p = cds_list_entry((pos)->member.next, __typeof__(*(pos)), member); \
    159 		&(pos)->member != (head); \
    160 		pos = (p), p = cds_list_entry((pos)->member.next, __typeof__(*(pos)), member))
    161 
    162 /*
    163  * Same as cds_list_for_each_entry_safe, but starts from "pos" which should
    164  * point to an entry within the list.
    165  */
    166 #define cds_list_for_each_entry_safe_from(pos, p, head, member) \
    167         for (p = cds_list_entry((pos)->member.next, __typeof__(*(pos)), member); \
    168                 &(pos)->member != (head); \
    169                 pos = (p), p = cds_list_entry((pos)->member.next, __typeof__(*(pos)), member))
    170 
    171 static inline
    172 int cds_list_empty(const struct cds_list_head *head)
    173 {
    174 	return head == head->next;
    175 }
    176 
    177 static inline
    178 void cds_list_replace_init(struct cds_list_head *old,
    179 		struct cds_list_head *_new)
    180 {
    181 	struct cds_list_head *head = old->next;
    182 
    183 	cds_list_del(old);
    184 	cds_list_add_tail(_new, head);
    185 	CDS_INIT_LIST_HEAD(old);
    186 }
    187 
    188 #endif	/* _CDS_LIST_H */
    189