xref: /illumos-gate/usr/src/uts/common/sys/queue.h (revision 85280f08)
1381a2a9aSdr /*
2381a2a9aSdr  * Copyright (c) 1991, 1993
3381a2a9aSdr  *	The Regents of the University of California.  All rights reserved.
4381a2a9aSdr  *
5381a2a9aSdr  * Redistribution and use in source and binary forms, with or without
6381a2a9aSdr  * modification, are permitted provided that the following conditions
7381a2a9aSdr  * are met:
8381a2a9aSdr  * 1. Redistributions of source code must retain the above copyright
9381a2a9aSdr  *    notice, this list of conditions and the following disclaimer.
10381a2a9aSdr  * 2. Redistributions in binary form must reproduce the above copyright
11381a2a9aSdr  *    notice, this list of conditions and the following disclaimer in the
12381a2a9aSdr  *    documentation and/or other materials provided with the distribution.
13381a2a9aSdr  * 3. Neither the name of the University nor the names of its contributors
14381a2a9aSdr  *    may be used to endorse or promote products derived from this software
15381a2a9aSdr  *    without specific prior written permission.
16381a2a9aSdr  *
17381a2a9aSdr  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18381a2a9aSdr  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19381a2a9aSdr  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20381a2a9aSdr  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21381a2a9aSdr  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22381a2a9aSdr  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23381a2a9aSdr  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24381a2a9aSdr  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25381a2a9aSdr  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26381a2a9aSdr  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27381a2a9aSdr  * SUCH DAMAGE.
28381a2a9aSdr  *
29381a2a9aSdr  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
30381a2a9aSdr  */
31381a2a9aSdr /*
32c1374a13SSurya Prakki  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
33381a2a9aSdr  * Use is subject to license terms.
34381a2a9aSdr  */
35381a2a9aSdr 
36381a2a9aSdr #ifndef	_SYS_QUEUE_H
37381a2a9aSdr #define	_SYS_QUEUE_H
38381a2a9aSdr 
39381a2a9aSdr #include <sys/note.h>
40*85280f08SToomas Soome #include <sys/containerof.h>
41381a2a9aSdr 
42*85280f08SToomas Soome #ifdef __cplusplus
43381a2a9aSdr extern "C" {
44381a2a9aSdr #endif
45381a2a9aSdr 
46381a2a9aSdr /*
47381a2a9aSdr  * This file defines five types of data structures: singly-linked lists,
48381a2a9aSdr  * lists, simple queues, tail queues, and circular queues.
49381a2a9aSdr  *
50381a2a9aSdr  * A singly-linked list is headed by a single forward pointer. The
51381a2a9aSdr  * elements are singly linked for minimum space and pointer manipulation
52381a2a9aSdr  * overhead at the expense of O(n) removal for arbitrary elements. New
53381a2a9aSdr  * elements can be added to the list after an existing element or at the
54381a2a9aSdr  * head of the list.  Elements being removed from the head of the list
55381a2a9aSdr  * should use the explicit macro for this purpose for optimum
56381a2a9aSdr  * efficiency. A singly-linked list may only be traversed in the forward
57381a2a9aSdr  * direction.  Singly-linked lists are ideal for applications with large
58381a2a9aSdr  * datasets and few or no removals or for implementing a LIFO queue.
59381a2a9aSdr  *
60381a2a9aSdr  * A list is headed by a single forward pointer (or an array of forward
61381a2a9aSdr  * pointers for a hash table header). The elements are doubly linked
62381a2a9aSdr  * so that an arbitrary element can be removed without a need to
63381a2a9aSdr  * traverse the list. New elements can be added to the list before
64381a2a9aSdr  * or after an existing element or at the head of the list. A list
65381a2a9aSdr  * may only be traversed in the forward direction.
66381a2a9aSdr  *
67381a2a9aSdr  * A simple queue is headed by a pair of pointers, one the head of the
68381a2a9aSdr  * list and the other to the tail of the list. The elements are singly
69381a2a9aSdr  * linked to save space, so elements can only be removed from the
70381a2a9aSdr  * head of the list. New elements can be added to the list after
71381a2a9aSdr  * an existing element, at the head of the list, or at the end of the
72381a2a9aSdr  * list. A simple queue may only be traversed in the forward direction.
73381a2a9aSdr  *
74381a2a9aSdr  * A tail queue is headed by a pair of pointers, one to the head of the
75381a2a9aSdr  * list and the other to the tail of the list. The elements are doubly
76381a2a9aSdr  * linked so that an arbitrary element can be removed without a need to
77381a2a9aSdr  * traverse the list. New elements can be added to the list before or
78381a2a9aSdr  * after an existing element, at the head of the list, or at the end of
79381a2a9aSdr  * the list. A tail queue may be traversed in either direction.
80381a2a9aSdr  *
81381a2a9aSdr  * A circle queue is headed by a pair of pointers, one to the head of the
82381a2a9aSdr  * list and the other to the tail of the list. The elements are doubly
83381a2a9aSdr  * linked so that an arbitrary element can be removed without a need to
84381a2a9aSdr  * traverse the list. New elements can be added to the list before or after
85381a2a9aSdr  * an existing element, at the head of the list, or at the end of the list.
86381a2a9aSdr  * A circle queue may be traversed in either direction, but has a more
87381a2a9aSdr  * complex end of list detection.
88381a2a9aSdr  *
89*85280f08SToomas Soome  * For details on the use of these macros, see the queue.h(3HEAD) manual page.
90381a2a9aSdr  */
91381a2a9aSdr 
92*85280f08SToomas Soome #ifdef QUEUE_MACRO_DEBUG
93*85280f08SToomas Soome #warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
94*85280f08SToomas Soome #define	QUEUE_MACRO_DEBUG_TRACE
95*85280f08SToomas Soome #define	QUEUE_MACRO_DEBUG_TRASH
96381a2a9aSdr #endif
97381a2a9aSdr 
98*85280f08SToomas Soome #ifdef QUEUE_MACRO_DEBUG_TRACE
99*85280f08SToomas Soome /* Store the last 2 places the queue element or head was altered */
100*85280f08SToomas Soome struct qm_trace {
101*85280f08SToomas Soome 	unsigned long	lastline;
102*85280f08SToomas Soome 	unsigned long	prevline;
103*85280f08SToomas Soome 	const char	*lastfile;
104*85280f08SToomas Soome 	const char	*prevfile;
105*85280f08SToomas Soome };
106*85280f08SToomas Soome 
107*85280f08SToomas Soome #define	TRACEBUF	struct qm_trace trace;
108*85280f08SToomas Soome #define	TRACEBUF_INITIALIZER	{ __LINE__, 0, __FILE__, NULL },
109*85280f08SToomas Soome 
110*85280f08SToomas Soome #define	QMD_TRACE_HEAD(head) do {					\
111*85280f08SToomas Soome 	(head)->trace.prevline = (head)->trace.lastline;		\
112*85280f08SToomas Soome 	(head)->trace.prevfile = (head)->trace.lastfile;		\
113*85280f08SToomas Soome 	(head)->trace.lastline = __LINE__;				\
114*85280f08SToomas Soome 	(head)->trace.lastfile = __FILE__;				\
115381a2a9aSdr 	_NOTE(CONSTCOND)						\
116381a2a9aSdr } while (0)
117381a2a9aSdr 
118*85280f08SToomas Soome #define	QMD_TRACE_ELEM(elem) do {					\
119*85280f08SToomas Soome 	(elem)->trace.prevline = (elem)->trace.lastline;		\
120*85280f08SToomas Soome 	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
121*85280f08SToomas Soome 	(elem)->trace.lastline = __LINE__;				\
122*85280f08SToomas Soome 	(elem)->trace.lastfile = __FILE__;				\
123381a2a9aSdr 	_NOTE(CONSTCOND)						\
124381a2a9aSdr } while (0)
125381a2a9aSdr 
126*85280f08SToomas Soome #else	/* !QUEUE_MACRO_DEBUG_TRACE */
127*85280f08SToomas Soome #define	QMD_TRACE_ELEM(elem)
128*85280f08SToomas Soome #define	QMD_TRACE_HEAD(head)
129*85280f08SToomas Soome #define	TRACEBUF
130*85280f08SToomas Soome #define	TRACEBUF_INITIALIZER
131*85280f08SToomas Soome #endif	/* QUEUE_MACRO_DEBUG_TRACE */
132*85280f08SToomas Soome 
133*85280f08SToomas Soome #ifdef QUEUE_MACRO_DEBUG_TRASH
134*85280f08SToomas Soome #define	TRASHIT(x)		do {(x) = (void *)-1; } while (0)
135*85280f08SToomas Soome #define	QMD_IS_TRASHED(x)	((x) == (void *)(intptr_t)-1)
136*85280f08SToomas Soome #else	/* !QUEUE_MACRO_DEBUG_TRASH */
137*85280f08SToomas Soome #define	TRASHIT(x)
138*85280f08SToomas Soome #define	QMD_IS_TRASHED(x)	0
139*85280f08SToomas Soome #endif	/* QUEUE_MACRO_DEBUG_TRASH */
140*85280f08SToomas Soome 
141*85280f08SToomas Soome #if defined(QUEUE_MACRO_DEBUG_TRACE) || defined(QUEUE_MACRO_DEBUG_TRASH)
142*85280f08SToomas Soome #define	QMD_SAVELINK(name, link)	void **name = (void *)&(link)
143*85280f08SToomas Soome #else	/* !QUEUE_MACRO_DEBUG_TRACE && !QUEUE_MACRO_DEBUG_TRASH */
144*85280f08SToomas Soome #define	QMD_SAVELINK(name, link)
145*85280f08SToomas Soome #endif	/* QUEUE_MACRO_DEBUG_TRACE || QUEUE_MACRO_DEBUG_TRASH */
146*85280f08SToomas Soome 
147*85280f08SToomas Soome #ifdef __cplusplus
148381a2a9aSdr /*
149*85280f08SToomas Soome  * In C++ there can be structure lists and class lists:
150381a2a9aSdr  */
151*85280f08SToomas Soome #define	QUEUE_TYPEOF(type) type
152*85280f08SToomas Soome #else
153*85280f08SToomas Soome #define	QUEUE_TYPEOF(type) struct type
154*85280f08SToomas Soome #endif
155381a2a9aSdr 
156381a2a9aSdr /*
157381a2a9aSdr  * Singly-linked List definitions.
158381a2a9aSdr  */
159381a2a9aSdr #define	SLIST_HEAD(name, type)						\
160381a2a9aSdr struct name {								\
161381a2a9aSdr 	struct type *slh_first;	/* first element */			\
162381a2a9aSdr }
163381a2a9aSdr 
164*85280f08SToomas Soome #define	SLIST_CLASS_HEAD(name, type)					\
165*85280f08SToomas Soome struct name {								\
166*85280f08SToomas Soome 	class type *slh_first;	/* first element */			\
167*85280f08SToomas Soome }
168*85280f08SToomas Soome 
169381a2a9aSdr #define	SLIST_HEAD_INITIALIZER(head)					\
170381a2a9aSdr 	{ NULL }
171381a2a9aSdr 
172381a2a9aSdr #define	SLIST_ENTRY(type)						\
173381a2a9aSdr struct {								\
174381a2a9aSdr 	struct type *sle_next;	/* next element */			\
175381a2a9aSdr }
176381a2a9aSdr 
177*85280f08SToomas Soome #define	SLIST_CLASS_ENTRY(type)						\
178*85280f08SToomas Soome struct {								\
179*85280f08SToomas Soome 	class type *sle_next;		/* next element */		\
180*85280f08SToomas Soome }
181*85280f08SToomas Soome 
182*85280f08SToomas Soome /*
183*85280f08SToomas Soome  * Singly-linked List access methods.
184*85280f08SToomas Soome  */
185*85280f08SToomas Soome #define	SLIST_FIRST(head)	((head)->slh_first)
186*85280f08SToomas Soome #define	SLIST_END(head)		NULL
187*85280f08SToomas Soome #define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
188*85280f08SToomas Soome #define	SLIST_EMPTY(head)	((head)->slh_first == SLIST_END(head))
189*85280f08SToomas Soome 
190*85280f08SToomas Soome #define	SLIST_FOREACH(var, head, field)					\
191*85280f08SToomas Soome 	for ((var) = SLIST_FIRST((head));				\
192*85280f08SToomas Soome 		(var) != SLIST_END(head);				\
193*85280f08SToomas Soome 		(var) = SLIST_NEXT((var), field))
194*85280f08SToomas Soome 
195*85280f08SToomas Soome #define	SLIST_FOREACH_FROM(var, head, field)				\
196*85280f08SToomas Soome 	for ((var) = ((var) != SLIST_END(head) ? (var) : SLIST_FIRST((head))); \
197*85280f08SToomas Soome 		(var) != SLIST_END(head);				\
198*85280f08SToomas Soome 		(var) = SLIST_NEXT((var), field))
199*85280f08SToomas Soome 
200*85280f08SToomas Soome #define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
201*85280f08SToomas Soome 	for ((var) = SLIST_FIRST((head));				\
202*85280f08SToomas Soome 		(var) != SLIST_END(head) &&				\
203*85280f08SToomas Soome 		((tvar) = SLIST_NEXT((var), field), 1);			\
204*85280f08SToomas Soome 		(var) = (tvar))
205*85280f08SToomas Soome 
206*85280f08SToomas Soome #define	SLIST_FOREACH_FROM_SAFE(var, head, field, tvar)			\
207*85280f08SToomas Soome 	for ((var) = ((var) != SLIST_END(head) ? (var) : SLIST_FIRST((head))); \
208*85280f08SToomas Soome 		(var) != SLIST_END(head) &&				\
209*85280f08SToomas Soome 		((tvar) = SLIST_NEXT((var), field), 1);			\
210*85280f08SToomas Soome 		(var) = (tvar))
211*85280f08SToomas Soome 
212381a2a9aSdr /*
213381a2a9aSdr  * Singly-linked List functions.
214381a2a9aSdr  */
215381a2a9aSdr #define	SLIST_INIT(head) do {						\
216*85280f08SToomas Soome 	(head)->slh_first = SLIST_END(head);				\
217*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
218*85280f08SToomas Soome } while (0)
219*85280f08SToomas Soome 
220*85280f08SToomas Soome #define	SLIST_CONCAT(head1, head2, type, field) do {			\
221*85280f08SToomas Soome 	QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1);		\
222*85280f08SToomas Soome 	if (curelm == SLIST_END(head1)) {				\
223*85280f08SToomas Soome 		if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) !=	\
224*85280f08SToomas Soome 		    SLIST_END(head1))					\
225*85280f08SToomas Soome 			SLIST_INIT(head2);				\
226*85280f08SToomas Soome 	} else if (SLIST_FIRST(head2) != SLIST_END(head2)) {		\
227*85280f08SToomas Soome 		while (SLIST_NEXT(curelm, field) != SLIST_END(head1))	\
228*85280f08SToomas Soome 			curelm = SLIST_NEXT(curelm, field);		\
229*85280f08SToomas Soome 		SLIST_NEXT(curelm, field) = SLIST_FIRST(head2);		\
230*85280f08SToomas Soome 		SLIST_INIT(head2);					\
231*85280f08SToomas Soome 	}								\
232381a2a9aSdr 	_NOTE(CONSTCOND)						\
233381a2a9aSdr } while (0)
234381a2a9aSdr 
235381a2a9aSdr #define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
236*85280f08SToomas Soome 	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
237*85280f08SToomas Soome 	SLIST_NEXT((slistelm), field) = (elm);				\
238381a2a9aSdr 	_NOTE(CONSTCOND)						\
239381a2a9aSdr } while (0)
240381a2a9aSdr 
241381a2a9aSdr #define	SLIST_INSERT_HEAD(head, elm, field) do {			\
242*85280f08SToomas Soome 	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
243*85280f08SToomas Soome 	SLIST_FIRST((head)) = (elm);					\
244381a2a9aSdr 	_NOTE(CONSTCOND)						\
245381a2a9aSdr } while (0)
246381a2a9aSdr 
247381a2a9aSdr #define	SLIST_REMOVE_HEAD(head, field) do {				\
248*85280f08SToomas Soome 	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
249*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
250*85280f08SToomas Soome } while (0)
251*85280f08SToomas Soome 
252*85280f08SToomas Soome #define	SLIST_REMOVE_AFTER(slistelm, field) do {			\
253*85280f08SToomas Soome 	SLIST_NEXT((slistelm), field) =					\
254*85280f08SToomas Soome 	    SLIST_NEXT(SLIST_NEXT((slistelm), field), field);		\
255381a2a9aSdr 	_NOTE(CONSTCOND)						\
256381a2a9aSdr } while (0)
257381a2a9aSdr 
258381a2a9aSdr #define	SLIST_REMOVE(head, elm, type, field) do {			\
259*85280f08SToomas Soome 	QMD_SAVELINK(oldnext, SLIST_NEXT((elm), field));		\
260*85280f08SToomas Soome 	if (SLIST_FIRST((head)) == (elm)) {				\
261381a2a9aSdr 		SLIST_REMOVE_HEAD((head), field);			\
262381a2a9aSdr 	}								\
263381a2a9aSdr 	else {								\
264*85280f08SToomas Soome 		QUEUE_TYPEOF(type) *curelm = SLIST_FIRST((head));	\
265*85280f08SToomas Soome 		while (SLIST_NEXT(curelm, field) != (elm))		\
266*85280f08SToomas Soome 			curelm = SLIST_NEXT(curelm, field);		\
267*85280f08SToomas Soome 		SLIST_REMOVE_AFTER(curelm, field);			\
268381a2a9aSdr 	}								\
269*85280f08SToomas Soome 	TRASHIT(*oldnext);						\
270381a2a9aSdr 	_NOTE(CONSTCOND)						\
271381a2a9aSdr } while (0)
272381a2a9aSdr 
273*85280f08SToomas Soome #define	SLIST_SWAP(head1, head2, type) do {				\
274*85280f08SToomas Soome 	QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1);		\
275*85280f08SToomas Soome 	SLIST_FIRST(head1) = SLIST_FIRST(head2);			\
276*85280f08SToomas Soome 	SLIST_FIRST(head2) = swap_first;				\
277*85280f08SToomas Soome } while (0)
278381a2a9aSdr 
279381a2a9aSdr /*
280381a2a9aSdr  * Singly-linked Tail queue declarations.
281381a2a9aSdr  */
282381a2a9aSdr #define	STAILQ_HEAD(name, type)						\
283381a2a9aSdr struct name {								\
284381a2a9aSdr 	struct type *stqh_first;	/* first element */		\
285381a2a9aSdr 	struct type **stqh_last;	/* addr of last next element */	\
286381a2a9aSdr }
287381a2a9aSdr 
288*85280f08SToomas Soome #define	STAILQ_CLASS_HEAD(name, type)					\
289*85280f08SToomas Soome struct name {								\
290*85280f08SToomas Soome 	class type *stqh_first;	/* first element */			\
291*85280f08SToomas Soome 	class type **stqh_last;	/* addr of last next element */		\
292*85280f08SToomas Soome }
293*85280f08SToomas Soome 
294381a2a9aSdr #define	STAILQ_HEAD_INITIALIZER(head)					\
295381a2a9aSdr 	{ NULL, &(head).stqh_first }
296381a2a9aSdr 
297381a2a9aSdr #define	STAILQ_ENTRY(type)						\
298381a2a9aSdr struct {								\
299*85280f08SToomas Soome 	struct type *stqe_next;	/* next element */			\
300381a2a9aSdr }
301381a2a9aSdr 
302*85280f08SToomas Soome #define	STAILQ_CLASS_ENTRY(type)					\
303*85280f08SToomas Soome struct {								\
304*85280f08SToomas Soome 	class type *stqe_next;	/* next element */			\
305*85280f08SToomas Soome }
306*85280f08SToomas Soome 
307*85280f08SToomas Soome /*
308*85280f08SToomas Soome  * Singly-linked Tail queue access methods.
309*85280f08SToomas Soome  */
310*85280f08SToomas Soome #define	STAILQ_FIRST(head)	((head)->stqh_first)
311*85280f08SToomas Soome #define	STAILQ_END(head)	NULL
312*85280f08SToomas Soome #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
313*85280f08SToomas Soome #define	STAILQ_EMPTY(head)	((head)->stqh_first == STAILQ_END(head))
314*85280f08SToomas Soome 
315*85280f08SToomas Soome #define	STAILQ_FOREACH(var, head, field)				\
316*85280f08SToomas Soome 	for ((var) = STAILQ_FIRST(head);				\
317*85280f08SToomas Soome 	    (var) != STAILQ_END(head);					\
318*85280f08SToomas Soome 	    (var) = STAILQ_NEXT((var), field))
319*85280f08SToomas Soome 
320*85280f08SToomas Soome #define	STAILQ_FOREACH_FROM(var, head, field)				\
321*85280f08SToomas Soome 	for ((var) =							\
322*85280f08SToomas Soome 	    ((var) != STAILQ_END(head) ? (var) : STAILQ_FIRST((head))); \
323*85280f08SToomas Soome 	    (var) != STAILQ_END(head);					\
324*85280f08SToomas Soome 	    (var) = STAILQ_NEXT((var), field))
325*85280f08SToomas Soome 
326*85280f08SToomas Soome #define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
327*85280f08SToomas Soome 	for ((var) = STAILQ_FIRST(head);				\
328*85280f08SToomas Soome 	    (var) != STAILQ_END(head) &&				\
329*85280f08SToomas Soome 	    ((tvar) = STAILQ_NEXT((var), field), 1);			\
330*85280f08SToomas Soome 	    (var) = (tvar))
331*85280f08SToomas Soome 
332*85280f08SToomas Soome #define	STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)		\
333*85280f08SToomas Soome 	for ((var) =							\
334*85280f08SToomas Soome 	    ((var) != STAILQ_END(head) ? (var) : STAILQ_FIRST((head))); \
335*85280f08SToomas Soome 	    (var) != STAILQ_END(head) &&				\
336*85280f08SToomas Soome 	    ((tvar) = STAILQ_NEXT((var), field), 1);			\
337*85280f08SToomas Soome 	    (var) = (tvar))
338*85280f08SToomas Soome 
339381a2a9aSdr /*
340381a2a9aSdr  * Singly-linked Tail queue functions.
341381a2a9aSdr  */
342381a2a9aSdr #define	STAILQ_INIT(head) do {						\
343*85280f08SToomas Soome 	STAILQ_FIRST(head) = STAILQ_END(head);				\
344*85280f08SToomas Soome 	(head)->stqh_last = &STAILQ_FIRST((head));			\
345*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
346*85280f08SToomas Soome } while (0)
347*85280f08SToomas Soome 
348*85280f08SToomas Soome #define	STAILQ_CONCAT(head1, head2) do {				\
349*85280f08SToomas Soome 	if (!STAILQ_EMPTY((head2))) {					\
350*85280f08SToomas Soome 		*(head1)->stqh_last = STAILQ_FIRST((head2));		\
351*85280f08SToomas Soome 		(head1)->stqh_last = (head2)->stqh_last;		\
352*85280f08SToomas Soome 		STAILQ_INIT((head2));					\
353*85280f08SToomas Soome 	}								\
354*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
355*85280f08SToomas Soome } while (0)
356*85280f08SToomas Soome 
357*85280f08SToomas Soome #define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
358*85280f08SToomas Soome 	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
359*85280f08SToomas Soome 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
360*85280f08SToomas Soome 	STAILQ_NEXT((tqelm), field) = (elm);				\
361381a2a9aSdr 	_NOTE(CONSTCOND)						\
362381a2a9aSdr } while (0)
363381a2a9aSdr 
364381a2a9aSdr #define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
365*85280f08SToomas Soome 	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
366*85280f08SToomas Soome 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
367*85280f08SToomas Soome 	STAILQ_FIRST((head)) = (elm);					\
368381a2a9aSdr 	_NOTE(CONSTCOND)						\
369381a2a9aSdr } while (0)
370381a2a9aSdr 
371381a2a9aSdr #define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
372*85280f08SToomas Soome 	STAILQ_NEXT((elm), field) = NULL;				\
373381a2a9aSdr 	*(head)->stqh_last = (elm);					\
374*85280f08SToomas Soome 	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
375381a2a9aSdr 	_NOTE(CONSTCOND)						\
376381a2a9aSdr } while (0)
377381a2a9aSdr 
378*85280f08SToomas Soome #define	STAILQ_LAST(head, type, field)					\
379*85280f08SToomas Soome 	(STAILQ_EMPTY((head)) ? NULL :					\
380*85280f08SToomas Soome 	    __containerof((head)->stqh_last,				\
381*85280f08SToomas Soome 	    QUEUE_TYPEOF(type), field.stqe_next))
382*85280f08SToomas Soome 
383*85280f08SToomas Soome #define	STAILQ_REMOVE_HEAD(head, field) do {				\
384*85280f08SToomas Soome 	if ((STAILQ_FIRST((head)) =					\
385*85280f08SToomas Soome 	    STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
386*85280f08SToomas Soome 		(head)->stqh_last = &STAILQ_FIRST((head));		\
387381a2a9aSdr 	_NOTE(CONSTCOND)						\
388381a2a9aSdr } while (0)
389381a2a9aSdr 
390*85280f08SToomas Soome #define	STAILQ_REMOVE_AFTER(head, elm, field) do {			\
391*85280f08SToomas Soome 	if ((STAILQ_NEXT(elm, field) =					\
392*85280f08SToomas Soome 	    STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
393*85280f08SToomas Soome 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
394381a2a9aSdr 	_NOTE(CONSTCOND)						\
395381a2a9aSdr } while (0)
396381a2a9aSdr 
397381a2a9aSdr #define	STAILQ_REMOVE(head, elm, type, field) do {			\
398*85280f08SToomas Soome 	QMD_SAVELINK(oldnext, (elm)->field.stqe_next);			\
399*85280f08SToomas Soome 	if (STAILQ_FIRST((head)) == (elm)) {				\
400381a2a9aSdr 		STAILQ_REMOVE_HEAD((head), field);			\
401381a2a9aSdr 	} else {							\
402*85280f08SToomas Soome 		QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head);	\
403*85280f08SToomas Soome 		while (STAILQ_NEXT(curelm, field) != (elm))		\
404*85280f08SToomas Soome 			curelm = STAILQ_NEXT(curelm, field);		\
405*85280f08SToomas Soome 		STAILQ_REMOVE_AFTER(head, curelm, field);		\
406381a2a9aSdr 	}								\
407*85280f08SToomas Soome 	TRASHIT(*oldnext);						\
4088c5d29abSToomas Soome 	_NOTE(CONSTCOND)						\
4098c5d29abSToomas Soome } while (0)
410381a2a9aSdr 
411*85280f08SToomas Soome #define	STAILQ_SWAP(head1, head2, type) do {				\
412*85280f08SToomas Soome 	QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1);		\
413*85280f08SToomas Soome 	QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last;		\
414*85280f08SToomas Soome 	STAILQ_FIRST(head1) = STAILQ_FIRST(head2);			\
415*85280f08SToomas Soome 	(head1)->stqh_last = (head2)->stqh_last;			\
416*85280f08SToomas Soome 	STAILQ_FIRST(head2) = swap_first;				\
417*85280f08SToomas Soome 	(head2)->stqh_last = swap_last;					\
418*85280f08SToomas Soome 	if (STAILQ_EMPTY(head1))					\
419*85280f08SToomas Soome 		(head1)->stqh_last = &STAILQ_FIRST(head1);		\
420*85280f08SToomas Soome 	if (STAILQ_EMPTY(head2))					\
421*85280f08SToomas Soome 		(head2)->stqh_last = &STAILQ_FIRST(head2);		\
422*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
423*85280f08SToomas Soome } while (0)
4248c5d29abSToomas Soome 
4258c5d29abSToomas Soome /*
426*85280f08SToomas Soome  * List definitions.
4278c5d29abSToomas Soome  */
428*85280f08SToomas Soome #define	LIST_HEAD(name, type)						\
429*85280f08SToomas Soome struct name {								\
430*85280f08SToomas Soome 	struct type *lh_first;	/* first element */			\
431*85280f08SToomas Soome }
4328c5d29abSToomas Soome 
433*85280f08SToomas Soome #define	LIST_CLASS_HEAD(name, type)					\
434*85280f08SToomas Soome struct name {								\
435*85280f08SToomas Soome 	class type *lh_first;	/* first element */			\
436*85280f08SToomas Soome }
437*85280f08SToomas Soome 
438*85280f08SToomas Soome #define	LIST_HEAD_INITIALIZER(head)					\
439*85280f08SToomas Soome 	{ NULL }
440*85280f08SToomas Soome 
441*85280f08SToomas Soome #define	LIST_ENTRY(type)						\
442*85280f08SToomas Soome struct {								\
443*85280f08SToomas Soome 	struct type *le_next;	/* next element */			\
444*85280f08SToomas Soome 	struct type **le_prev;	/* address of previous next element */	\
445*85280f08SToomas Soome }
446*85280f08SToomas Soome 
447*85280f08SToomas Soome #define	LIST_CLASS_ENTRY(type)						\
448*85280f08SToomas Soome struct {								\
449*85280f08SToomas Soome 	class type *le_next;	/* next element */			\
450*85280f08SToomas Soome 	class type **le_prev;	/* address of previous next element */	\
451*85280f08SToomas Soome }
452*85280f08SToomas Soome 
453*85280f08SToomas Soome /*
454*85280f08SToomas Soome  * List access methods.
455*85280f08SToomas Soome  */
456*85280f08SToomas Soome #define	LIST_FIRST(head)		((head)->lh_first)
457*85280f08SToomas Soome #define	LIST_END(head)			NULL
458*85280f08SToomas Soome #define	LIST_EMPTY(head)		((head)->lh_first == LIST_END(head))
459*85280f08SToomas Soome #define	LIST_NEXT(elm, field)		((elm)->field.le_next)
460*85280f08SToomas Soome #define	LIST_PREV(elm, head, type, field)				\
461*85280f08SToomas Soome 	((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL :		\
462*85280f08SToomas Soome 	__containerof((elm)->field.le_prev, type, field.le_next))
463*85280f08SToomas Soome 
464*85280f08SToomas Soome #define	LIST_FOREACH(var, head, field)					\
465*85280f08SToomas Soome 	for ((var) = LIST_FIRST((head));				\
466*85280f08SToomas Soome 	    (var) != LIST_END(head);					\
467*85280f08SToomas Soome 	    (var) = LIST_NEXT((var), field))
468*85280f08SToomas Soome 
469*85280f08SToomas Soome #define	LIST_FOREACH_FROM(var, head, field)				\
470*85280f08SToomas Soome 	for ((var) = ((var) != LIST_END(head) ? (var) : LIST_FIRST((head));\
471*85280f08SToomas Soome 	    (var) != LIST_END(head);					\
472*85280f08SToomas Soome 	    (var) = LIST_NEXT((var), field))
473*85280f08SToomas Soome 
474*85280f08SToomas Soome #define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
475*85280f08SToomas Soome 	for ((var) = LIST_FIRST((head));				\
476*85280f08SToomas Soome 	    (var) != LIST_END(head) &&				\
477*85280f08SToomas Soome 	    ((tvar) = LIST_NEXT((var), field), 1);			\
478*85280f08SToomas Soome 	    (var) = (tvar))
479*85280f08SToomas Soome 
480*85280f08SToomas Soome #define	LIST_FOREACH_FROM_SAFE(var, head, field, tvar)			\
481*85280f08SToomas Soome 	for ((var) = ((var) != LIST_END(head) ? (var) : LIST_FIRST((head));\
482*85280f08SToomas Soome 	    (var) != LIST_END(head) &&				\
483*85280f08SToomas Soome 	    ((tvar) = LIST_NEXT((var), field), 1);			\
484*85280f08SToomas Soome 	    (var) = (tvar))
485*85280f08SToomas Soome 
486*85280f08SToomas Soome /*
487*85280f08SToomas Soome  * List functions.
488*85280f08SToomas Soome  */
489*85280f08SToomas Soome #if defined(_KERNEL) && defined(QUEUEDEBUG)
490*85280f08SToomas Soome #define	QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)			\
491*85280f08SToomas Soome 	if ((head)->lh_first &&						\
492*85280f08SToomas Soome 	    (head)->lh_first->field.le_prev != &(head)->lh_first)	\
493*85280f08SToomas Soome 		panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
494*85280f08SToomas Soome #define	QUEUEDEBUG_LIST_OP(elm, field)					\
495*85280f08SToomas Soome 	if ((elm)->field.le_next &&					\
496*85280f08SToomas Soome 	    (elm)->field.le_next->field.le_prev !=			\
497*85280f08SToomas Soome 	    &(elm)->field.le_next)					\
498*85280f08SToomas Soome 		panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
499*85280f08SToomas Soome 	if (*(elm)->field.le_prev != (elm))				\
500*85280f08SToomas Soome 		panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__);
501*85280f08SToomas Soome #define	QUEUEDEBUG_LIST_POSTREMOVE(elm, field)				\
502*85280f08SToomas Soome 	(elm)->field.le_next = (void *)1L;				\
503*85280f08SToomas Soome 	(elm)->field.le_prev = (void *)1L;
504*85280f08SToomas Soome #else
505*85280f08SToomas Soome #define	QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
506*85280f08SToomas Soome #define	QUEUEDEBUG_LIST_OP(elm, field)
507*85280f08SToomas Soome #define	QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
508*85280f08SToomas Soome #endif
509*85280f08SToomas Soome 
510*85280f08SToomas Soome #define	LIST_INIT(head) do {						\
511*85280f08SToomas Soome 	LIST_FIRST((head)) = LIST_END(head);				\
512*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
513*85280f08SToomas Soome } while (0)
514*85280f08SToomas Soome 
515*85280f08SToomas Soome #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
516*85280f08SToomas Soome 	QUEUEDEBUG_LIST_OP((listelm), field)				\
517*85280f08SToomas Soome 	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
518*85280f08SToomas Soome 		LIST_NEXT((listelm), field)->field.le_prev =		\
519*85280f08SToomas Soome 		    &LIST_NEXT((elm), field);				\
520*85280f08SToomas Soome 	LIST_NEXT((listelm), field) = (elm);				\
521*85280f08SToomas Soome 	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
522*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
523*85280f08SToomas Soome } while (0)
524*85280f08SToomas Soome 
525*85280f08SToomas Soome #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
526*85280f08SToomas Soome 	QUEUEDEBUG_LIST_OP((listelm), field)				\
527*85280f08SToomas Soome 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
528*85280f08SToomas Soome 	LIST_NEXT((elm), field) = (listelm);				\
529*85280f08SToomas Soome 	*(listelm)->field.le_prev = (elm);				\
530*85280f08SToomas Soome 	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
531*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
532*85280f08SToomas Soome } while (0)
533*85280f08SToomas Soome 
534*85280f08SToomas Soome #define	LIST_INSERT_HEAD(head, elm, field) do {				\
535*85280f08SToomas Soome 	QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field)		\
536*85280f08SToomas Soome 	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
537*85280f08SToomas Soome 		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
538*85280f08SToomas Soome 	LIST_FIRST((head)) = (elm);					\
539*85280f08SToomas Soome 	(elm)->field.le_prev = &LIST_FIRST((head));			\
540*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
541*85280f08SToomas Soome } while (0)
542*85280f08SToomas Soome 
543*85280f08SToomas Soome #define	LIST_REMOVE(elm, field) do {					\
544*85280f08SToomas Soome 	QUEUEDEBUG_LIST_OP((elm), field)				\
545*85280f08SToomas Soome 	if (LIST_NEXT((elm), field) != NULL)				\
546*85280f08SToomas Soome 		LIST_NEXT((elm), field)->field.le_prev =		\
547*85280f08SToomas Soome 		    (elm)->field.le_prev;				\
548*85280f08SToomas Soome 	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
549*85280f08SToomas Soome 	QUEUEDEBUG_LIST_POSTREMOVE((elm), field)			\
550*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
551*85280f08SToomas Soome } while (0)
552*85280f08SToomas Soome 
553*85280f08SToomas Soome #define	LIST_SWAP(head1, head2, type, field) do {                       \
554*85280f08SToomas Soome 	QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1);               \
555*85280f08SToomas Soome 	LIST_FIRST((head1)) = LIST_FIRST((head2));                      \
556*85280f08SToomas Soome 	LIST_FIRST((head2)) = swap_tmp;                                 \
557*85280f08SToomas Soome 	if ((swap_tmp = LIST_FIRST((head1))) != NULL)                   \
558*85280f08SToomas Soome 		swap_tmp->field.le_prev = &LIST_FIRST((head1));         \
559*85280f08SToomas Soome 	if ((swap_tmp = LIST_FIRST((head2))) != NULL)                   \
560*85280f08SToomas Soome 		swap_tmp->field.le_prev = &LIST_FIRST((head2));         \
561*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
562*85280f08SToomas Soome } while (0)
563381a2a9aSdr 
564381a2a9aSdr /*
565381a2a9aSdr  * Simple queue definitions.
566381a2a9aSdr  */
567381a2a9aSdr #define	SIMPLEQ_HEAD(name, type)					\
568381a2a9aSdr struct name {								\
569381a2a9aSdr 	struct type *sqh_first;	/* first element */		\
570381a2a9aSdr 	struct type **sqh_last;	/* addr of last next element */	\
571381a2a9aSdr }
572381a2a9aSdr 
573*85280f08SToomas Soome #define	SIMPLEQ_CLASS_HEAD(name, type)					\
574*85280f08SToomas Soome struct name {								\
575*85280f08SToomas Soome 	class type *sqh_first;	/* first element */		\
576*85280f08SToomas Soome 	class type **sqh_last;	/* addr of last next element */	\
577*85280f08SToomas Soome }
578*85280f08SToomas Soome 
579381a2a9aSdr #define	SIMPLEQ_HEAD_INITIALIZER(head)					\
580381a2a9aSdr 	{ NULL, &(head).sqh_first }
581381a2a9aSdr 
582381a2a9aSdr #define	SIMPLEQ_ENTRY(type)						\
583381a2a9aSdr struct {								\
584381a2a9aSdr 	struct type *sqe_next;	/* next element */			\
585381a2a9aSdr }
586381a2a9aSdr 
587*85280f08SToomas Soome #define	SIMPLEQ_CLASS_ENTRY(type)					\
588*85280f08SToomas Soome struct {								\
589*85280f08SToomas Soome 	class type *sqe_next;	/* next element */			\
590*85280f08SToomas Soome }
591*85280f08SToomas Soome 
592*85280f08SToomas Soome /*
593*85280f08SToomas Soome  * Simple queue access methods.
594*85280f08SToomas Soome  */
595*85280f08SToomas Soome #define	SIMPLEQ_FIRST(head)		((head)->sqh_first)
596*85280f08SToomas Soome #define	SIMPLEQ_END(head)		NULL
597*85280f08SToomas Soome #define	SIMPLEQ_EMPTY(head)		((head)->sqh_first == SIMPLEQ_END(head))
598*85280f08SToomas Soome #define	SIMPLEQ_NEXT(elm, field)	((elm)->field.sqe_next)
599*85280f08SToomas Soome 
600*85280f08SToomas Soome #define	SIMPLEQ_FOREACH(var, head, field)				\
601*85280f08SToomas Soome 	for ((var) = SIMPLEQ_FIRST((head));				\
602*85280f08SToomas Soome 	    (var) != SIMPLEQ_END(head);					\
603*85280f08SToomas Soome 	    (var) = SIMPLEQ_NEXT((var), field))
604*85280f08SToomas Soome 
605*85280f08SToomas Soome #define	SIMPLEQ_FOREACH_FROM(var, head, field)				\
606*85280f08SToomas Soome 	for ((var) =							\
607*85280f08SToomas Soome 	    ((var) != SIMPLEQ_END(head) ? (var) : SIMPLEQ_FIRST((head)));\
608*85280f08SToomas Soome 	    (var) != SIMPLEQ_END(head);					\
609*85280f08SToomas Soome 	    (var) = SIMPLEQ_NEXT((var), field))
610*85280f08SToomas Soome 
611*85280f08SToomas Soome #define	SIMPLEQ_FOREACH_SAFE(var, head, field, tvar)			\
612*85280f08SToomas Soome 	for ((var) = SIMPLEQ_FIRST((head));				\
613*85280f08SToomas Soome 	    (var) != SIMPLEQ_END(head) &&				\
614*85280f08SToomas Soome 	    ((tvar) = SIMPLEQ_NEXT((var), field), 1);			\
615*85280f08SToomas Soome 	    (var) = (tvar))
616*85280f08SToomas Soome 
617*85280f08SToomas Soome #define	SIMPLEQ_FOREACH_FROM_SAFE(var, head, field, tvar)		\
618*85280f08SToomas Soome 	for ((var) =							\
619*85280f08SToomas Soome 	    ((var) != SIMPLEQ_END(head) ? (var) : SIMPLEQ_FIRST((head)));\
620*85280f08SToomas Soome 	    (var) != SIMPLEQ_END(head) &&				\
621*85280f08SToomas Soome 	    ((tvar) = SIMPLEQ_NEXT((var), field), 1);			\
622*85280f08SToomas Soome 	    (var) = (tvar))
623*85280f08SToomas Soome 
624381a2a9aSdr /*
625381a2a9aSdr  * Simple queue functions.
626381a2a9aSdr  */
627381a2a9aSdr #define	SIMPLEQ_INIT(head) do {						\
628*85280f08SToomas Soome 	SIMPLEQ_FIRST((head)) = NULL;					\
629*85280f08SToomas Soome 	(head)->sqh_last = &SIMPLEQ_FIRST((head));			\
630381a2a9aSdr 	_NOTE(CONSTCOND)						\
631381a2a9aSdr } while (0)
632381a2a9aSdr 
633381a2a9aSdr #define	SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
634*85280f08SToomas Soome 	if ((SIMPLEQ_NEXT((elm), field) = SIMPLEQ_FIRST((head))) == NULL)\
635*85280f08SToomas Soome 		(head)->sqh_last = &SIMPLEQ_NEXT((elm), field);		\
636*85280f08SToomas Soome 	SIMPLEQ_FIRST((head)) = (elm);					\
637381a2a9aSdr 	_NOTE(CONSTCOND)						\
638381a2a9aSdr } while (0)
639381a2a9aSdr 
640381a2a9aSdr #define	SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
641*85280f08SToomas Soome 	SIMPLEQ_NEXT((elm), field) = NULL;				\
642381a2a9aSdr 	*(head)->sqh_last = (elm);					\
643*85280f08SToomas Soome 	(head)->sqh_last = &SIMPLEQ_NEXT((elm), field);			\
644381a2a9aSdr 	_NOTE(CONSTCOND)						\
645381a2a9aSdr } while (0)
646381a2a9aSdr 
647381a2a9aSdr #define	SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
648*85280f08SToomas Soome 	if ((SIMPLEQ_NEXT((elm), field) = SIMPLEQ_NEXT((listelm), field)) == \
649*85280f08SToomas Soome 	    NULL)							\
650*85280f08SToomas Soome 		(head)->sqh_last = &SIMPLEQ_NEXT((elm), field);		\
651*85280f08SToomas Soome 	SIMPLEQ_NEXT((listelm), field) = (elm);				\
652381a2a9aSdr 	_NOTE(CONSTCOND)						\
653381a2a9aSdr } while (0)
654381a2a9aSdr 
655381a2a9aSdr #define	SIMPLEQ_REMOVE_HEAD(head, field) do {				\
656*85280f08SToomas Soome 	if ((SIMPLEQ_FIRST((head)) =					\
657*85280f08SToomas Soome 	    SIMPLEQ_NEXT(SIMPLEQ_FIRST((head)), field)) == NULL)	\
658*85280f08SToomas Soome 		(head)->sqh_last = &SIMPLEQ_FIRST((head));		\
659*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
660*85280f08SToomas Soome } while (0)
661*85280f08SToomas Soome 
662*85280f08SToomas Soome #define	SIMPLEQ_REMOVE_AFTER(head, elm, field) do {			\
663*85280f08SToomas Soome 	if ((SIMPLEQ_NEXT((elm)) =					\
664*85280f08SToomas Soome 	    SIMPLEQ_NEXT(SIMPLEQ_NEXT((elm), field), field)) == NULL)	\
665*85280f08SToomas Soome 		(head)->sqh_last = &SIMPLEQ_NEXT((elm), field);		\
666381a2a9aSdr 	_NOTE(CONSTCOND)						\
667381a2a9aSdr } while (0)
668381a2a9aSdr 
669381a2a9aSdr #define	SIMPLEQ_REMOVE(head, elm, type, field) do {			\
670*85280f08SToomas Soome 	if (SIMPLEQ_FIRST((head)) == (elm)) {				\
671381a2a9aSdr 		SIMPLEQ_REMOVE_HEAD((head), field);			\
672381a2a9aSdr 	} else {							\
673*85280f08SToomas Soome 		QUEUE_TYPEOF(type) *curelm = SIMPLEQ_FIRST((head));	\
674*85280f08SToomas Soome 		while (SIMPLEQ_NEXT(curelm, field) != (elm))		\
675*85280f08SToomas Soome 			curelm = SIMPLEQ_NEXT(curelm, field);		\
676*85280f08SToomas Soome 		SIMPLEQ_REMOVE_AFTER((head), curelm, field);		\
677381a2a9aSdr 	}								\
678381a2a9aSdr 	_NOTE(CONSTCOND)						\
679381a2a9aSdr } while (0)
680381a2a9aSdr 
681*85280f08SToomas Soome #define	SIMPLEQ_CONCAT(head1, head2) do {				\
682*85280f08SToomas Soome 	if (!SIMPLEQ_EMPTY((head2))) {					\
683*85280f08SToomas Soome 		*(head1)->sqh_last = (head2)->sqh_first;		\
684*85280f08SToomas Soome 		(head1)->sqh_last = (head2)->sqh_last;			\
685*85280f08SToomas Soome 		SIMPLEQ_INIT((head2));					\
686*85280f08SToomas Soome 	}								\
687*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
688*85280f08SToomas Soome } while (0)
689381a2a9aSdr 
690*85280f08SToomas Soome #define	SIMPLEQ_LAST(head, type, field)					\
691*85280f08SToomas Soome 	(SIMPLEQ_EMPTY((head)) ?					\
692*85280f08SToomas Soome 	    NULL :							\
693*85280f08SToomas Soome 	    ((QUEUE_TYPEOF(type) *)(void *)				\
694*85280f08SToomas Soome 	    ((char *)((head)->sqh_last) - offsetof(QUEUE_TYPEOF(type), field))))
695381a2a9aSdr 
696381a2a9aSdr /*
697381a2a9aSdr  * Tail queue definitions.
698381a2a9aSdr  */
699*85280f08SToomas Soome #define	TAILQ_HEAD(name, type)						\
700*85280f08SToomas Soome struct name {								\
701*85280f08SToomas Soome 	struct type *tqh_first;		/* first element */		\
702*85280f08SToomas Soome 	struct type **tqh_last;	/* addr of last next element */		\
703*85280f08SToomas Soome 	TRACEBUF							\
704*85280f08SToomas Soome }
705*85280f08SToomas Soome 
706*85280f08SToomas Soome #define	TAILQ_CLASS_HEAD(name, type)					\
707381a2a9aSdr struct name {								\
708*85280f08SToomas Soome 	class type *tqh_first;		/* first element */		\
709*85280f08SToomas Soome 	class type **tqh_last;	/* addr of last next element */		\
710*85280f08SToomas Soome 	TRACEBUF							\
711381a2a9aSdr }
712381a2a9aSdr 
713381a2a9aSdr #define	TAILQ_HEAD_INITIALIZER(head)					\
714381a2a9aSdr 	{ NULL, &(head).tqh_first }
715381a2a9aSdr 
716*85280f08SToomas Soome #define	TAILQ_ENTRY(type)						\
717381a2a9aSdr struct {								\
718*85280f08SToomas Soome 	struct type *tqe_next;	/* next element */			\
719*85280f08SToomas Soome 	struct type **tqe_prev;	/* address of previous next element */	\
720*85280f08SToomas Soome 	TRACEBUF							\
721*85280f08SToomas Soome }
722*85280f08SToomas Soome 
723*85280f08SToomas Soome #define	TAILQ_CLASS_ENTRY(type)						\
724*85280f08SToomas Soome struct {								\
725*85280f08SToomas Soome 	class type *tqe_next;	/* next element */			\
726*85280f08SToomas Soome 	class type **tqe_prev;	/* address of previous next element */	\
727*85280f08SToomas Soome 	TRACEBUF							\
728381a2a9aSdr }
729*85280f08SToomas Soome 
730*85280f08SToomas Soome /*
731*85280f08SToomas Soome  * Tail queue access methods.
732*85280f08SToomas Soome  */
733*85280f08SToomas Soome #define	TAILQ_FIRST(head)		((head)->tqh_first)
734*85280f08SToomas Soome #define	TAILQ_END(head)			NULL
735*85280f08SToomas Soome #define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
736*85280f08SToomas Soome #define	TAILQ_LAST(head, headname) \
737*85280f08SToomas Soome 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
738*85280f08SToomas Soome #define	TAILQ_PREV(elm, headname, field) \
739*85280f08SToomas Soome 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
740*85280f08SToomas Soome #define	TAILQ_EMPTY(head)		((head)->tqh_first == TAILQ_END(head))
741*85280f08SToomas Soome 
742*85280f08SToomas Soome 
743*85280f08SToomas Soome #define	TAILQ_FOREACH(var, head, field)					\
744*85280f08SToomas Soome 	for ((var) = TAILQ_FIRST((head));				\
745*85280f08SToomas Soome 	    (var) != TAILQ_END(head);					\
746*85280f08SToomas Soome 	    (var) = TAILQ_NEXT((var), field))
747*85280f08SToomas Soome 
748*85280f08SToomas Soome #define	TAILQ_FOREACH_FROM(var, head, field)				\
749*85280f08SToomas Soome 	for ((var) = ((var) != TAILQ_END((head)) ?			\
750*85280f08SToomas Soome 	    (var) : TAILQ_FIRST((head)));				\
751*85280f08SToomas Soome 	    (var) != TAILQ_END(head);					\
752*85280f08SToomas Soome 	    (var) = TAILQ_NEXT((var), field))
753*85280f08SToomas Soome 
754*85280f08SToomas Soome #define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
755*85280f08SToomas Soome 	for ((var) = TAILQ_FIRST((head));				\
756*85280f08SToomas Soome 	    (var) != TAILQ_END(head) &&					\
757*85280f08SToomas Soome 	    ((tvar) = TAILQ_NEXT((var), field), 1);			\
758*85280f08SToomas Soome 	    (var) = (tvar))
759*85280f08SToomas Soome 
760*85280f08SToomas Soome #define	TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)			\
761*85280f08SToomas Soome 	for ((var) = ((var) != TAILQ_END((head)) ?			\
762*85280f08SToomas Soome 	    (var) : TAILQ_FIRST((head)));				\
763*85280f08SToomas Soome 	    (var) != TAILQ_END(head) &&					\
764*85280f08SToomas Soome 	    ((tvar) = TAILQ_NEXT((var), field), 1);			\
765*85280f08SToomas Soome 	    (var) = (tvar))
766*85280f08SToomas Soome 
767*85280f08SToomas Soome #define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
768*85280f08SToomas Soome 	for ((var) = TAILQ_LAST((head), headname);			\
769*85280f08SToomas Soome 	    (var) != TAILQ_END(head);					\
770*85280f08SToomas Soome 	    (var) = TAILQ_PREV((var), headname, field))
771*85280f08SToomas Soome 
772*85280f08SToomas Soome #define	TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field)		\
773*85280f08SToomas Soome 	for ((var) = ((var) != TAILQ_END((head)) ?			\
774*85280f08SToomas Soome 	    (var) : TAILQ_LAST((head), headname));			\
775*85280f08SToomas Soome 	    (var) != TAILQ_END(head);					\
776*85280f08SToomas Soome 	    (var) = TAILQ_PREV((var), headname, field))
777*85280f08SToomas Soome 
778*85280f08SToomas Soome #define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
779*85280f08SToomas Soome 	for ((var) = TAILQ_LAST((head), headname);			\
780*85280f08SToomas Soome 	    (var) != TAILQ_END(head) &&					\
781*85280f08SToomas Soome 	    ((tvar) = TAILQ_PREV((var), headname, field), 1);		\
782*85280f08SToomas Soome 	    (var) = (tvar))
783*85280f08SToomas Soome 
784*85280f08SToomas Soome #define	TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar)\
785*85280f08SToomas Soome 	for ((var) = ((var) != TAILQ_END((head)) ?			\
786*85280f08SToomas Soome 	    (var) : TAILQ_LAST((head), headname));			\
787*85280f08SToomas Soome 	    (var) != TAILQ_END(head) &&					\
788*85280f08SToomas Soome 	    ((tvar) = TAILQ_PREV((var), headname, field), 1);		\
789*85280f08SToomas Soome 	    (var) = (tvar))
790381a2a9aSdr 
791381a2a9aSdr /*
792381a2a9aSdr  * Tail queue functions.
793381a2a9aSdr  */
794381a2a9aSdr #if defined(_KERNEL) && defined(QUEUEDEBUG)
795381a2a9aSdr #define	QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)			\
796381a2a9aSdr 	if ((head)->tqh_first &&					\
797381a2a9aSdr 	    (head)->tqh_first->field.tqe_prev != &(head)->tqh_first)	\
798c1374a13SSurya Prakki 		panic("TAILQ_INSERT_HEAD %p %s:%d", (void *)(head),	\
799c1374a13SSurya Prakki 		    __FILE__, __LINE__);
800381a2a9aSdr #define	QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)			\
801381a2a9aSdr 	if (*(head)->tqh_last != NULL)					\
802c1374a13SSurya Prakki 		panic("TAILQ_INSERT_TAIL %p %s:%d", (void *)(head),	\
803c1374a13SSurya Prakki 		    __FILE__, __LINE__);
804381a2a9aSdr #define	QUEUEDEBUG_TAILQ_OP(elm, field)					\
805381a2a9aSdr 	if ((elm)->field.tqe_next &&					\
806381a2a9aSdr 	    (elm)->field.tqe_next->field.tqe_prev !=			\
807381a2a9aSdr 	    &(elm)->field.tqe_next)					\
808c1374a13SSurya Prakki 		panic("TAILQ_* forw %p %s:%d", (void *)(elm),		\
809c1374a13SSurya Prakki 		    __FILE__, __LINE__);\
810381a2a9aSdr 	if (*(elm)->field.tqe_prev != (elm))				\
811c1374a13SSurya Prakki 		panic("TAILQ_* back %p %s:%d", (void *)(elm),		\
812c1374a13SSurya Prakki 		    __FILE__, __LINE__);
813381a2a9aSdr #define	QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)			\
814381a2a9aSdr 	if ((elm)->field.tqe_next == NULL &&				\
815381a2a9aSdr 	    (head)->tqh_last != &(elm)->field.tqe_next)			\
816381a2a9aSdr 		panic("TAILQ_PREREMOVE head %p elm %p %s:%d",		\
817c1374a13SSurya Prakki 		    (void *)(head), (void *)(elm), __FILE__, __LINE__);
818381a2a9aSdr #define	QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)				\
819381a2a9aSdr 	(elm)->field.tqe_next = (void *)1L;				\
820381a2a9aSdr 	(elm)->field.tqe_prev = (void *)1L;
821381a2a9aSdr #else
822381a2a9aSdr #define	QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
823381a2a9aSdr #define	QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
824381a2a9aSdr #define	QUEUEDEBUG_TAILQ_OP(elm, field)
825381a2a9aSdr #define	QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
826381a2a9aSdr #define	QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
827381a2a9aSdr #endif
828381a2a9aSdr 
829381a2a9aSdr #define	TAILQ_INIT(head) do {						\
830*85280f08SToomas Soome 	TAILQ_FIRST((head)) = TAILQ_END((head));			\
831*85280f08SToomas Soome 	(head)->tqh_last = &TAILQ_FIRST((head));			\
832381a2a9aSdr 	_NOTE(CONSTCOND)						\
833381a2a9aSdr } while (0)
834381a2a9aSdr 
835381a2a9aSdr #define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
836381a2a9aSdr 	QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field)		\
837*85280f08SToomas Soome 	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
838*85280f08SToomas Soome 		TAILQ_FIRST((head))->field.tqe_prev =			\
839*85280f08SToomas Soome 		    &TAILQ_NEXT((elm), field);				\
840381a2a9aSdr 	else								\
841*85280f08SToomas Soome 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
842*85280f08SToomas Soome 	TAILQ_FIRST((head)) = (elm);					\
843*85280f08SToomas Soome 	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
844381a2a9aSdr 	_NOTE(CONSTCOND)						\
845381a2a9aSdr } while (0)
846381a2a9aSdr 
847381a2a9aSdr #define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
848381a2a9aSdr 	QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field)		\
849*85280f08SToomas Soome 	TAILQ_NEXT((elm), field) = NULL;				\
850381a2a9aSdr 	(elm)->field.tqe_prev = (head)->tqh_last;			\
851381a2a9aSdr 	*(head)->tqh_last = (elm);					\
852*85280f08SToomas Soome 	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
853381a2a9aSdr 	_NOTE(CONSTCOND)						\
854381a2a9aSdr } while (0)
855381a2a9aSdr 
856381a2a9aSdr #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
857381a2a9aSdr 	QUEUEDEBUG_TAILQ_OP((listelm), field)				\
858*85280f08SToomas Soome 	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
859*85280f08SToomas Soome 		TAILQ_NEXT((elm), field)->field.tqe_prev =		\
860*85280f08SToomas Soome 		    &TAILQ_NEXT((elm), field);				\
861381a2a9aSdr 	else								\
862*85280f08SToomas Soome 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
863*85280f08SToomas Soome 	TAILQ_NEXT((listelm), field) = (elm);				\
864*85280f08SToomas Soome 	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
865381a2a9aSdr 	_NOTE(CONSTCOND)						\
866381a2a9aSdr } while (0)
867381a2a9aSdr 
868381a2a9aSdr #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
869381a2a9aSdr 	QUEUEDEBUG_TAILQ_OP((listelm), field)				\
870381a2a9aSdr 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
871*85280f08SToomas Soome 	TAILQ_NEXT((elm), field) = (listelm);				\
872381a2a9aSdr 	*(listelm)->field.tqe_prev = (elm);				\
873*85280f08SToomas Soome 	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
874381a2a9aSdr 	_NOTE(CONSTCOND)						\
875381a2a9aSdr } while (0)
876381a2a9aSdr 
877381a2a9aSdr #define	TAILQ_REMOVE(head, elm, field) do {				\
878381a2a9aSdr 	QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field)		\
879381a2a9aSdr 	QUEUEDEBUG_TAILQ_OP((elm), field)				\
880*85280f08SToomas Soome 	if ((TAILQ_NEXT((elm), field)) != NULL)				\
881*85280f08SToomas Soome 		TAILQ_NEXT((elm), field)->field.tqe_prev =		\
882381a2a9aSdr 		    (elm)->field.tqe_prev;				\
883381a2a9aSdr 	else								\
884381a2a9aSdr 		(head)->tqh_last = (elm)->field.tqe_prev;		\
885*85280f08SToomas Soome 	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
886381a2a9aSdr 	QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field);			\
887381a2a9aSdr 	_NOTE(CONSTCOND)						\
888381a2a9aSdr } while (0)
889381a2a9aSdr 
890*85280f08SToomas Soome #define	TAILQ_SWAP(head1, head2, type, field) do {			\
891*85280f08SToomas Soome 	QUEUE_TYPEOF(type) *swap_first = TAILQ_FIRST((head1));		\
892*85280f08SToomas Soome 	QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last;		\
893*85280f08SToomas Soome 	TAILQ_FIRST((head1)) = TAILQ_FIRST((head2));			\
894*85280f08SToomas Soome 	(head1)->tqh_last = (head2)->tqh_last;				\
895*85280f08SToomas Soome 	TAILQ_FIRST((head2)) = swap_first;				\
896*85280f08SToomas Soome 	(head2)->tqh_last = swap_last;					\
897*85280f08SToomas Soome 	if ((swap_first = TAILQ_FIRST((head1))) != NULL)		\
898*85280f08SToomas Soome 		swap_first->field.tqe_prev = &TAILQ_FIRST((head1));	\
899*85280f08SToomas Soome 	else								\
900*85280f08SToomas Soome 		(head1)->tqh_last = &TAILQ_FIRST((head1));		\
901*85280f08SToomas Soome 	if ((swap_first = TAILQ_FIRST((head2))) != NULL)		\
902*85280f08SToomas Soome 		swap_first->field.tqe_prev = &TAILQ_FIRST((head2));	\
903*85280f08SToomas Soome 	else								\
904*85280f08SToomas Soome 		(head2)->tqh_last = &TAILQ_FIRST((head2));		\
905*85280f08SToomas Soome 	_NOTE(CONSTCOND)						\
906*85280f08SToomas Soome } while (0)
907b346eeddSGordon Ross 
908b346eeddSGordon Ross /*
909*85280f08SToomas Soome  * Circular queue definitions. Do not use. We still keep the macros
910*85280f08SToomas Soome  * for compatibility but because of pointer aliasing issues their use
911*85280f08SToomas Soome  * is discouraged!
912381a2a9aSdr  */
913381a2a9aSdr #define	CIRCLEQ_HEAD(name, type)					\
914381a2a9aSdr struct name {								\
915381a2a9aSdr 	struct type *cqh_first;		/* first element */	\
916381a2a9aSdr 	struct type *cqh_last;		/* last element */		\
917381a2a9aSdr }
918381a2a9aSdr 
919381a2a9aSdr #define	CIRCLEQ_HEAD_INITIALIZER(head)					\
920381a2a9aSdr 	{ (void *)&head, (void *)&head }
921381a2a9aSdr 
922381a2a9aSdr #define	CIRCLEQ_ENTRY(type)						\
923381a2a9aSdr struct {								\
924381a2a9aSdr 	struct type *cqe_next;		/* next element */		\
925381a2a9aSdr 	struct type *cqe_prev;		/* previous element */		\
926381a2a9aSdr }
927381a2a9aSdr 
928*85280f08SToomas Soome /*
929*85280f08SToomas Soome  * Circular queue access methods.
930*85280f08SToomas Soome  */
931*85280f08SToomas Soome #define	CIRCLEQ_EMPTY(head)		((head)->cqh_first == (void *)(head))
932*85280f08SToomas Soome #define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
933*85280f08SToomas Soome #define	CIRCLEQ_LAST(head)		((head)->cqh_last)
934*85280f08SToomas Soome #define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
935*85280f08SToomas Soome #define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
936*85280f08SToomas Soome 
937*85280f08SToomas Soome #define	CIRCLEQ_LOOP_NEXT(head, elm, field)				\
938*85280f08SToomas Soome 	(((elm)->field.cqe_next == (void *)(head))			\
939*85280f08SToomas Soome 	    ? ((head)->cqh_first)					\
940*85280f08SToomas Soome 	    : (elm->field.cqe_next))
941*85280f08SToomas Soome #define	CIRCLEQ_LOOP_PREV(head, elm, field)				\
942*85280f08SToomas Soome 	(((elm)->field.cqe_prev == (void *)(head))			\
943*85280f08SToomas Soome 	    ? ((head)->cqh_last)					\
944*85280f08SToomas Soome 	    : (elm->field.cqe_prev))
945*85280f08SToomas Soome 
946*85280f08SToomas Soome #define	CIRCLEQ_FOREACH(var, head, field)				\
947*85280f08SToomas Soome 	for ((var) = CIRCLEQ_FIRST((head));				\
948*85280f08SToomas Soome 		(var) != (void *)(head);				\
949*85280f08SToomas Soome 		(var) = CIRCLEQ_NEXT((var), field))
950*85280f08SToomas Soome 
951*85280f08SToomas Soome #define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
952*85280f08SToomas Soome 	for ((var) = CIRCLEQ_LAST((head));				\
953*85280f08SToomas Soome 		(var) != (void *)(head);				\
954*85280f08SToomas Soome 		(var) = CIRCLEQ_PREV((var), field))
955*85280f08SToomas Soome 
956381a2a9aSdr /*
957381a2a9aSdr  * Circular queue functions.
958381a2a9aSdr  */
959381a2a9aSdr #define	CIRCLEQ_INIT(head) do {						\
960381a2a9aSdr 	(head)->cqh_first = (void *)(head);				\
961381a2a9aSdr 	(head)->cqh_last = (void *)(head);				\
962381a2a9aSdr 	_NOTE(CONSTCOND)						\
963381a2a9aSdr } while (0)
964381a2a9aSdr 
965381a2a9aSdr #define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
966381a2a9aSdr 	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
967381a2a9aSdr 	(elm)->field.cqe_prev = (listelm);				\
968381a2a9aSdr 	if ((listelm)->field.cqe_next == (void *)(head))		\
969381a2a9aSdr 		(head)->cqh_last = (elm);				\
970381a2a9aSdr 	else								\
971381a2a9aSdr 		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
972381a2a9aSdr 	(listelm)->field.cqe_next = (elm);				\
973381a2a9aSdr 	_NOTE(CONSTCOND)						\
974381a2a9aSdr } while (0)
975381a2a9aSdr 
976381a2a9aSdr #define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
977381a2a9aSdr 	(elm)->field.cqe_next = (listelm);				\
978381a2a9aSdr 	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
979381a2a9aSdr 	if ((listelm)->field.cqe_prev == (void *)(head))		\
980381a2a9aSdr 		(head)->cqh_first = (elm);				\
981381a2a9aSdr 	else								\
982381a2a9aSdr 		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
983381a2a9aSdr 	(listelm)->field.cqe_prev = (elm);				\
984381a2a9aSdr 	_NOTE(CONSTCOND)						\
985381a2a9aSdr } while (0)
986381a2a9aSdr 
987381a2a9aSdr #define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
988381a2a9aSdr 	(elm)->field.cqe_next = (head)->cqh_first;			\
989381a2a9aSdr 	(elm)->field.cqe_prev = (void *)(head);				\
990381a2a9aSdr 	if ((head)->cqh_last == (void *)(head))			\
991381a2a9aSdr 		(head)->cqh_last = (elm);				\
992381a2a9aSdr 	else								\
993381a2a9aSdr 		(head)->cqh_first->field.cqe_prev = (elm);		\
994381a2a9aSdr 	(head)->cqh_first = (elm);					\
995381a2a9aSdr 	_NOTE(CONSTCOND)						\
996381a2a9aSdr } while (0)
997381a2a9aSdr 
998381a2a9aSdr #define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
999381a2a9aSdr 	(elm)->field.cqe_next = (void *)(head);				\
1000381a2a9aSdr 	(elm)->field.cqe_prev = (head)->cqh_last;			\
1001381a2a9aSdr 	if ((head)->cqh_first == (void *)(head))			\
1002381a2a9aSdr 		(head)->cqh_first = (elm);				\
1003381a2a9aSdr 	else								\
1004381a2a9aSdr 		(head)->cqh_last->field.cqe_next = (elm);		\
1005381a2a9aSdr 	(head)->cqh_last = (elm);					\
1006381a2a9aSdr 	_NOTE(CONSTCOND)						\
1007381a2a9aSdr } while (0)
1008381a2a9aSdr 
1009381a2a9aSdr #define	CIRCLEQ_REMOVE(head, elm, field) do {				\
1010381a2a9aSdr 	if ((elm)->field.cqe_next == (void *)(head))			\
1011381a2a9aSdr 		(head)->cqh_last = (elm)->field.cqe_prev;		\
1012381a2a9aSdr 	else								\
1013381a2a9aSdr 		(elm)->field.cqe_next->field.cqe_prev =			\
1014381a2a9aSdr 		    (elm)->field.cqe_prev;				\
1015381a2a9aSdr 	if ((elm)->field.cqe_prev == (void *)(head))			\
1016381a2a9aSdr 		(head)->cqh_first = (elm)->field.cqe_next;		\
1017381a2a9aSdr 	else								\
1018381a2a9aSdr 		(elm)->field.cqe_prev->field.cqe_next =			\
1019381a2a9aSdr 		    (elm)->field.cqe_next;				\
1020381a2a9aSdr 	_NOTE(CONSTCOND)						\
1021381a2a9aSdr } while (0)
1022381a2a9aSdr 
1023*85280f08SToomas Soome #ifdef __cplusplus
1024381a2a9aSdr }
1025381a2a9aSdr #endif
1026381a2a9aSdr 
1027381a2a9aSdr #endif	/* !_SYS_QUEUE_H */
1028