xref: /nrf52832-nimble/packages/NimBLE-latest/porting/nimble/include/os/queue.h (revision 042d53a763ad75cb1465103098bb88c245d95138)
1*042d53a7SEvalZero /*
2*042d53a7SEvalZero  * Copyright (c) 1991, 1993
3*042d53a7SEvalZero  *	The Regents of the University of California.  All rights reserved.
4*042d53a7SEvalZero  *
5*042d53a7SEvalZero  * Redistribution and use in source and binary forms, with or without
6*042d53a7SEvalZero  * modification, are permitted provided that the following conditions
7*042d53a7SEvalZero  * are met:
8*042d53a7SEvalZero  * 1. Redistributions of source code must retain the above copyright
9*042d53a7SEvalZero  *    notice, this list of conditions and the following disclaimer.
10*042d53a7SEvalZero  * 2. Redistributions in binary form must reproduce the above copyright
11*042d53a7SEvalZero  *    notice, this list of conditions and the following disclaimer in the
12*042d53a7SEvalZero  *    documentation and/or other materials provided with the distribution.
13*042d53a7SEvalZero  * 4. Neither the name of the University nor the names of its contributors
14*042d53a7SEvalZero  *    may be used to endorse or promote products derived from this software
15*042d53a7SEvalZero  *    without specific prior written permission.
16*042d53a7SEvalZero  *
17*042d53a7SEvalZero  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18*042d53a7SEvalZero  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*042d53a7SEvalZero  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*042d53a7SEvalZero  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21*042d53a7SEvalZero  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*042d53a7SEvalZero  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*042d53a7SEvalZero  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*042d53a7SEvalZero  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*042d53a7SEvalZero  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*042d53a7SEvalZero  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*042d53a7SEvalZero  * SUCH DAMAGE.
28*042d53a7SEvalZero  *
29*042d53a7SEvalZero  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
30*042d53a7SEvalZero  * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
31*042d53a7SEvalZero  */
32*042d53a7SEvalZero 
33*042d53a7SEvalZero #ifndef _QUEUE_H_
34*042d53a7SEvalZero #define	_QUEUE_H_
35*042d53a7SEvalZero 
36*042d53a7SEvalZero #ifdef __cplusplus
37*042d53a7SEvalZero extern "C" {
38*042d53a7SEvalZero #endif
39*042d53a7SEvalZero 
40*042d53a7SEvalZero /*
41*042d53a7SEvalZero  * This file defines five types of data structures: singly-linked lists,
42*042d53a7SEvalZero  * singly-linked tail queues, lists, tail queues, and circular queues.
43*042d53a7SEvalZero  *
44*042d53a7SEvalZero  * A singly-linked list is headed by a single forward pointer. The elements
45*042d53a7SEvalZero  * are singly linked for minimum space and pointer manipulation overhead at
46*042d53a7SEvalZero  * the expense of O(n) removal for arbitrary elements. New elements can be
47*042d53a7SEvalZero  * added to the list after an existing element or at the head of the list.
48*042d53a7SEvalZero  * Elements being removed from the head of the list should use the explicit
49*042d53a7SEvalZero  * macro for this purpose for optimum efficiency. A singly-linked list may
50*042d53a7SEvalZero  * only be traversed in the forward direction.  Singly-linked lists are ideal
51*042d53a7SEvalZero  * for applications with large datasets and few or no removals or for
52*042d53a7SEvalZero  * implementing a LIFO queue.
53*042d53a7SEvalZero  *
54*042d53a7SEvalZero  * A singly-linked tail queue is headed by a pair of pointers, one to the
55*042d53a7SEvalZero  * head of the list and the other to the tail of the list. The elements are
56*042d53a7SEvalZero  * singly linked for minimum space and pointer manipulation overhead at the
57*042d53a7SEvalZero  * expense of O(n) removal for arbitrary elements. New elements can be added
58*042d53a7SEvalZero  * to the list after an existing element, at the head of the list, or at the
59*042d53a7SEvalZero  * end of the list. Elements being removed from the head of the tail queue
60*042d53a7SEvalZero  * should use the explicit macro for this purpose for optimum efficiency.
61*042d53a7SEvalZero  * A singly-linked tail queue may only be traversed in the forward direction.
62*042d53a7SEvalZero  * Singly-linked tail queues are ideal for applications with large datasets
63*042d53a7SEvalZero  * and few or no removals or for implementing a FIFO queue.
64*042d53a7SEvalZero  *
65*042d53a7SEvalZero  * A list is headed by a single forward pointer (or an array of forward
66*042d53a7SEvalZero  * pointers for a hash table header). The elements are doubly linked
67*042d53a7SEvalZero  * so that an arbitrary element can be removed without a need to
68*042d53a7SEvalZero  * traverse the list. New elements can be added to the list before
69*042d53a7SEvalZero  * or after an existing element or at the head of the list. A list
70*042d53a7SEvalZero  * may only be traversed in the forward direction.
71*042d53a7SEvalZero  *
72*042d53a7SEvalZero  * A tail queue is headed by a pair of pointers, one to the head of the
73*042d53a7SEvalZero  * list and the other to the tail of the list. The elements are doubly
74*042d53a7SEvalZero  * linked so that an arbitrary element can be removed without a need to
75*042d53a7SEvalZero  * traverse the list. New elements can be added to the list before or
76*042d53a7SEvalZero  * after an existing element, at the head of the list, or at the end of
77*042d53a7SEvalZero  * the list. A tail queue may be traversed in either direction.
78*042d53a7SEvalZero  *
79*042d53a7SEvalZero  * A circle queue is headed by a pair of pointers, one to the head of the
80*042d53a7SEvalZero  * list and the other to the tail of the list. The elements are doubly
81*042d53a7SEvalZero  * linked so that an arbitrary element can be removed without a need to
82*042d53a7SEvalZero  * traverse the list. New elements can be added to the list before or after
83*042d53a7SEvalZero  * an existing element, at the head of the list, or at the end of the list.
84*042d53a7SEvalZero  * A circle queue may be traversed in either direction, but has a more
85*042d53a7SEvalZero  * complex end of list detection.
86*042d53a7SEvalZero  *
87*042d53a7SEvalZero  * For details on the use of these macros, see the queue(3) manual page.
88*042d53a7SEvalZero  *
89*042d53a7SEvalZero  *
90*042d53a7SEvalZero  *                      SLIST   LIST    STAILQ  TAILQ   CIRCLEQ
91*042d53a7SEvalZero  * _HEAD                +       +       +       +       +
92*042d53a7SEvalZero  * _HEAD_INITIALIZER    +       +       +       +       +
93*042d53a7SEvalZero  * _ENTRY               +       +       +       +       +
94*042d53a7SEvalZero  * _INIT                +       +       +       +       +
95*042d53a7SEvalZero  * _EMPTY               +       +       +       +       +
96*042d53a7SEvalZero  * _FIRST               +       +       +       +       +
97*042d53a7SEvalZero  * _NEXT                +       +       +       +       +
98*042d53a7SEvalZero  * _PREV                -       -       -       +       +
99*042d53a7SEvalZero  * _LAST                -       -       +       +       +
100*042d53a7SEvalZero  * _FOREACH             +       +       +       +       +
101*042d53a7SEvalZero  * _FOREACH_REVERSE     -       -       -       +       +
102*042d53a7SEvalZero  * _INSERT_HEAD         +       +       +       +       +
103*042d53a7SEvalZero  * _INSERT_BEFORE       -       +       -       +       +
104*042d53a7SEvalZero  * _INSERT_AFTER        +       +       +       +       +
105*042d53a7SEvalZero  * _INSERT_TAIL         -       -       +       +       +
106*042d53a7SEvalZero  * _REMOVE_HEAD         +       -       +       -       -
107*042d53a7SEvalZero  * _REMOVE              +       +       +       +       +
108*042d53a7SEvalZero  *
109*042d53a7SEvalZero  */
110*042d53a7SEvalZero 
111*042d53a7SEvalZero /*
112*042d53a7SEvalZero  * Singly-linked List declarations.
113*042d53a7SEvalZero  */
114*042d53a7SEvalZero #define	SLIST_HEAD(name, type)                          \
115*042d53a7SEvalZero struct name {                                           \
116*042d53a7SEvalZero     struct type *slh_first;	/* first element */         \
117*042d53a7SEvalZero }
118*042d53a7SEvalZero 
119*042d53a7SEvalZero #define	SLIST_HEAD_INITIALIZER(head)                    \
120*042d53a7SEvalZero     { NULL }
121*042d53a7SEvalZero 
122*042d53a7SEvalZero #define	SLIST_ENTRY(type)                               \
123*042d53a7SEvalZero struct {                                                \
124*042d53a7SEvalZero     struct type *sle_next;  /* next element */          \
125*042d53a7SEvalZero }
126*042d53a7SEvalZero 
127*042d53a7SEvalZero /*
128*042d53a7SEvalZero  * Singly-linked List functions.
129*042d53a7SEvalZero  */
130*042d53a7SEvalZero #define SLIST_EMPTY(head)   ((head)->slh_first == NULL)
131*042d53a7SEvalZero 
132*042d53a7SEvalZero #define SLIST_FIRST(head)   ((head)->slh_first)
133*042d53a7SEvalZero 
134*042d53a7SEvalZero #define SLIST_FOREACH(var, head, field)                 \
135*042d53a7SEvalZero     for ((var) = SLIST_FIRST((head));                   \
136*042d53a7SEvalZero         (var);                                          \
137*042d53a7SEvalZero         (var) = SLIST_NEXT((var), field))
138*042d53a7SEvalZero 
139*042d53a7SEvalZero #define SLIST_INIT(head) do {                           \
140*042d53a7SEvalZero         SLIST_FIRST((head)) = NULL;                     \
141*042d53a7SEvalZero } while (0)
142*042d53a7SEvalZero 
143*042d53a7SEvalZero #define SLIST_INSERT_AFTER(slistelm, elm, field) do {           \
144*042d53a7SEvalZero     SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);   \
145*042d53a7SEvalZero     SLIST_NEXT((slistelm), field) = (elm);                      \
146*042d53a7SEvalZero } while (0)
147*042d53a7SEvalZero 
148*042d53a7SEvalZero #define SLIST_INSERT_HEAD(head, elm, field) do {            \
149*042d53a7SEvalZero     SLIST_NEXT((elm), field) = SLIST_FIRST((head));         \
150*042d53a7SEvalZero     SLIST_FIRST((head)) = (elm);                            \
151*042d53a7SEvalZero } while (0)
152*042d53a7SEvalZero 
153*042d53a7SEvalZero #define SLIST_NEXT(elm, field)	((elm)->field.sle_next)
154*042d53a7SEvalZero 
155*042d53a7SEvalZero #define SLIST_REMOVE(head, elm, type, field) do {           \
156*042d53a7SEvalZero     if (SLIST_FIRST((head)) == (elm)) {                     \
157*042d53a7SEvalZero         SLIST_REMOVE_HEAD((head), field);                   \
158*042d53a7SEvalZero     }                                                       \
159*042d53a7SEvalZero     else {                                                  \
160*042d53a7SEvalZero         struct type *curelm = SLIST_FIRST((head));          \
161*042d53a7SEvalZero         while (SLIST_NEXT(curelm, field) != (elm))          \
162*042d53a7SEvalZero             curelm = SLIST_NEXT(curelm, field);             \
163*042d53a7SEvalZero         SLIST_NEXT(curelm, field) =                         \
164*042d53a7SEvalZero             SLIST_NEXT(SLIST_NEXT(curelm, field), field);   \
165*042d53a7SEvalZero     }                                                       \
166*042d53a7SEvalZero } while (0)
167*042d53a7SEvalZero 
168*042d53a7SEvalZero #define SLIST_REMOVE_HEAD(head, field) do {                         \
169*042d53a7SEvalZero     SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);   \
170*042d53a7SEvalZero } while (0)
171*042d53a7SEvalZero 
172*042d53a7SEvalZero /*
173*042d53a7SEvalZero  * Singly-linked Tail queue declarations.
174*042d53a7SEvalZero  */
175*042d53a7SEvalZero #define	STAILQ_HEAD(name, type)						\
176*042d53a7SEvalZero struct name {								\
177*042d53a7SEvalZero 	struct type *stqh_first;/* first element */			\
178*042d53a7SEvalZero 	struct type **stqh_last;/* addr of last next element */		\
179*042d53a7SEvalZero }
180*042d53a7SEvalZero 
181*042d53a7SEvalZero #define	STAILQ_HEAD_INITIALIZER(head)					\
182*042d53a7SEvalZero 	{ NULL, &(head).stqh_first }
183*042d53a7SEvalZero 
184*042d53a7SEvalZero #define	STAILQ_ENTRY(type)						\
185*042d53a7SEvalZero struct {								\
186*042d53a7SEvalZero 	struct type *stqe_next;	/* next element */			\
187*042d53a7SEvalZero }
188*042d53a7SEvalZero 
189*042d53a7SEvalZero /*
190*042d53a7SEvalZero  * Singly-linked Tail queue functions.
191*042d53a7SEvalZero  */
192*042d53a7SEvalZero #define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
193*042d53a7SEvalZero 
194*042d53a7SEvalZero #define	STAILQ_FIRST(head)	((head)->stqh_first)
195*042d53a7SEvalZero 
196*042d53a7SEvalZero #define	STAILQ_FOREACH(var, head, field)				\
197*042d53a7SEvalZero 	for((var) = STAILQ_FIRST((head));				\
198*042d53a7SEvalZero 	   (var);							\
199*042d53a7SEvalZero 	   (var) = STAILQ_NEXT((var), field))
200*042d53a7SEvalZero 
201*042d53a7SEvalZero #define	STAILQ_INIT(head) do {						\
202*042d53a7SEvalZero 	STAILQ_FIRST((head)) = NULL;					\
203*042d53a7SEvalZero 	(head)->stqh_last = &STAILQ_FIRST((head));			\
204*042d53a7SEvalZero } while (0)
205*042d53a7SEvalZero 
206*042d53a7SEvalZero #define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
207*042d53a7SEvalZero 	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
208*042d53a7SEvalZero 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
209*042d53a7SEvalZero 	STAILQ_NEXT((tqelm), field) = (elm);				\
210*042d53a7SEvalZero } while (0)
211*042d53a7SEvalZero 
212*042d53a7SEvalZero #define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
213*042d53a7SEvalZero 	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
214*042d53a7SEvalZero 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
215*042d53a7SEvalZero 	STAILQ_FIRST((head)) = (elm);					\
216*042d53a7SEvalZero } while (0)
217*042d53a7SEvalZero 
218*042d53a7SEvalZero #define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
219*042d53a7SEvalZero 	STAILQ_NEXT((elm), field) = NULL;				\
220*042d53a7SEvalZero 	*(head)->stqh_last = (elm);					\
221*042d53a7SEvalZero 	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
222*042d53a7SEvalZero } while (0)
223*042d53a7SEvalZero 
224*042d53a7SEvalZero #define	STAILQ_LAST(head, type, field)					\
225*042d53a7SEvalZero 	(STAILQ_EMPTY(head) ?						\
226*042d53a7SEvalZero 		NULL :							\
227*042d53a7SEvalZero 	        ((struct type *)					\
228*042d53a7SEvalZero 		((char *)((head)->stqh_last) - offsetof(struct type, field))))
229*042d53a7SEvalZero 
230*042d53a7SEvalZero #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
231*042d53a7SEvalZero 
232*042d53a7SEvalZero #define	STAILQ_REMOVE(head, elm, type, field) do {			\
233*042d53a7SEvalZero 	if (STAILQ_FIRST((head)) == (elm)) {				\
234*042d53a7SEvalZero 		STAILQ_REMOVE_HEAD(head, field);			\
235*042d53a7SEvalZero 	}								\
236*042d53a7SEvalZero 	else {								\
237*042d53a7SEvalZero 		struct type *curelm = STAILQ_FIRST((head));		\
238*042d53a7SEvalZero 		while (STAILQ_NEXT(curelm, field) != (elm))		\
239*042d53a7SEvalZero 			curelm = STAILQ_NEXT(curelm, field);		\
240*042d53a7SEvalZero 		if ((STAILQ_NEXT(curelm, field) =			\
241*042d53a7SEvalZero 		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
242*042d53a7SEvalZero 			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
243*042d53a7SEvalZero 	}								\
244*042d53a7SEvalZero } while (0)
245*042d53a7SEvalZero 
246*042d53a7SEvalZero #define	STAILQ_REMOVE_HEAD(head, field) do {				\
247*042d53a7SEvalZero 	if ((STAILQ_FIRST((head)) =					\
248*042d53a7SEvalZero 	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
249*042d53a7SEvalZero 		(head)->stqh_last = &STAILQ_FIRST((head));		\
250*042d53a7SEvalZero } while (0)
251*042d53a7SEvalZero 
252*042d53a7SEvalZero #define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
253*042d53a7SEvalZero 	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
254*042d53a7SEvalZero 		(head)->stqh_last = &STAILQ_FIRST((head));		\
255*042d53a7SEvalZero } while (0)
256*042d53a7SEvalZero 
257*042d53a7SEvalZero #define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
258*042d53a7SEvalZero 	if ((STAILQ_NEXT(elm, field) =					\
259*042d53a7SEvalZero 	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
260*042d53a7SEvalZero 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
261*042d53a7SEvalZero } while (0)
262*042d53a7SEvalZero 
263*042d53a7SEvalZero /*
264*042d53a7SEvalZero  * List declarations.
265*042d53a7SEvalZero  */
266*042d53a7SEvalZero #define	LIST_HEAD(name, type)						\
267*042d53a7SEvalZero struct name {								\
268*042d53a7SEvalZero 	struct type *lh_first;	/* first element */			\
269*042d53a7SEvalZero }
270*042d53a7SEvalZero 
271*042d53a7SEvalZero #define	LIST_HEAD_INITIALIZER(head)					\
272*042d53a7SEvalZero 	{ NULL }
273*042d53a7SEvalZero 
274*042d53a7SEvalZero #define	LIST_ENTRY(type)						\
275*042d53a7SEvalZero struct {								\
276*042d53a7SEvalZero 	struct type *le_next;	/* next element */			\
277*042d53a7SEvalZero 	struct type **le_prev;	/* address of previous next element */	\
278*042d53a7SEvalZero }
279*042d53a7SEvalZero 
280*042d53a7SEvalZero /*
281*042d53a7SEvalZero  * List functions.
282*042d53a7SEvalZero  */
283*042d53a7SEvalZero 
284*042d53a7SEvalZero #define	LIST_EMPTY(head)	((head)->lh_first == NULL)
285*042d53a7SEvalZero 
286*042d53a7SEvalZero #define	LIST_FIRST(head)	((head)->lh_first)
287*042d53a7SEvalZero 
288*042d53a7SEvalZero #define	LIST_FOREACH(var, head, field)					\
289*042d53a7SEvalZero 	for ((var) = LIST_FIRST((head));				\
290*042d53a7SEvalZero 	    (var);							\
291*042d53a7SEvalZero 	    (var) = LIST_NEXT((var), field))
292*042d53a7SEvalZero 
293*042d53a7SEvalZero #define	LIST_INIT(head) do {						\
294*042d53a7SEvalZero 	LIST_FIRST((head)) = NULL;					\
295*042d53a7SEvalZero } while (0)
296*042d53a7SEvalZero 
297*042d53a7SEvalZero #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
298*042d53a7SEvalZero 	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
299*042d53a7SEvalZero 		LIST_NEXT((listelm), field)->field.le_prev =		\
300*042d53a7SEvalZero 		    &LIST_NEXT((elm), field);				\
301*042d53a7SEvalZero 	LIST_NEXT((listelm), field) = (elm);				\
302*042d53a7SEvalZero 	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
303*042d53a7SEvalZero } while (0)
304*042d53a7SEvalZero 
305*042d53a7SEvalZero #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
306*042d53a7SEvalZero 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
307*042d53a7SEvalZero 	LIST_NEXT((elm), field) = (listelm);				\
308*042d53a7SEvalZero 	*(listelm)->field.le_prev = (elm);				\
309*042d53a7SEvalZero 	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
310*042d53a7SEvalZero } while (0)
311*042d53a7SEvalZero 
312*042d53a7SEvalZero #define	LIST_INSERT_HEAD(head, elm, field) do {				\
313*042d53a7SEvalZero 	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
314*042d53a7SEvalZero 		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
315*042d53a7SEvalZero 	LIST_FIRST((head)) = (elm);					\
316*042d53a7SEvalZero 	(elm)->field.le_prev = &LIST_FIRST((head));			\
317*042d53a7SEvalZero } while (0)
318*042d53a7SEvalZero 
319*042d53a7SEvalZero #define	LIST_NEXT(elm, field)	((elm)->field.le_next)
320*042d53a7SEvalZero 
321*042d53a7SEvalZero #define	LIST_REMOVE(elm, field) do {					\
322*042d53a7SEvalZero 	if (LIST_NEXT((elm), field) != NULL)				\
323*042d53a7SEvalZero 		LIST_NEXT((elm), field)->field.le_prev = 		\
324*042d53a7SEvalZero 		    (elm)->field.le_prev;				\
325*042d53a7SEvalZero 	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
326*042d53a7SEvalZero } while (0)
327*042d53a7SEvalZero 
328*042d53a7SEvalZero /*
329*042d53a7SEvalZero  * Tail queue declarations.
330*042d53a7SEvalZero  */
331*042d53a7SEvalZero #define	TAILQ_HEAD(name, type)						\
332*042d53a7SEvalZero struct name {								\
333*042d53a7SEvalZero 	struct type *tqh_first;	/* first element */			\
334*042d53a7SEvalZero 	struct type **tqh_last;	/* addr of last next element */		\
335*042d53a7SEvalZero }
336*042d53a7SEvalZero 
337*042d53a7SEvalZero #define	TAILQ_HEAD_INITIALIZER(head)					\
338*042d53a7SEvalZero 	{ NULL, &(head).tqh_first }
339*042d53a7SEvalZero 
340*042d53a7SEvalZero #define	TAILQ_ENTRY(type)						\
341*042d53a7SEvalZero struct {								\
342*042d53a7SEvalZero 	struct type *tqe_next;	/* next element */			\
343*042d53a7SEvalZero 	struct type **tqe_prev;	/* address of previous next element */	\
344*042d53a7SEvalZero }
345*042d53a7SEvalZero 
346*042d53a7SEvalZero /*
347*042d53a7SEvalZero  * Tail queue functions.
348*042d53a7SEvalZero  */
349*042d53a7SEvalZero #define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
350*042d53a7SEvalZero 
351*042d53a7SEvalZero #define	TAILQ_FIRST(head)	((head)->tqh_first)
352*042d53a7SEvalZero 
353*042d53a7SEvalZero #define	TAILQ_FOREACH(var, head, field)					\
354*042d53a7SEvalZero 	for ((var) = TAILQ_FIRST((head));				\
355*042d53a7SEvalZero 	    (var);							\
356*042d53a7SEvalZero 	    (var) = TAILQ_NEXT((var), field))
357*042d53a7SEvalZero 
358*042d53a7SEvalZero #define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
359*042d53a7SEvalZero 	for ((var) = TAILQ_LAST((head), headname);			\
360*042d53a7SEvalZero 	    (var);							\
361*042d53a7SEvalZero 	    (var) = TAILQ_PREV((var), headname, field))
362*042d53a7SEvalZero 
363*042d53a7SEvalZero #define	TAILQ_INIT(head) do {						\
364*042d53a7SEvalZero 	TAILQ_FIRST((head)) = NULL;					\
365*042d53a7SEvalZero 	(head)->tqh_last = &TAILQ_FIRST((head));			\
366*042d53a7SEvalZero } while (0)
367*042d53a7SEvalZero 
368*042d53a7SEvalZero #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
369*042d53a7SEvalZero 	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
370*042d53a7SEvalZero 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
371*042d53a7SEvalZero 		    &TAILQ_NEXT((elm), field);				\
372*042d53a7SEvalZero 	else								\
373*042d53a7SEvalZero 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
374*042d53a7SEvalZero 	TAILQ_NEXT((listelm), field) = (elm);				\
375*042d53a7SEvalZero 	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
376*042d53a7SEvalZero } while (0)
377*042d53a7SEvalZero 
378*042d53a7SEvalZero #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
379*042d53a7SEvalZero 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
380*042d53a7SEvalZero 	TAILQ_NEXT((elm), field) = (listelm);				\
381*042d53a7SEvalZero 	*(listelm)->field.tqe_prev = (elm);				\
382*042d53a7SEvalZero 	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
383*042d53a7SEvalZero } while (0)
384*042d53a7SEvalZero 
385*042d53a7SEvalZero #define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
386*042d53a7SEvalZero 	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
387*042d53a7SEvalZero 		TAILQ_FIRST((head))->field.tqe_prev =			\
388*042d53a7SEvalZero 		    &TAILQ_NEXT((elm), field);				\
389*042d53a7SEvalZero 	else								\
390*042d53a7SEvalZero 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
391*042d53a7SEvalZero 	TAILQ_FIRST((head)) = (elm);					\
392*042d53a7SEvalZero 	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
393*042d53a7SEvalZero } while (0)
394*042d53a7SEvalZero 
395*042d53a7SEvalZero #define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
396*042d53a7SEvalZero 	TAILQ_NEXT((elm), field) = NULL;				\
397*042d53a7SEvalZero 	(elm)->field.tqe_prev = (head)->tqh_last;			\
398*042d53a7SEvalZero 	*(head)->tqh_last = (elm);					\
399*042d53a7SEvalZero 	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
400*042d53a7SEvalZero } while (0)
401*042d53a7SEvalZero 
402*042d53a7SEvalZero #define	TAILQ_LAST(head, headname)					\
403*042d53a7SEvalZero 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
404*042d53a7SEvalZero 
405*042d53a7SEvalZero #define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
406*042d53a7SEvalZero 
407*042d53a7SEvalZero #define	TAILQ_PREV(elm, headname, field)				\
408*042d53a7SEvalZero 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
409*042d53a7SEvalZero 
410*042d53a7SEvalZero #define	TAILQ_REMOVE(head, elm, field) do {				\
411*042d53a7SEvalZero 	if ((TAILQ_NEXT((elm), field)) != NULL)				\
412*042d53a7SEvalZero 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
413*042d53a7SEvalZero 		    (elm)->field.tqe_prev;				\
414*042d53a7SEvalZero 	else								\
415*042d53a7SEvalZero 		(head)->tqh_last = (elm)->field.tqe_prev;		\
416*042d53a7SEvalZero 	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
417*042d53a7SEvalZero } while (0)
418*042d53a7SEvalZero 
419*042d53a7SEvalZero /*
420*042d53a7SEvalZero  * Circular queue declarations.
421*042d53a7SEvalZero  */
422*042d53a7SEvalZero #define	CIRCLEQ_HEAD(name, type)					\
423*042d53a7SEvalZero struct name {								\
424*042d53a7SEvalZero 	struct type *cqh_first;		/* first element */		\
425*042d53a7SEvalZero 	struct type *cqh_last;		/* last element */		\
426*042d53a7SEvalZero }
427*042d53a7SEvalZero 
428*042d53a7SEvalZero #define	CIRCLEQ_HEAD_INITIALIZER(head)					\
429*042d53a7SEvalZero 	{ (void *)&(head), (void *)&(head) }
430*042d53a7SEvalZero 
431*042d53a7SEvalZero #define	CIRCLEQ_ENTRY(type)						\
432*042d53a7SEvalZero struct {								\
433*042d53a7SEvalZero 	struct type *cqe_next;		/* next element */		\
434*042d53a7SEvalZero 	struct type *cqe_prev;		/* previous element */		\
435*042d53a7SEvalZero }
436*042d53a7SEvalZero 
437*042d53a7SEvalZero /*
438*042d53a7SEvalZero  * Circular queue functions.
439*042d53a7SEvalZero  */
440*042d53a7SEvalZero #define	CIRCLEQ_EMPTY(head)	((head)->cqh_first == (void *)(head))
441*042d53a7SEvalZero 
442*042d53a7SEvalZero #define	CIRCLEQ_FIRST(head)	((head)->cqh_first)
443*042d53a7SEvalZero 
444*042d53a7SEvalZero #define	CIRCLEQ_FOREACH(var, head, field)				\
445*042d53a7SEvalZero 	for ((var) = CIRCLEQ_FIRST((head));				\
446*042d53a7SEvalZero 	    (var) != (void *)(head) || ((var) = NULL);			\
447*042d53a7SEvalZero 	    (var) = CIRCLEQ_NEXT((var), field))
448*042d53a7SEvalZero 
449*042d53a7SEvalZero #define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
450*042d53a7SEvalZero 	for ((var) = CIRCLEQ_LAST((head));				\
451*042d53a7SEvalZero 	    (var) != (void *)(head) || ((var) = NULL);			\
452*042d53a7SEvalZero 	    (var) = CIRCLEQ_PREV((var), field))
453*042d53a7SEvalZero 
454*042d53a7SEvalZero #define	CIRCLEQ_INIT(head) do {						\
455*042d53a7SEvalZero 	CIRCLEQ_FIRST((head)) = (void *)(head);				\
456*042d53a7SEvalZero 	CIRCLEQ_LAST((head)) = (void *)(head);				\
457*042d53a7SEvalZero } while (0)
458*042d53a7SEvalZero 
459*042d53a7SEvalZero #define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
460*042d53a7SEvalZero 	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field);	\
461*042d53a7SEvalZero 	CIRCLEQ_PREV((elm), field) = (listelm);				\
462*042d53a7SEvalZero 	if (CIRCLEQ_NEXT((listelm), field) == (void *)(head))		\
463*042d53a7SEvalZero 		CIRCLEQ_LAST((head)) = (elm);				\
464*042d53a7SEvalZero 	else								\
465*042d53a7SEvalZero 		CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
466*042d53a7SEvalZero 	CIRCLEQ_NEXT((listelm), field) = (elm);				\
467*042d53a7SEvalZero } while (0)
468*042d53a7SEvalZero 
469*042d53a7SEvalZero #define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
470*042d53a7SEvalZero 	CIRCLEQ_NEXT((elm), field) = (listelm);				\
471*042d53a7SEvalZero 	CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field);	\
472*042d53a7SEvalZero 	if (CIRCLEQ_PREV((listelm), field) == (void *)(head))		\
473*042d53a7SEvalZero 		CIRCLEQ_FIRST((head)) = (elm);				\
474*042d53a7SEvalZero 	else								\
475*042d53a7SEvalZero 		CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
476*042d53a7SEvalZero 	CIRCLEQ_PREV((listelm), field) = (elm);				\
477*042d53a7SEvalZero } while (0)
478*042d53a7SEvalZero 
479*042d53a7SEvalZero #define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
480*042d53a7SEvalZero 	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head));		\
481*042d53a7SEvalZero 	CIRCLEQ_PREV((elm), field) = (void *)(head);			\
482*042d53a7SEvalZero 	if (CIRCLEQ_LAST((head)) == (void *)(head))			\
483*042d53a7SEvalZero 		CIRCLEQ_LAST((head)) = (elm);				\
484*042d53a7SEvalZero 	else								\
485*042d53a7SEvalZero 		CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm);	\
486*042d53a7SEvalZero 	CIRCLEQ_FIRST((head)) = (elm);					\
487*042d53a7SEvalZero } while (0)
488*042d53a7SEvalZero 
489*042d53a7SEvalZero #define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
490*042d53a7SEvalZero 	CIRCLEQ_NEXT((elm), field) = (void *)(head);			\
491*042d53a7SEvalZero 	CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head));		\
492*042d53a7SEvalZero 	if (CIRCLEQ_FIRST((head)) == (void *)(head))			\
493*042d53a7SEvalZero 		CIRCLEQ_FIRST((head)) = (elm);				\
494*042d53a7SEvalZero 	else								\
495*042d53a7SEvalZero 		CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm);	\
496*042d53a7SEvalZero 	CIRCLEQ_LAST((head)) = (elm);					\
497*042d53a7SEvalZero } while (0)
498*042d53a7SEvalZero 
499*042d53a7SEvalZero #define	CIRCLEQ_LAST(head)	((head)->cqh_last)
500*042d53a7SEvalZero 
501*042d53a7SEvalZero #define	CIRCLEQ_NEXT(elm,field)	((elm)->field.cqe_next)
502*042d53a7SEvalZero 
503*042d53a7SEvalZero #define	CIRCLEQ_PREV(elm,field)	((elm)->field.cqe_prev)
504*042d53a7SEvalZero 
505*042d53a7SEvalZero #define	CIRCLEQ_REMOVE(head, elm, field) do {				\
506*042d53a7SEvalZero 	if (CIRCLEQ_NEXT((elm), field) == (void *)(head))		\
507*042d53a7SEvalZero 		CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field);	\
508*042d53a7SEvalZero 	else								\
509*042d53a7SEvalZero 		CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) =	\
510*042d53a7SEvalZero 		    CIRCLEQ_PREV((elm), field);				\
511*042d53a7SEvalZero 	if (CIRCLEQ_PREV((elm), field) == (void *)(head))		\
512*042d53a7SEvalZero 		CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field);	\
513*042d53a7SEvalZero 	else								\
514*042d53a7SEvalZero 		CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) =	\
515*042d53a7SEvalZero 		    CIRCLEQ_NEXT((elm), field);				\
516*042d53a7SEvalZero } while (0)
517*042d53a7SEvalZero 
518*042d53a7SEvalZero #ifdef __cplusplus
519*042d53a7SEvalZero }
520*042d53a7SEvalZero #endif
521*042d53a7SEvalZero 
522*042d53a7SEvalZero #endif /* !_QUEUE_H_ */
523