xref: /onnv-gate/usr/src/uts/common/sys/queue.h (revision 2958:98aa41c076f5)
1*2958Sdr146992 /*	$NetBSD: queue.h,v 1.42 2005/07/13 15:08:24 wiz Exp $	*/
2*2958Sdr146992 
3*2958Sdr146992 /*
4*2958Sdr146992  * Copyright (c) 1991, 1993
5*2958Sdr146992  *	The Regents of the University of California.  All rights reserved.
6*2958Sdr146992  *
7*2958Sdr146992  * Redistribution and use in source and binary forms, with or without
8*2958Sdr146992  * modification, are permitted provided that the following conditions
9*2958Sdr146992  * are met:
10*2958Sdr146992  * 1. Redistributions of source code must retain the above copyright
11*2958Sdr146992  *    notice, this list of conditions and the following disclaimer.
12*2958Sdr146992  * 2. Redistributions in binary form must reproduce the above copyright
13*2958Sdr146992  *    notice, this list of conditions and the following disclaimer in the
14*2958Sdr146992  *    documentation and/or other materials provided with the distribution.
15*2958Sdr146992  * 3. Neither the name of the University nor the names of its contributors
16*2958Sdr146992  *    may be used to endorse or promote products derived from this software
17*2958Sdr146992  *    without specific prior written permission.
18*2958Sdr146992  *
19*2958Sdr146992  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20*2958Sdr146992  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21*2958Sdr146992  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22*2958Sdr146992  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23*2958Sdr146992  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24*2958Sdr146992  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25*2958Sdr146992  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*2958Sdr146992  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27*2958Sdr146992  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28*2958Sdr146992  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29*2958Sdr146992  * SUCH DAMAGE.
30*2958Sdr146992  *
31*2958Sdr146992  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
32*2958Sdr146992  */
33*2958Sdr146992 /*
34*2958Sdr146992  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
35*2958Sdr146992  * Use is subject to license terms.
36*2958Sdr146992  */
37*2958Sdr146992 
38*2958Sdr146992 #ifndef	_SYS_QUEUE_H
39*2958Sdr146992 #define	_SYS_QUEUE_H
40*2958Sdr146992 
41*2958Sdr146992 #pragma ident	"%Z%%M%	%I%	%E% SMI"
42*2958Sdr146992 
43*2958Sdr146992 #include <sys/note.h>
44*2958Sdr146992 
45*2958Sdr146992 #ifdef	__cplusplus
46*2958Sdr146992 extern "C" {
47*2958Sdr146992 #endif
48*2958Sdr146992 
49*2958Sdr146992 /*
50*2958Sdr146992  * This file defines five types of data structures: singly-linked lists,
51*2958Sdr146992  * lists, simple queues, tail queues, and circular queues.
52*2958Sdr146992  *
53*2958Sdr146992  * A singly-linked list is headed by a single forward pointer. The
54*2958Sdr146992  * elements are singly linked for minimum space and pointer manipulation
55*2958Sdr146992  * overhead at the expense of O(n) removal for arbitrary elements. New
56*2958Sdr146992  * elements can be added to the list after an existing element or at the
57*2958Sdr146992  * head of the list.  Elements being removed from the head of the list
58*2958Sdr146992  * should use the explicit macro for this purpose for optimum
59*2958Sdr146992  * efficiency. A singly-linked list may only be traversed in the forward
60*2958Sdr146992  * direction.  Singly-linked lists are ideal for applications with large
61*2958Sdr146992  * datasets and few or no removals or for implementing a LIFO queue.
62*2958Sdr146992  *
63*2958Sdr146992  * A list is headed by a single forward pointer (or an array of forward
64*2958Sdr146992  * pointers for a hash table header). The elements are doubly linked
65*2958Sdr146992  * so that an arbitrary element can be removed without a need to
66*2958Sdr146992  * traverse the list. New elements can be added to the list before
67*2958Sdr146992  * or after an existing element or at the head of the list. A list
68*2958Sdr146992  * may only be traversed in the forward direction.
69*2958Sdr146992  *
70*2958Sdr146992  * A simple queue is headed by a pair of pointers, one the head of the
71*2958Sdr146992  * list and the other to the tail of the list. The elements are singly
72*2958Sdr146992  * linked to save space, so elements can only be removed from the
73*2958Sdr146992  * head of the list. New elements can be added to the list after
74*2958Sdr146992  * an existing element, at the head of the list, or at the end of the
75*2958Sdr146992  * list. A simple queue may only be traversed in the forward direction.
76*2958Sdr146992  *
77*2958Sdr146992  * A tail queue is headed by a pair of pointers, one to the head of the
78*2958Sdr146992  * list and the other to the tail of the list. The elements are doubly
79*2958Sdr146992  * linked so that an arbitrary element can be removed without a need to
80*2958Sdr146992  * traverse the list. New elements can be added to the list before or
81*2958Sdr146992  * after an existing element, at the head of the list, or at the end of
82*2958Sdr146992  * the list. A tail queue may be traversed in either direction.
83*2958Sdr146992  *
84*2958Sdr146992  * A circle queue is headed by a pair of pointers, one to the head of the
85*2958Sdr146992  * list and the other to the tail of the list. The elements are doubly
86*2958Sdr146992  * linked so that an arbitrary element can be removed without a need to
87*2958Sdr146992  * traverse the list. New elements can be added to the list before or after
88*2958Sdr146992  * an existing element, at the head of the list, or at the end of the list.
89*2958Sdr146992  * A circle queue may be traversed in either direction, but has a more
90*2958Sdr146992  * complex end of list detection.
91*2958Sdr146992  *
92*2958Sdr146992  * For details on the use of these macros, see the queue(3) manual page.
93*2958Sdr146992  */
94*2958Sdr146992 
95*2958Sdr146992 /*
96*2958Sdr146992  * List definitions.
97*2958Sdr146992  */
98*2958Sdr146992 #define	LIST_HEAD(name, type)						\
99*2958Sdr146992 struct name {								\
100*2958Sdr146992 	struct type *lh_first;	/* first element */			\
101*2958Sdr146992 }
102*2958Sdr146992 
103*2958Sdr146992 #define	LIST_HEAD_INITIALIZER(head)					\
104*2958Sdr146992 	{ NULL }
105*2958Sdr146992 
106*2958Sdr146992 #define	LIST_ENTRY(type)						\
107*2958Sdr146992 struct {								\
108*2958Sdr146992 	struct type *le_next;	/* next element */			\
109*2958Sdr146992 	struct type **le_prev;	/* address of previous next element */	\
110*2958Sdr146992 }
111*2958Sdr146992 
112*2958Sdr146992 /*
113*2958Sdr146992  * List functions.
114*2958Sdr146992  */
115*2958Sdr146992 #if defined(_KERNEL) && defined(QUEUEDEBUG)
116*2958Sdr146992 #define	QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)			\
117*2958Sdr146992 	if ((head)->lh_first &&						\
118*2958Sdr146992 	    (head)->lh_first->field.le_prev != &(head)->lh_first)	\
119*2958Sdr146992 		panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
120*2958Sdr146992 #define	QUEUEDEBUG_LIST_OP(elm, field)					\
121*2958Sdr146992 	if ((elm)->field.le_next &&					\
122*2958Sdr146992 	    (elm)->field.le_next->field.le_prev !=			\
123*2958Sdr146992 	    &(elm)->field.le_next)					\
124*2958Sdr146992 		panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
125*2958Sdr146992 	if (*(elm)->field.le_prev != (elm))				\
126*2958Sdr146992 		panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__);
127*2958Sdr146992 #define	QUEUEDEBUG_LIST_POSTREMOVE(elm, field)				\
128*2958Sdr146992 	(elm)->field.le_next = (void *)1L;				\
129*2958Sdr146992 	(elm)->field.le_prev = (void *)1L;
130*2958Sdr146992 #else
131*2958Sdr146992 #define	QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
132*2958Sdr146992 #define	QUEUEDEBUG_LIST_OP(elm, field)
133*2958Sdr146992 #define	QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
134*2958Sdr146992 #endif
135*2958Sdr146992 
136*2958Sdr146992 #define	LIST_INIT(head) do {						\
137*2958Sdr146992 	(head)->lh_first = NULL;					\
138*2958Sdr146992 	_NOTE(CONSTCOND)						\
139*2958Sdr146992 } while (0)
140*2958Sdr146992 
141*2958Sdr146992 #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
142*2958Sdr146992 	QUEUEDEBUG_LIST_OP((listelm), field)				\
143*2958Sdr146992 	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
144*2958Sdr146992 		(listelm)->field.le_next->field.le_prev =		\
145*2958Sdr146992 		    &(elm)->field.le_next;				\
146*2958Sdr146992 	(listelm)->field.le_next = (elm);				\
147*2958Sdr146992 	(elm)->field.le_prev = &(listelm)->field.le_next;		\
148*2958Sdr146992 	_NOTE(CONSTCOND)						\
149*2958Sdr146992 } while (0)
150*2958Sdr146992 
151*2958Sdr146992 #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
152*2958Sdr146992 	QUEUEDEBUG_LIST_OP((listelm), field)				\
153*2958Sdr146992 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
154*2958Sdr146992 	(elm)->field.le_next = (listelm);				\
155*2958Sdr146992 	*(listelm)->field.le_prev = (elm);				\
156*2958Sdr146992 	(listelm)->field.le_prev = &(elm)->field.le_next;		\
157*2958Sdr146992 	_NOTE(CONSTCOND)						\
158*2958Sdr146992 } while (0)
159*2958Sdr146992 
160*2958Sdr146992 #define	LIST_INSERT_HEAD(head, elm, field) do {				\
161*2958Sdr146992 	QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field)		\
162*2958Sdr146992 	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
163*2958Sdr146992 		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
164*2958Sdr146992 	(head)->lh_first = (elm);					\
165*2958Sdr146992 	(elm)->field.le_prev = &(head)->lh_first;			\
166*2958Sdr146992 	_NOTE(CONSTCOND)						\
167*2958Sdr146992 } while (0)
168*2958Sdr146992 
169*2958Sdr146992 #define	LIST_REMOVE(elm, field) do {					\
170*2958Sdr146992 	QUEUEDEBUG_LIST_OP((elm), field)				\
171*2958Sdr146992 	if ((elm)->field.le_next != NULL)				\
172*2958Sdr146992 		(elm)->field.le_next->field.le_prev = 			\
173*2958Sdr146992 		    (elm)->field.le_prev;				\
174*2958Sdr146992 	*(elm)->field.le_prev = (elm)->field.le_next;			\
175*2958Sdr146992 	QUEUEDEBUG_LIST_POSTREMOVE((elm), field)			\
176*2958Sdr146992 	_NOTE(CONSTCOND)						\
177*2958Sdr146992 } while (0)
178*2958Sdr146992 
179*2958Sdr146992 #define	LIST_FOREACH(var, head, field)					\
180*2958Sdr146992 	for ((var) = ((head)->lh_first);				\
181*2958Sdr146992 		(var);							\
182*2958Sdr146992 		(var) = ((var)->field.le_next))
183*2958Sdr146992 
184*2958Sdr146992 /*
185*2958Sdr146992  * List access methods.
186*2958Sdr146992  */
187*2958Sdr146992 #define	LIST_EMPTY(head)		((head)->lh_first == NULL)
188*2958Sdr146992 #define	LIST_FIRST(head)		((head)->lh_first)
189*2958Sdr146992 #define	LIST_NEXT(elm, field)		((elm)->field.le_next)
190*2958Sdr146992 
191*2958Sdr146992 
192*2958Sdr146992 /*
193*2958Sdr146992  * Singly-linked List definitions.
194*2958Sdr146992  */
195*2958Sdr146992 #define	SLIST_HEAD(name, type)						\
196*2958Sdr146992 struct name {								\
197*2958Sdr146992 	struct type *slh_first;	/* first element */			\
198*2958Sdr146992 }
199*2958Sdr146992 
200*2958Sdr146992 #define	SLIST_HEAD_INITIALIZER(head)					\
201*2958Sdr146992 	{ NULL }
202*2958Sdr146992 
203*2958Sdr146992 #define	SLIST_ENTRY(type)						\
204*2958Sdr146992 struct {								\
205*2958Sdr146992 	struct type *sle_next;	/* next element */			\
206*2958Sdr146992 }
207*2958Sdr146992 
208*2958Sdr146992 /*
209*2958Sdr146992  * Singly-linked List functions.
210*2958Sdr146992  */
211*2958Sdr146992 #define	SLIST_INIT(head) do {						\
212*2958Sdr146992 	(head)->slh_first = NULL;					\
213*2958Sdr146992 	_NOTE(CONSTCOND)						\
214*2958Sdr146992 } while (0)
215*2958Sdr146992 
216*2958Sdr146992 #define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
217*2958Sdr146992 	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
218*2958Sdr146992 	(slistelm)->field.sle_next = (elm);				\
219*2958Sdr146992 	_NOTE(CONSTCOND)						\
220*2958Sdr146992 } while (0)
221*2958Sdr146992 
222*2958Sdr146992 #define	SLIST_INSERT_HEAD(head, elm, field) do {			\
223*2958Sdr146992 	(elm)->field.sle_next = (head)->slh_first;			\
224*2958Sdr146992 	(head)->slh_first = (elm);					\
225*2958Sdr146992 	_NOTE(CONSTCOND)						\
226*2958Sdr146992 } while (0)
227*2958Sdr146992 
228*2958Sdr146992 #define	SLIST_REMOVE_HEAD(head, field) do {				\
229*2958Sdr146992 	(head)->slh_first = (head)->slh_first->field.sle_next;		\
230*2958Sdr146992 	_NOTE(CONSTCOND)						\
231*2958Sdr146992 } while (0)
232*2958Sdr146992 
233*2958Sdr146992 #define	SLIST_REMOVE(head, elm, type, field) do {			\
234*2958Sdr146992 	if ((head)->slh_first == (elm)) {				\
235*2958Sdr146992 		SLIST_REMOVE_HEAD((head), field);			\
236*2958Sdr146992 	}								\
237*2958Sdr146992 	else {								\
238*2958Sdr146992 		struct type *curelm = (head)->slh_first;		\
239*2958Sdr146992 		while (curelm->field.sle_next != (elm))			\
240*2958Sdr146992 			curelm = curelm->field.sle_next;		\
241*2958Sdr146992 		curelm->field.sle_next =				\
242*2958Sdr146992 		    curelm->field.sle_next->field.sle_next;		\
243*2958Sdr146992 	}								\
244*2958Sdr146992 	_NOTE(CONSTCOND)						\
245*2958Sdr146992 } while (0)
246*2958Sdr146992 
247*2958Sdr146992 #define	SLIST_FOREACH(var, head, field)					\
248*2958Sdr146992 	for ((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
249*2958Sdr146992 
250*2958Sdr146992 /*
251*2958Sdr146992  * Singly-linked List access methods.
252*2958Sdr146992  */
253*2958Sdr146992 #define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
254*2958Sdr146992 #define	SLIST_FIRST(head)	((head)->slh_first)
255*2958Sdr146992 #define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
256*2958Sdr146992 
257*2958Sdr146992 
258*2958Sdr146992 /*
259*2958Sdr146992  * Singly-linked Tail queue declarations.
260*2958Sdr146992  */
261*2958Sdr146992 #define	STAILQ_HEAD(name, type)						\
262*2958Sdr146992 struct name {								\
263*2958Sdr146992 	struct type *stqh_first;	/* first element */		\
264*2958Sdr146992 	struct type **stqh_last;	/* addr of last next element */	\
265*2958Sdr146992 }
266*2958Sdr146992 
267*2958Sdr146992 #define	STAILQ_HEAD_INITIALIZER(head)					\
268*2958Sdr146992 	{ NULL, &(head).stqh_first }
269*2958Sdr146992 
270*2958Sdr146992 #define	STAILQ_ENTRY(type)						\
271*2958Sdr146992 struct {								\
272*2958Sdr146992 	struct type *stqe_next;	/* next element */		\
273*2958Sdr146992 }
274*2958Sdr146992 
275*2958Sdr146992 /*
276*2958Sdr146992  * Singly-linked Tail queue functions.
277*2958Sdr146992  */
278*2958Sdr146992 #define	STAILQ_INIT(head) do {						\
279*2958Sdr146992 	(head)->stqh_first = NULL;					\
280*2958Sdr146992 	(head)->stqh_last = &(head)->stqh_first;			\
281*2958Sdr146992 	_NOTE(CONSTCOND)						\
282*2958Sdr146992 } while (0)
283*2958Sdr146992 
284*2958Sdr146992 #define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
285*2958Sdr146992 	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
286*2958Sdr146992 		(head)->stqh_last = &(elm)->field.stqe_next;		\
287*2958Sdr146992 	(head)->stqh_first = (elm);					\
288*2958Sdr146992 	_NOTE(CONSTCOND)						\
289*2958Sdr146992 } while (0)
290*2958Sdr146992 
291*2958Sdr146992 #define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
292*2958Sdr146992 	(elm)->field.stqe_next = NULL;					\
293*2958Sdr146992 	*(head)->stqh_last = (elm);					\
294*2958Sdr146992 	(head)->stqh_last = &(elm)->field.stqe_next;			\
295*2958Sdr146992 	_NOTE(CONSTCOND)						\
296*2958Sdr146992 } while (0)
297*2958Sdr146992 
298*2958Sdr146992 #define	STAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
299*2958Sdr146992 	if (((elm)->field.stqe_next = (listelm)->field.stqe_next)	\
300*2958Sdr146992 	    == NULL)							\
301*2958Sdr146992 		(head)->stqh_last = &(elm)->field.stqe_next;		\
302*2958Sdr146992 	(listelm)->field.stqe_next = (elm);				\
303*2958Sdr146992 	_NOTE(CONSTCOND)						\
304*2958Sdr146992 } while (0)
305*2958Sdr146992 
306*2958Sdr146992 #define	STAILQ_REMOVE_HEAD(head, field) do {				\
307*2958Sdr146992 	if (((head)->stqh_first = (head)->stqh_first->field.stqe_next)	\
308*2958Sdr146992 	    == NULL) 							\
309*2958Sdr146992 		(head)->stqh_last = &(head)->stqh_first;		\
310*2958Sdr146992 	_NOTE(CONSTCOND)						\
311*2958Sdr146992 } while (0)
312*2958Sdr146992 
313*2958Sdr146992 #define	STAILQ_REMOVE(head, elm, type, field) do {			\
314*2958Sdr146992 	if ((head)->stqh_first == (elm)) {				\
315*2958Sdr146992 		STAILQ_REMOVE_HEAD((head), field);			\
316*2958Sdr146992 	} else {							\
317*2958Sdr146992 		struct type *curelm = (head)->stqh_first;		\
318*2958Sdr146992 		while (curelm->field.stqe_next != (elm))		\
319*2958Sdr146992 			curelm = curelm->field.stqe_next;		\
320*2958Sdr146992 		if ((curelm->field.stqe_next =				\
321*2958Sdr146992 			curelm->field.stqe_next->field.stqe_next) == NULL) \
322*2958Sdr146992 			    (head)->stqh_last = &(curelm)->field.stqe_next; \
323*2958Sdr146992 	}								\
324*2958Sdr146992 	_NOTE(CONSTCOND)						\
325*2958Sdr146992 } while (0)
326*2958Sdr146992 
327*2958Sdr146992 #define	STAILQ_FOREACH(var, head, field)				\
328*2958Sdr146992 	for ((var) = ((head)->stqh_first);				\
329*2958Sdr146992 		(var);							\
330*2958Sdr146992 		(var) = ((var)->field.stqe_next))
331*2958Sdr146992 
332*2958Sdr146992 /*
333*2958Sdr146992  * Singly-linked Tail queue access methods.
334*2958Sdr146992  */
335*2958Sdr146992 #define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
336*2958Sdr146992 #define	STAILQ_FIRST(head)	((head)->stqh_first)
337*2958Sdr146992 #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
338*2958Sdr146992 
339*2958Sdr146992 
340*2958Sdr146992 /*
341*2958Sdr146992  * Simple queue definitions.
342*2958Sdr146992  */
343*2958Sdr146992 #define	SIMPLEQ_HEAD(name, type)					\
344*2958Sdr146992 struct name {								\
345*2958Sdr146992 	struct type *sqh_first;	/* first element */		\
346*2958Sdr146992 	struct type **sqh_last;	/* addr of last next element */	\
347*2958Sdr146992 }
348*2958Sdr146992 
349*2958Sdr146992 #define	SIMPLEQ_HEAD_INITIALIZER(head)					\
350*2958Sdr146992 	{ NULL, &(head).sqh_first }
351*2958Sdr146992 
352*2958Sdr146992 #define	SIMPLEQ_ENTRY(type)						\
353*2958Sdr146992 struct {								\
354*2958Sdr146992 	struct type *sqe_next;	/* next element */			\
355*2958Sdr146992 }
356*2958Sdr146992 
357*2958Sdr146992 /*
358*2958Sdr146992  * Simple queue functions.
359*2958Sdr146992  */
360*2958Sdr146992 #define	SIMPLEQ_INIT(head) do {						\
361*2958Sdr146992 	(head)->sqh_first = NULL;					\
362*2958Sdr146992 	(head)->sqh_last = &(head)->sqh_first;				\
363*2958Sdr146992 	_NOTE(CONSTCOND)						\
364*2958Sdr146992 } while (0)
365*2958Sdr146992 
366*2958Sdr146992 #define	SIMPLEQ_INSERT_HEAD(head, elm, field) do {			\
367*2958Sdr146992 	if (((elm)->field.sqe_next = (head)->sqh_first) == NULL)	\
368*2958Sdr146992 		(head)->sqh_last = &(elm)->field.sqe_next;		\
369*2958Sdr146992 	(head)->sqh_first = (elm);					\
370*2958Sdr146992 	_NOTE(CONSTCOND)						\
371*2958Sdr146992 } while (0)
372*2958Sdr146992 
373*2958Sdr146992 #define	SIMPLEQ_INSERT_TAIL(head, elm, field) do {			\
374*2958Sdr146992 	(elm)->field.sqe_next = NULL;					\
375*2958Sdr146992 	*(head)->sqh_last = (elm);					\
376*2958Sdr146992 	(head)->sqh_last = &(elm)->field.sqe_next;			\
377*2958Sdr146992 	_NOTE(CONSTCOND)						\
378*2958Sdr146992 } while (0)
379*2958Sdr146992 
380*2958Sdr146992 #define	SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
381*2958Sdr146992 	if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
382*2958Sdr146992 		(head)->sqh_last = &(elm)->field.sqe_next;		\
383*2958Sdr146992 	(listelm)->field.sqe_next = (elm);				\
384*2958Sdr146992 	_NOTE(CONSTCOND)						\
385*2958Sdr146992 } while (0)
386*2958Sdr146992 
387*2958Sdr146992 #define	SIMPLEQ_REMOVE_HEAD(head, field) do {				\
388*2958Sdr146992 	if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
389*2958Sdr146992 		(head)->sqh_last = &(head)->sqh_first;			\
390*2958Sdr146992 	_NOTE(CONSTCOND)						\
391*2958Sdr146992 } while (0)
392*2958Sdr146992 
393*2958Sdr146992 #define	SIMPLEQ_REMOVE(head, elm, type, field) do {			\
394*2958Sdr146992 	if ((head)->sqh_first == (elm)) {				\
395*2958Sdr146992 		SIMPLEQ_REMOVE_HEAD((head), field);			\
396*2958Sdr146992 	} else {							\
397*2958Sdr146992 		struct type *curelm = (head)->sqh_first;		\
398*2958Sdr146992 		while (curelm->field.sqe_next != (elm))			\
399*2958Sdr146992 			curelm = curelm->field.sqe_next;		\
400*2958Sdr146992 		if ((curelm->field.sqe_next =				\
401*2958Sdr146992 			curelm->field.sqe_next->field.sqe_next) == NULL) \
402*2958Sdr146992 			    (head)->sqh_last = &(curelm)->field.sqe_next; \
403*2958Sdr146992 	}								\
404*2958Sdr146992 	_NOTE(CONSTCOND)						\
405*2958Sdr146992 } while (0)
406*2958Sdr146992 
407*2958Sdr146992 #define	SIMPLEQ_FOREACH(var, head, field)				\
408*2958Sdr146992 	for ((var) = ((head)->sqh_first);				\
409*2958Sdr146992 		(var);							\
410*2958Sdr146992 		(var) = ((var)->field.sqe_next))
411*2958Sdr146992 
412*2958Sdr146992 /*
413*2958Sdr146992  * Simple queue access methods.
414*2958Sdr146992  */
415*2958Sdr146992 #define	SIMPLEQ_EMPTY(head)		((head)->sqh_first == NULL)
416*2958Sdr146992 #define	SIMPLEQ_FIRST(head)		((head)->sqh_first)
417*2958Sdr146992 #define	SIMPLEQ_NEXT(elm, field)	((elm)->field.sqe_next)
418*2958Sdr146992 
419*2958Sdr146992 
420*2958Sdr146992 /*
421*2958Sdr146992  * Tail queue definitions.
422*2958Sdr146992  */
423*2958Sdr146992 #define	_TAILQ_HEAD(name, type)						\
424*2958Sdr146992 struct name {								\
425*2958Sdr146992 	type *tqh_first;		/* first element */		\
426*2958Sdr146992 	type **tqh_last;	/* addr of last next element */		\
427*2958Sdr146992 }
428*2958Sdr146992 #define	TAILQ_HEAD(name, type)	_TAILQ_HEAD(name, struct type)
429*2958Sdr146992 
430*2958Sdr146992 #define	TAILQ_HEAD_INITIALIZER(head)					\
431*2958Sdr146992 	{ NULL, &(head).tqh_first }
432*2958Sdr146992 
433*2958Sdr146992 #define	_TAILQ_ENTRY(type)						\
434*2958Sdr146992 struct {								\
435*2958Sdr146992 	type *tqe_next;		/* next element */			\
436*2958Sdr146992 	type **tqe_prev;	/* address of previous next element */\
437*2958Sdr146992 }
438*2958Sdr146992 #define	TAILQ_ENTRY(type)	_TAILQ_ENTRY(struct type)
439*2958Sdr146992 
440*2958Sdr146992 /*
441*2958Sdr146992  * Tail queue functions.
442*2958Sdr146992  */
443*2958Sdr146992 #if defined(_KERNEL) && defined(QUEUEDEBUG)
444*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)			\
445*2958Sdr146992 	if ((head)->tqh_first &&					\
446*2958Sdr146992 	    (head)->tqh_first->field.tqe_prev != &(head)->tqh_first)	\
447*2958Sdr146992 		panic("TAILQ_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__);
448*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)			\
449*2958Sdr146992 	if (*(head)->tqh_last != NULL)					\
450*2958Sdr146992 		panic("TAILQ_INSERT_TAIL %p %s:%d", (head), __FILE__, __LINE__);
451*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_OP(elm, field)					\
452*2958Sdr146992 	if ((elm)->field.tqe_next &&					\
453*2958Sdr146992 	    (elm)->field.tqe_next->field.tqe_prev !=			\
454*2958Sdr146992 	    &(elm)->field.tqe_next)					\
455*2958Sdr146992 		panic("TAILQ_* forw %p %s:%d", (elm), __FILE__, __LINE__);\
456*2958Sdr146992 	if (*(elm)->field.tqe_prev != (elm))				\
457*2958Sdr146992 		panic("TAILQ_* back %p %s:%d", (elm), __FILE__, __LINE__);
458*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)			\
459*2958Sdr146992 	if ((elm)->field.tqe_next == NULL &&				\
460*2958Sdr146992 	    (head)->tqh_last != &(elm)->field.tqe_next)			\
461*2958Sdr146992 		panic("TAILQ_PREREMOVE head %p elm %p %s:%d",		\
462*2958Sdr146992 		(head), (elm), __FILE__, __LINE__);
463*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)				\
464*2958Sdr146992 	(elm)->field.tqe_next = (void *)1L;				\
465*2958Sdr146992 	(elm)->field.tqe_prev = (void *)1L;
466*2958Sdr146992 #else
467*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
468*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
469*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_OP(elm, field)
470*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
471*2958Sdr146992 #define	QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
472*2958Sdr146992 #endif
473*2958Sdr146992 
474*2958Sdr146992 #define	TAILQ_INIT(head) do {						\
475*2958Sdr146992 	(head)->tqh_first = NULL;					\
476*2958Sdr146992 	(head)->tqh_last = &(head)->tqh_first;				\
477*2958Sdr146992 	_NOTE(CONSTCOND)						\
478*2958Sdr146992 } while (0)
479*2958Sdr146992 
480*2958Sdr146992 #define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
481*2958Sdr146992 	QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field)		\
482*2958Sdr146992 	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
483*2958Sdr146992 		(head)->tqh_first->field.tqe_prev =			\
484*2958Sdr146992 		    &(elm)->field.tqe_next;				\
485*2958Sdr146992 	else								\
486*2958Sdr146992 		(head)->tqh_last = &(elm)->field.tqe_next;		\
487*2958Sdr146992 	(head)->tqh_first = (elm);					\
488*2958Sdr146992 	(elm)->field.tqe_prev = &(head)->tqh_first;			\
489*2958Sdr146992 	_NOTE(CONSTCOND)						\
490*2958Sdr146992 } while (0)
491*2958Sdr146992 
492*2958Sdr146992 #define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
493*2958Sdr146992 	QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field)		\
494*2958Sdr146992 	(elm)->field.tqe_next = NULL;					\
495*2958Sdr146992 	(elm)->field.tqe_prev = (head)->tqh_last;			\
496*2958Sdr146992 	*(head)->tqh_last = (elm);					\
497*2958Sdr146992 	(head)->tqh_last = &(elm)->field.tqe_next;			\
498*2958Sdr146992 	_NOTE(CONSTCOND)						\
499*2958Sdr146992 } while (0)
500*2958Sdr146992 
501*2958Sdr146992 #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
502*2958Sdr146992 	QUEUEDEBUG_TAILQ_OP((listelm), field)				\
503*2958Sdr146992 	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
504*2958Sdr146992 		(elm)->field.tqe_next->field.tqe_prev = 		\
505*2958Sdr146992 		    &(elm)->field.tqe_next;				\
506*2958Sdr146992 	else								\
507*2958Sdr146992 		(head)->tqh_last = &(elm)->field.tqe_next;		\
508*2958Sdr146992 	(listelm)->field.tqe_next = (elm);				\
509*2958Sdr146992 	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
510*2958Sdr146992 	_NOTE(CONSTCOND)						\
511*2958Sdr146992 } while (0)
512*2958Sdr146992 
513*2958Sdr146992 #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
514*2958Sdr146992 	QUEUEDEBUG_TAILQ_OP((listelm), field)				\
515*2958Sdr146992 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
516*2958Sdr146992 	(elm)->field.tqe_next = (listelm);				\
517*2958Sdr146992 	*(listelm)->field.tqe_prev = (elm);				\
518*2958Sdr146992 	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
519*2958Sdr146992 	_NOTE(CONSTCOND)						\
520*2958Sdr146992 } while (0)
521*2958Sdr146992 
522*2958Sdr146992 #define	TAILQ_REMOVE(head, elm, field) do {				\
523*2958Sdr146992 	QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field)		\
524*2958Sdr146992 	QUEUEDEBUG_TAILQ_OP((elm), field)				\
525*2958Sdr146992 	if (((elm)->field.tqe_next) != NULL)				\
526*2958Sdr146992 		(elm)->field.tqe_next->field.tqe_prev = 		\
527*2958Sdr146992 		    (elm)->field.tqe_prev;				\
528*2958Sdr146992 	else								\
529*2958Sdr146992 		(head)->tqh_last = (elm)->field.tqe_prev;		\
530*2958Sdr146992 	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
531*2958Sdr146992 	QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field);			\
532*2958Sdr146992 	_NOTE(CONSTCOND)						\
533*2958Sdr146992 } while (0)
534*2958Sdr146992 
535*2958Sdr146992 #define	TAILQ_FOREACH(var, head, field)					\
536*2958Sdr146992 	for ((var) = ((head)->tqh_first);				\
537*2958Sdr146992 		(var);							\
538*2958Sdr146992 		(var) = ((var)->field.tqe_next))
539*2958Sdr146992 
540*2958Sdr146992 #define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
541*2958Sdr146992 	for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\
542*2958Sdr146992 		(var);							\
543*2958Sdr146992 		(var) = 						\
544*2958Sdr146992 		    (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
545*2958Sdr146992 
546*2958Sdr146992 /*
547*2958Sdr146992  * Tail queue access methods.
548*2958Sdr146992  */
549*2958Sdr146992 #define	TAILQ_EMPTY(head)		((head)->tqh_first == NULL)
550*2958Sdr146992 #define	TAILQ_FIRST(head)		((head)->tqh_first)
551*2958Sdr146992 #define	TAILQ_NEXT(elm, field)		((elm)->field.tqe_next)
552*2958Sdr146992 
553*2958Sdr146992 #define	TAILQ_LAST(head, headname) \
554*2958Sdr146992 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
555*2958Sdr146992 #define	TAILQ_PREV(elm, headname, field) \
556*2958Sdr146992 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
557*2958Sdr146992 
558*2958Sdr146992 
559*2958Sdr146992 /*
560*2958Sdr146992  * Circular queue definitions.
561*2958Sdr146992  */
562*2958Sdr146992 #define	CIRCLEQ_HEAD(name, type)					\
563*2958Sdr146992 struct name {								\
564*2958Sdr146992 	struct type *cqh_first;		/* first element */	\
565*2958Sdr146992 	struct type *cqh_last;		/* last element */		\
566*2958Sdr146992 }
567*2958Sdr146992 
568*2958Sdr146992 #define	CIRCLEQ_HEAD_INITIALIZER(head)					\
569*2958Sdr146992 	{ (void *)&head, (void *)&head }
570*2958Sdr146992 
571*2958Sdr146992 #define	CIRCLEQ_ENTRY(type)						\
572*2958Sdr146992 struct {								\
573*2958Sdr146992 	struct type *cqe_next;		/* next element */		\
574*2958Sdr146992 	struct type *cqe_prev;		/* previous element */		\
575*2958Sdr146992 }
576*2958Sdr146992 
577*2958Sdr146992 /*
578*2958Sdr146992  * Circular queue functions.
579*2958Sdr146992  */
580*2958Sdr146992 #define	CIRCLEQ_INIT(head) do {						\
581*2958Sdr146992 	(head)->cqh_first = (void *)(head);				\
582*2958Sdr146992 	(head)->cqh_last = (void *)(head);				\
583*2958Sdr146992 	_NOTE(CONSTCOND)						\
584*2958Sdr146992 } while (0)
585*2958Sdr146992 
586*2958Sdr146992 #define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
587*2958Sdr146992 	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
588*2958Sdr146992 	(elm)->field.cqe_prev = (listelm);				\
589*2958Sdr146992 	if ((listelm)->field.cqe_next == (void *)(head))		\
590*2958Sdr146992 		(head)->cqh_last = (elm);				\
591*2958Sdr146992 	else								\
592*2958Sdr146992 		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
593*2958Sdr146992 	(listelm)->field.cqe_next = (elm);				\
594*2958Sdr146992 	_NOTE(CONSTCOND)						\
595*2958Sdr146992 } while (0)
596*2958Sdr146992 
597*2958Sdr146992 #define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
598*2958Sdr146992 	(elm)->field.cqe_next = (listelm);				\
599*2958Sdr146992 	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
600*2958Sdr146992 	if ((listelm)->field.cqe_prev == (void *)(head))		\
601*2958Sdr146992 		(head)->cqh_first = (elm);				\
602*2958Sdr146992 	else								\
603*2958Sdr146992 		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
604*2958Sdr146992 	(listelm)->field.cqe_prev = (elm);				\
605*2958Sdr146992 	_NOTE(CONSTCOND)						\
606*2958Sdr146992 } while (0)
607*2958Sdr146992 
608*2958Sdr146992 #define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
609*2958Sdr146992 	(elm)->field.cqe_next = (head)->cqh_first;			\
610*2958Sdr146992 	(elm)->field.cqe_prev = (void *)(head);				\
611*2958Sdr146992 	if ((head)->cqh_last == (void *)(head))			\
612*2958Sdr146992 		(head)->cqh_last = (elm);				\
613*2958Sdr146992 	else								\
614*2958Sdr146992 		(head)->cqh_first->field.cqe_prev = (elm);		\
615*2958Sdr146992 	(head)->cqh_first = (elm);					\
616*2958Sdr146992 	_NOTE(CONSTCOND)						\
617*2958Sdr146992 } while (0)
618*2958Sdr146992 
619*2958Sdr146992 #define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
620*2958Sdr146992 	(elm)->field.cqe_next = (void *)(head);				\
621*2958Sdr146992 	(elm)->field.cqe_prev = (head)->cqh_last;			\
622*2958Sdr146992 	if ((head)->cqh_first == (void *)(head))			\
623*2958Sdr146992 		(head)->cqh_first = (elm);				\
624*2958Sdr146992 	else								\
625*2958Sdr146992 		(head)->cqh_last->field.cqe_next = (elm);		\
626*2958Sdr146992 	(head)->cqh_last = (elm);					\
627*2958Sdr146992 	_NOTE(CONSTCOND)						\
628*2958Sdr146992 } while (0)
629*2958Sdr146992 
630*2958Sdr146992 #define	CIRCLEQ_REMOVE(head, elm, field) do {				\
631*2958Sdr146992 	if ((elm)->field.cqe_next == (void *)(head))			\
632*2958Sdr146992 		(head)->cqh_last = (elm)->field.cqe_prev;		\
633*2958Sdr146992 	else								\
634*2958Sdr146992 		(elm)->field.cqe_next->field.cqe_prev =			\
635*2958Sdr146992 		    (elm)->field.cqe_prev;				\
636*2958Sdr146992 	if ((elm)->field.cqe_prev == (void *)(head))			\
637*2958Sdr146992 		(head)->cqh_first = (elm)->field.cqe_next;		\
638*2958Sdr146992 	else								\
639*2958Sdr146992 		(elm)->field.cqe_prev->field.cqe_next =			\
640*2958Sdr146992 		    (elm)->field.cqe_next;				\
641*2958Sdr146992 	_NOTE(CONSTCOND)						\
642*2958Sdr146992 } while (0)
643*2958Sdr146992 
644*2958Sdr146992 #define	CIRCLEQ_FOREACH(var, head, field)				\
645*2958Sdr146992 	for ((var) = ((head)->cqh_first);				\
646*2958Sdr146992 		(var) != (void *)(head);				\
647*2958Sdr146992 		(var) = ((var)->field.cqe_next))
648*2958Sdr146992 
649*2958Sdr146992 #define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
650*2958Sdr146992 	for ((var) = ((head)->cqh_last);				\
651*2958Sdr146992 		(var) != (void *)(head);				\
652*2958Sdr146992 		(var) = ((var)->field.cqe_prev))
653*2958Sdr146992 
654*2958Sdr146992 /*
655*2958Sdr146992  * Circular queue access methods.
656*2958Sdr146992  */
657*2958Sdr146992 #define	CIRCLEQ_EMPTY(head)		((head)->cqh_first == (void *)(head))
658*2958Sdr146992 #define	CIRCLEQ_FIRST(head)		((head)->cqh_first)
659*2958Sdr146992 #define	CIRCLEQ_LAST(head)		((head)->cqh_last)
660*2958Sdr146992 #define	CIRCLEQ_NEXT(elm, field)	((elm)->field.cqe_next)
661*2958Sdr146992 #define	CIRCLEQ_PREV(elm, field)	((elm)->field.cqe_prev)
662*2958Sdr146992 
663*2958Sdr146992 #ifdef	__cplusplus
664*2958Sdr146992 }
665*2958Sdr146992 #endif
666*2958Sdr146992 
667*2958Sdr146992 #endif	/* !_SYS_QUEUE_H */
668