xref: /f-stack/freebsd/sys/queue.h (revision 22ce4aff)
1a9643ea8Slogwang /*-
2*22ce4affSfengbojiang  * SPDX-License-Identifier: BSD-3-Clause
3*22ce4affSfengbojiang  *
4a9643ea8Slogwang  * Copyright (c) 1991, 1993
5a9643ea8Slogwang  *	The Regents of the University of California.  All rights reserved.
6a9643ea8Slogwang  *
7a9643ea8Slogwang  * Redistribution and use in source and binary forms, with or without
8a9643ea8Slogwang  * modification, are permitted provided that the following conditions
9a9643ea8Slogwang  * are met:
10a9643ea8Slogwang  * 1. Redistributions of source code must retain the above copyright
11a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer.
12a9643ea8Slogwang  * 2. Redistributions in binary form must reproduce the above copyright
13a9643ea8Slogwang  *    notice, this list of conditions and the following disclaimer in the
14a9643ea8Slogwang  *    documentation and/or other materials provided with the distribution.
15*22ce4affSfengbojiang  * 3. Neither the name of the University nor the names of its contributors
16a9643ea8Slogwang  *    may be used to endorse or promote products derived from this software
17a9643ea8Slogwang  *    without specific prior written permission.
18a9643ea8Slogwang  *
19a9643ea8Slogwang  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20a9643ea8Slogwang  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21a9643ea8Slogwang  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22a9643ea8Slogwang  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23a9643ea8Slogwang  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24a9643ea8Slogwang  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25a9643ea8Slogwang  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26a9643ea8Slogwang  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27a9643ea8Slogwang  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28a9643ea8Slogwang  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29a9643ea8Slogwang  * SUCH DAMAGE.
30a9643ea8Slogwang  *
31a9643ea8Slogwang  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
32a9643ea8Slogwang  * $FreeBSD$
33a9643ea8Slogwang  */
34a9643ea8Slogwang 
35a9643ea8Slogwang #ifndef _SYS_QUEUE_H_
36a9643ea8Slogwang #define	_SYS_QUEUE_H_
37a9643ea8Slogwang 
38a9643ea8Slogwang #include <sys/cdefs.h>
39a9643ea8Slogwang 
40a9643ea8Slogwang /*
41a9643ea8Slogwang  * This file defines four types of data structures: singly-linked lists,
42a9643ea8Slogwang  * singly-linked tail queues, lists and tail queues.
43a9643ea8Slogwang  *
44a9643ea8Slogwang  * A singly-linked list is headed by a single forward pointer. The elements
45a9643ea8Slogwang  * are singly linked for minimum space and pointer manipulation overhead at
46a9643ea8Slogwang  * the expense of O(n) removal for arbitrary elements. New elements can be
47a9643ea8Slogwang  * added to the list after an existing element or at the head of the list.
48a9643ea8Slogwang  * Elements being removed from the head of the list should use the explicit
49a9643ea8Slogwang  * macro for this purpose for optimum efficiency. A singly-linked list may
50a9643ea8Slogwang  * only be traversed in the forward direction.  Singly-linked lists are ideal
51a9643ea8Slogwang  * for applications with large datasets and few or no removals or for
52a9643ea8Slogwang  * implementing a LIFO queue.
53a9643ea8Slogwang  *
54a9643ea8Slogwang  * A singly-linked tail queue is headed by a pair of pointers, one to the
55a9643ea8Slogwang  * head of the list and the other to the tail of the list. The elements are
56a9643ea8Slogwang  * singly linked for minimum space and pointer manipulation overhead at the
57a9643ea8Slogwang  * expense of O(n) removal for arbitrary elements. New elements can be added
58a9643ea8Slogwang  * to the list after an existing element, at the head of the list, or at the
59a9643ea8Slogwang  * end of the list. Elements being removed from the head of the tail queue
60a9643ea8Slogwang  * should use the explicit macro for this purpose for optimum efficiency.
61a9643ea8Slogwang  * A singly-linked tail queue may only be traversed in the forward direction.
62a9643ea8Slogwang  * Singly-linked tail queues are ideal for applications with large datasets
63a9643ea8Slogwang  * and few or no removals or for implementing a FIFO queue.
64a9643ea8Slogwang  *
65a9643ea8Slogwang  * A list is headed by a single forward pointer (or an array of forward
66a9643ea8Slogwang  * pointers for a hash table header). The elements are doubly linked
67a9643ea8Slogwang  * so that an arbitrary element can be removed without a need to
68a9643ea8Slogwang  * traverse the list. New elements can be added to the list before
69a9643ea8Slogwang  * or after an existing element or at the head of the list. A list
70a9643ea8Slogwang  * may be traversed in either direction.
71a9643ea8Slogwang  *
72a9643ea8Slogwang  * A tail queue is headed by a pair of pointers, one to the head of the
73a9643ea8Slogwang  * list and the other to the tail of the list. The elements are doubly
74a9643ea8Slogwang  * linked so that an arbitrary element can be removed without a need to
75a9643ea8Slogwang  * traverse the list. New elements can be added to the list before or
76a9643ea8Slogwang  * after an existing element, at the head of the list, or at the end of
77a9643ea8Slogwang  * the list. A tail queue may be traversed in either direction.
78a9643ea8Slogwang  *
79a9643ea8Slogwang  * For details on the use of these macros, see the queue(3) manual page.
80a9643ea8Slogwang  *
81*22ce4affSfengbojiang  * Below is a summary of implemented functions where:
82*22ce4affSfengbojiang  *  +  means the macro is available
83*22ce4affSfengbojiang  *  -  means the macro is not available
84*22ce4affSfengbojiang  *  s  means the macro is available but is slow (runs in O(n) time)
85a9643ea8Slogwang  *
86a9643ea8Slogwang  *				SLIST	LIST	STAILQ	TAILQ
87a9643ea8Slogwang  * _HEAD			+	+	+	+
88a9643ea8Slogwang  * _CLASS_HEAD			+	+	+	+
89a9643ea8Slogwang  * _HEAD_INITIALIZER		+	+	+	+
90a9643ea8Slogwang  * _ENTRY			+	+	+	+
91a9643ea8Slogwang  * _CLASS_ENTRY			+	+	+	+
92a9643ea8Slogwang  * _INIT			+	+	+	+
93a9643ea8Slogwang  * _EMPTY			+	+	+	+
94a9643ea8Slogwang  * _FIRST			+	+	+	+
95a9643ea8Slogwang  * _NEXT			+	+	+	+
96a9643ea8Slogwang  * _PREV			-	+	-	+
97a9643ea8Slogwang  * _LAST			-	-	+	+
98*22ce4affSfengbojiang  * _LAST_FAST			-	-	-	+
99a9643ea8Slogwang  * _FOREACH			+	+	+	+
100a9643ea8Slogwang  * _FOREACH_FROM		+	+	+	+
101a9643ea8Slogwang  * _FOREACH_SAFE		+	+	+	+
102a9643ea8Slogwang  * _FOREACH_FROM_SAFE		+	+	+	+
103a9643ea8Slogwang  * _FOREACH_REVERSE		-	-	-	+
104a9643ea8Slogwang  * _FOREACH_REVERSE_FROM	-	-	-	+
105a9643ea8Slogwang  * _FOREACH_REVERSE_SAFE	-	-	-	+
106a9643ea8Slogwang  * _FOREACH_REVERSE_FROM_SAFE	-	-	-	+
107a9643ea8Slogwang  * _INSERT_HEAD			+	+	+	+
108a9643ea8Slogwang  * _INSERT_BEFORE		-	+	-	+
109a9643ea8Slogwang  * _INSERT_AFTER		+	+	+	+
110a9643ea8Slogwang  * _INSERT_TAIL			-	-	+	+
111*22ce4affSfengbojiang  * _CONCAT			s	s	+	+
112a9643ea8Slogwang  * _REMOVE_AFTER		+	-	+	-
113a9643ea8Slogwang  * _REMOVE_HEAD			+	-	+	-
114*22ce4affSfengbojiang  * _REMOVE			s	+	s	+
115a9643ea8Slogwang  * _SWAP			+	+	+	+
116a9643ea8Slogwang  *
117a9643ea8Slogwang  */
118a9643ea8Slogwang #ifdef QUEUE_MACRO_DEBUG
119*22ce4affSfengbojiang #warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
120*22ce4affSfengbojiang #define	QUEUE_MACRO_DEBUG_TRACE
121*22ce4affSfengbojiang #define	QUEUE_MACRO_DEBUG_TRASH
122*22ce4affSfengbojiang #endif
123*22ce4affSfengbojiang 
124*22ce4affSfengbojiang #ifdef QUEUE_MACRO_DEBUG_TRACE
125a9643ea8Slogwang /* Store the last 2 places the queue element or head was altered */
126a9643ea8Slogwang struct qm_trace {
127a9643ea8Slogwang 	unsigned long	 lastline;
128a9643ea8Slogwang 	unsigned long	 prevline;
129a9643ea8Slogwang 	const char	*lastfile;
130a9643ea8Slogwang 	const char	*prevfile;
131a9643ea8Slogwang };
132a9643ea8Slogwang 
133a9643ea8Slogwang #define	TRACEBUF	struct qm_trace trace;
134a9643ea8Slogwang #define	TRACEBUF_INITIALIZER	{ __LINE__, 0, __FILE__, NULL } ,
135a9643ea8Slogwang 
136a9643ea8Slogwang #define	QMD_TRACE_HEAD(head) do {					\
137a9643ea8Slogwang 	(head)->trace.prevline = (head)->trace.lastline;		\
138a9643ea8Slogwang 	(head)->trace.prevfile = (head)->trace.lastfile;		\
139a9643ea8Slogwang 	(head)->trace.lastline = __LINE__;				\
140a9643ea8Slogwang 	(head)->trace.lastfile = __FILE__;				\
141a9643ea8Slogwang } while (0)
142a9643ea8Slogwang 
143a9643ea8Slogwang #define	QMD_TRACE_ELEM(elem) do {					\
144a9643ea8Slogwang 	(elem)->trace.prevline = (elem)->trace.lastline;		\
145a9643ea8Slogwang 	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
146a9643ea8Slogwang 	(elem)->trace.lastline = __LINE__;				\
147a9643ea8Slogwang 	(elem)->trace.lastfile = __FILE__;				\
148a9643ea8Slogwang } while (0)
149a9643ea8Slogwang 
150*22ce4affSfengbojiang #else	/* !QUEUE_MACRO_DEBUG_TRACE */
151a9643ea8Slogwang #define	QMD_TRACE_ELEM(elem)
152a9643ea8Slogwang #define	QMD_TRACE_HEAD(head)
153a9643ea8Slogwang #define	TRACEBUF
154a9643ea8Slogwang #define	TRACEBUF_INITIALIZER
155*22ce4affSfengbojiang #endif	/* QUEUE_MACRO_DEBUG_TRACE */
156*22ce4affSfengbojiang 
157*22ce4affSfengbojiang #ifdef QUEUE_MACRO_DEBUG_TRASH
158*22ce4affSfengbojiang #define	QMD_SAVELINK(name, link)	void **name = (void *)&(link)
159*22ce4affSfengbojiang #define	TRASHIT(x)		do {(x) = (void *)-1;} while (0)
160*22ce4affSfengbojiang #define	QMD_IS_TRASHED(x)	((x) == (void *)(intptr_t)-1)
161*22ce4affSfengbojiang #else	/* !QUEUE_MACRO_DEBUG_TRASH */
162*22ce4affSfengbojiang #define	QMD_SAVELINK(name, link)
163a9643ea8Slogwang #define	TRASHIT(x)
164*22ce4affSfengbojiang #define	QMD_IS_TRASHED(x)	0
165*22ce4affSfengbojiang #endif	/* QUEUE_MACRO_DEBUG_TRASH */
166a9643ea8Slogwang 
167a9643ea8Slogwang #ifdef __cplusplus
168a9643ea8Slogwang /*
169a9643ea8Slogwang  * In C++ there can be structure lists and class lists:
170a9643ea8Slogwang  */
171a9643ea8Slogwang #define	QUEUE_TYPEOF(type) type
172a9643ea8Slogwang #else
173a9643ea8Slogwang #define	QUEUE_TYPEOF(type) struct type
174a9643ea8Slogwang #endif
175a9643ea8Slogwang 
176a9643ea8Slogwang /*
177a9643ea8Slogwang  * Singly-linked List declarations.
178a9643ea8Slogwang  */
179a9643ea8Slogwang #define	SLIST_HEAD(name, type)						\
180a9643ea8Slogwang struct name {								\
181a9643ea8Slogwang 	struct type *slh_first;	/* first element */			\
182a9643ea8Slogwang }
183a9643ea8Slogwang 
184a9643ea8Slogwang #define	SLIST_CLASS_HEAD(name, type)					\
185a9643ea8Slogwang struct name {								\
186a9643ea8Slogwang 	class type *slh_first;	/* first element */			\
187a9643ea8Slogwang }
188a9643ea8Slogwang 
189a9643ea8Slogwang #define	SLIST_HEAD_INITIALIZER(head)					\
190a9643ea8Slogwang 	{ NULL }
191a9643ea8Slogwang 
192a9643ea8Slogwang #define	SLIST_ENTRY(type)						\
193a9643ea8Slogwang struct {								\
194a9643ea8Slogwang 	struct type *sle_next;	/* next element */			\
195a9643ea8Slogwang }
196a9643ea8Slogwang 
197a9643ea8Slogwang #define	SLIST_CLASS_ENTRY(type)						\
198a9643ea8Slogwang struct {								\
199a9643ea8Slogwang 	class type *sle_next;		/* next element */		\
200a9643ea8Slogwang }
201a9643ea8Slogwang 
202a9643ea8Slogwang /*
203a9643ea8Slogwang  * Singly-linked List functions.
204a9643ea8Slogwang  */
205*22ce4affSfengbojiang #if (defined(_KERNEL) && defined(INVARIANTS))
206*22ce4affSfengbojiang #define	QMD_SLIST_CHECK_PREVPTR(prevp, elm) do {			\
207*22ce4affSfengbojiang 	if (*(prevp) != (elm))						\
208*22ce4affSfengbojiang 		panic("Bad prevptr *(%p) == %p != %p",			\
209*22ce4affSfengbojiang 		    (prevp), *(prevp), (elm));				\
210*22ce4affSfengbojiang } while (0)
211*22ce4affSfengbojiang #else
212*22ce4affSfengbojiang #define	QMD_SLIST_CHECK_PREVPTR(prevp, elm)
213*22ce4affSfengbojiang #endif
214*22ce4affSfengbojiang 
215*22ce4affSfengbojiang #define SLIST_CONCAT(head1, head2, type, field) do {			\
216*22ce4affSfengbojiang 	QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1);		\
217*22ce4affSfengbojiang 	if (curelm == NULL) {						\
218*22ce4affSfengbojiang 		if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL)	\
219*22ce4affSfengbojiang 			SLIST_INIT(head2);				\
220*22ce4affSfengbojiang 	} else if (SLIST_FIRST(head2) != NULL) {			\
221*22ce4affSfengbojiang 		while (SLIST_NEXT(curelm, field) != NULL)		\
222*22ce4affSfengbojiang 			curelm = SLIST_NEXT(curelm, field);		\
223*22ce4affSfengbojiang 		SLIST_NEXT(curelm, field) = SLIST_FIRST(head2);		\
224*22ce4affSfengbojiang 		SLIST_INIT(head2);					\
225*22ce4affSfengbojiang 	}								\
226*22ce4affSfengbojiang } while (0)
227*22ce4affSfengbojiang 
228a9643ea8Slogwang #define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
229a9643ea8Slogwang 
230a9643ea8Slogwang #define	SLIST_FIRST(head)	((head)->slh_first)
231a9643ea8Slogwang 
232a9643ea8Slogwang #define	SLIST_FOREACH(var, head, field)					\
233a9643ea8Slogwang 	for ((var) = SLIST_FIRST((head));				\
234a9643ea8Slogwang 	    (var);							\
235a9643ea8Slogwang 	    (var) = SLIST_NEXT((var), field))
236a9643ea8Slogwang 
237a9643ea8Slogwang #define	SLIST_FOREACH_FROM(var, head, field)				\
238a9643ea8Slogwang 	for ((var) = ((var) ? (var) : SLIST_FIRST((head)));		\
239a9643ea8Slogwang 	    (var);							\
240a9643ea8Slogwang 	    (var) = SLIST_NEXT((var), field))
241a9643ea8Slogwang 
242a9643ea8Slogwang #define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
243a9643ea8Slogwang 	for ((var) = SLIST_FIRST((head));				\
244a9643ea8Slogwang 	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
245a9643ea8Slogwang 	    (var) = (tvar))
246a9643ea8Slogwang 
247a9643ea8Slogwang #define	SLIST_FOREACH_FROM_SAFE(var, head, field, tvar)			\
248a9643ea8Slogwang 	for ((var) = ((var) ? (var) : SLIST_FIRST((head)));		\
249a9643ea8Slogwang 	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
250a9643ea8Slogwang 	    (var) = (tvar))
251a9643ea8Slogwang 
252a9643ea8Slogwang #define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
253a9643ea8Slogwang 	for ((varp) = &SLIST_FIRST((head));				\
254a9643ea8Slogwang 	    ((var) = *(varp)) != NULL;					\
255a9643ea8Slogwang 	    (varp) = &SLIST_NEXT((var), field))
256a9643ea8Slogwang 
257a9643ea8Slogwang #define	SLIST_INIT(head) do {						\
258a9643ea8Slogwang 	SLIST_FIRST((head)) = NULL;					\
259a9643ea8Slogwang } while (0)
260a9643ea8Slogwang 
261a9643ea8Slogwang #define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
262a9643ea8Slogwang 	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
263a9643ea8Slogwang 	SLIST_NEXT((slistelm), field) = (elm);				\
264a9643ea8Slogwang } while (0)
265a9643ea8Slogwang 
266a9643ea8Slogwang #define	SLIST_INSERT_HEAD(head, elm, field) do {			\
267a9643ea8Slogwang 	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
268a9643ea8Slogwang 	SLIST_FIRST((head)) = (elm);					\
269a9643ea8Slogwang } while (0)
270a9643ea8Slogwang 
271a9643ea8Slogwang #define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
272a9643ea8Slogwang 
273a9643ea8Slogwang #define	SLIST_REMOVE(head, elm, type, field) do {			\
274a9643ea8Slogwang 	QMD_SAVELINK(oldnext, (elm)->field.sle_next);			\
275a9643ea8Slogwang 	if (SLIST_FIRST((head)) == (elm)) {				\
276a9643ea8Slogwang 		SLIST_REMOVE_HEAD((head), field);			\
277a9643ea8Slogwang 	}								\
278a9643ea8Slogwang 	else {								\
279a9643ea8Slogwang 		QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head);		\
280a9643ea8Slogwang 		while (SLIST_NEXT(curelm, field) != (elm))		\
281a9643ea8Slogwang 			curelm = SLIST_NEXT(curelm, field);		\
282a9643ea8Slogwang 		SLIST_REMOVE_AFTER(curelm, field);			\
283a9643ea8Slogwang 	}								\
284a9643ea8Slogwang 	TRASHIT(*oldnext);						\
285a9643ea8Slogwang } while (0)
286a9643ea8Slogwang 
287a9643ea8Slogwang #define SLIST_REMOVE_AFTER(elm, field) do {				\
288a9643ea8Slogwang 	SLIST_NEXT(elm, field) =					\
289a9643ea8Slogwang 	    SLIST_NEXT(SLIST_NEXT(elm, field), field);			\
290a9643ea8Slogwang } while (0)
291a9643ea8Slogwang 
292a9643ea8Slogwang #define	SLIST_REMOVE_HEAD(head, field) do {				\
293a9643ea8Slogwang 	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
294a9643ea8Slogwang } while (0)
295a9643ea8Slogwang 
296*22ce4affSfengbojiang #define	SLIST_REMOVE_PREVPTR(prevp, elm, field) do {			\
297*22ce4affSfengbojiang 	QMD_SLIST_CHECK_PREVPTR(prevp, elm);				\
298*22ce4affSfengbojiang 	*(prevp) = SLIST_NEXT(elm, field);				\
299*22ce4affSfengbojiang 	TRASHIT((elm)->field.sle_next);					\
300*22ce4affSfengbojiang } while (0)
301*22ce4affSfengbojiang 
302a9643ea8Slogwang #define SLIST_SWAP(head1, head2, type) do {				\
303a9643ea8Slogwang 	QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1);		\
304a9643ea8Slogwang 	SLIST_FIRST(head1) = SLIST_FIRST(head2);			\
305a9643ea8Slogwang 	SLIST_FIRST(head2) = swap_first;				\
306a9643ea8Slogwang } while (0)
307a9643ea8Slogwang 
308a9643ea8Slogwang /*
309a9643ea8Slogwang  * Singly-linked Tail queue declarations.
310a9643ea8Slogwang  */
311a9643ea8Slogwang #define	STAILQ_HEAD(name, type)						\
312a9643ea8Slogwang struct name {								\
313a9643ea8Slogwang 	struct type *stqh_first;/* first element */			\
314a9643ea8Slogwang 	struct type **stqh_last;/* addr of last next element */		\
315a9643ea8Slogwang }
316a9643ea8Slogwang 
317a9643ea8Slogwang #define	STAILQ_CLASS_HEAD(name, type)					\
318a9643ea8Slogwang struct name {								\
319a9643ea8Slogwang 	class type *stqh_first;	/* first element */			\
320a9643ea8Slogwang 	class type **stqh_last;	/* addr of last next element */		\
321a9643ea8Slogwang }
322a9643ea8Slogwang 
323a9643ea8Slogwang #define	STAILQ_HEAD_INITIALIZER(head)					\
324a9643ea8Slogwang 	{ NULL, &(head).stqh_first }
325a9643ea8Slogwang 
326a9643ea8Slogwang #define	STAILQ_ENTRY(type)						\
327a9643ea8Slogwang struct {								\
328a9643ea8Slogwang 	struct type *stqe_next;	/* next element */			\
329a9643ea8Slogwang }
330a9643ea8Slogwang 
331a9643ea8Slogwang #define	STAILQ_CLASS_ENTRY(type)					\
332a9643ea8Slogwang struct {								\
333a9643ea8Slogwang 	class type *stqe_next;	/* next element */			\
334a9643ea8Slogwang }
335a9643ea8Slogwang 
336a9643ea8Slogwang /*
337a9643ea8Slogwang  * Singly-linked Tail queue functions.
338a9643ea8Slogwang  */
339a9643ea8Slogwang #define	STAILQ_CONCAT(head1, head2) do {				\
340a9643ea8Slogwang 	if (!STAILQ_EMPTY((head2))) {					\
341a9643ea8Slogwang 		*(head1)->stqh_last = (head2)->stqh_first;		\
342a9643ea8Slogwang 		(head1)->stqh_last = (head2)->stqh_last;		\
343a9643ea8Slogwang 		STAILQ_INIT((head2));					\
344a9643ea8Slogwang 	}								\
345a9643ea8Slogwang } while (0)
346a9643ea8Slogwang 
347a9643ea8Slogwang #define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
348a9643ea8Slogwang 
349a9643ea8Slogwang #define	STAILQ_FIRST(head)	((head)->stqh_first)
350a9643ea8Slogwang 
351a9643ea8Slogwang #define	STAILQ_FOREACH(var, head, field)				\
352a9643ea8Slogwang 	for((var) = STAILQ_FIRST((head));				\
353a9643ea8Slogwang 	   (var);							\
354a9643ea8Slogwang 	   (var) = STAILQ_NEXT((var), field))
355a9643ea8Slogwang 
356a9643ea8Slogwang #define	STAILQ_FOREACH_FROM(var, head, field)				\
357a9643ea8Slogwang 	for ((var) = ((var) ? (var) : STAILQ_FIRST((head)));		\
358a9643ea8Slogwang 	   (var);							\
359a9643ea8Slogwang 	   (var) = STAILQ_NEXT((var), field))
360a9643ea8Slogwang 
361a9643ea8Slogwang #define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
362a9643ea8Slogwang 	for ((var) = STAILQ_FIRST((head));				\
363a9643ea8Slogwang 	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
364a9643ea8Slogwang 	    (var) = (tvar))
365a9643ea8Slogwang 
366a9643ea8Slogwang #define	STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)		\
367a9643ea8Slogwang 	for ((var) = ((var) ? (var) : STAILQ_FIRST((head)));		\
368a9643ea8Slogwang 	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
369a9643ea8Slogwang 	    (var) = (tvar))
370a9643ea8Slogwang 
371a9643ea8Slogwang #define	STAILQ_INIT(head) do {						\
372a9643ea8Slogwang 	STAILQ_FIRST((head)) = NULL;					\
373a9643ea8Slogwang 	(head)->stqh_last = &STAILQ_FIRST((head));			\
374a9643ea8Slogwang } while (0)
375a9643ea8Slogwang 
376a9643ea8Slogwang #define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
377a9643ea8Slogwang 	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
378a9643ea8Slogwang 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
379a9643ea8Slogwang 	STAILQ_NEXT((tqelm), field) = (elm);				\
380a9643ea8Slogwang } while (0)
381a9643ea8Slogwang 
382a9643ea8Slogwang #define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
383a9643ea8Slogwang 	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
384a9643ea8Slogwang 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
385a9643ea8Slogwang 	STAILQ_FIRST((head)) = (elm);					\
386a9643ea8Slogwang } while (0)
387a9643ea8Slogwang 
388a9643ea8Slogwang #define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
389a9643ea8Slogwang 	STAILQ_NEXT((elm), field) = NULL;				\
390a9643ea8Slogwang 	*(head)->stqh_last = (elm);					\
391a9643ea8Slogwang 	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
392a9643ea8Slogwang } while (0)
393a9643ea8Slogwang 
394a9643ea8Slogwang #define	STAILQ_LAST(head, type, field)				\
395a9643ea8Slogwang 	(STAILQ_EMPTY((head)) ? NULL :				\
396a9643ea8Slogwang 	    __containerof((head)->stqh_last,			\
397a9643ea8Slogwang 	    QUEUE_TYPEOF(type), field.stqe_next))
398a9643ea8Slogwang 
399a9643ea8Slogwang #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
400a9643ea8Slogwang 
401a9643ea8Slogwang #define	STAILQ_REMOVE(head, elm, type, field) do {			\
402a9643ea8Slogwang 	QMD_SAVELINK(oldnext, (elm)->field.stqe_next);			\
403a9643ea8Slogwang 	if (STAILQ_FIRST((head)) == (elm)) {				\
404a9643ea8Slogwang 		STAILQ_REMOVE_HEAD((head), field);			\
405a9643ea8Slogwang 	}								\
406a9643ea8Slogwang 	else {								\
407a9643ea8Slogwang 		QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head);	\
408a9643ea8Slogwang 		while (STAILQ_NEXT(curelm, field) != (elm))		\
409a9643ea8Slogwang 			curelm = STAILQ_NEXT(curelm, field);		\
410a9643ea8Slogwang 		STAILQ_REMOVE_AFTER(head, curelm, field);		\
411a9643ea8Slogwang 	}								\
412a9643ea8Slogwang 	TRASHIT(*oldnext);						\
413a9643ea8Slogwang } while (0)
414a9643ea8Slogwang 
415a9643ea8Slogwang #define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
416a9643ea8Slogwang 	if ((STAILQ_NEXT(elm, field) =					\
417a9643ea8Slogwang 	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
418a9643ea8Slogwang 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
419a9643ea8Slogwang } while (0)
420a9643ea8Slogwang 
421a9643ea8Slogwang #define	STAILQ_REMOVE_HEAD(head, field) do {				\
422a9643ea8Slogwang 	if ((STAILQ_FIRST((head)) =					\
423a9643ea8Slogwang 	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
424a9643ea8Slogwang 		(head)->stqh_last = &STAILQ_FIRST((head));		\
425a9643ea8Slogwang } while (0)
426a9643ea8Slogwang 
427a9643ea8Slogwang #define STAILQ_SWAP(head1, head2, type) do {				\
428a9643ea8Slogwang 	QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1);		\
429a9643ea8Slogwang 	QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last;		\
430a9643ea8Slogwang 	STAILQ_FIRST(head1) = STAILQ_FIRST(head2);			\
431a9643ea8Slogwang 	(head1)->stqh_last = (head2)->stqh_last;			\
432a9643ea8Slogwang 	STAILQ_FIRST(head2) = swap_first;				\
433a9643ea8Slogwang 	(head2)->stqh_last = swap_last;					\
434a9643ea8Slogwang 	if (STAILQ_EMPTY(head1))					\
435a9643ea8Slogwang 		(head1)->stqh_last = &STAILQ_FIRST(head1);		\
436a9643ea8Slogwang 	if (STAILQ_EMPTY(head2))					\
437a9643ea8Slogwang 		(head2)->stqh_last = &STAILQ_FIRST(head2);		\
438a9643ea8Slogwang } while (0)
439a9643ea8Slogwang 
440a9643ea8Slogwang /*
441a9643ea8Slogwang  * List declarations.
442a9643ea8Slogwang  */
443a9643ea8Slogwang #define	LIST_HEAD(name, type)						\
444a9643ea8Slogwang struct name {								\
445a9643ea8Slogwang 	struct type *lh_first;	/* first element */			\
446a9643ea8Slogwang }
447a9643ea8Slogwang 
448a9643ea8Slogwang #define	LIST_CLASS_HEAD(name, type)					\
449a9643ea8Slogwang struct name {								\
450a9643ea8Slogwang 	class type *lh_first;	/* first element */			\
451a9643ea8Slogwang }
452a9643ea8Slogwang 
453a9643ea8Slogwang #define	LIST_HEAD_INITIALIZER(head)					\
454a9643ea8Slogwang 	{ NULL }
455a9643ea8Slogwang 
456a9643ea8Slogwang #define	LIST_ENTRY(type)						\
457a9643ea8Slogwang struct {								\
458a9643ea8Slogwang 	struct type *le_next;	/* next element */			\
459a9643ea8Slogwang 	struct type **le_prev;	/* address of previous next element */	\
460a9643ea8Slogwang }
461a9643ea8Slogwang 
462a9643ea8Slogwang #define	LIST_CLASS_ENTRY(type)						\
463a9643ea8Slogwang struct {								\
464a9643ea8Slogwang 	class type *le_next;	/* next element */			\
465a9643ea8Slogwang 	class type **le_prev;	/* address of previous next element */	\
466a9643ea8Slogwang }
467a9643ea8Slogwang 
468a9643ea8Slogwang /*
469a9643ea8Slogwang  * List functions.
470a9643ea8Slogwang  */
471a9643ea8Slogwang 
472a9643ea8Slogwang #if (defined(_KERNEL) && defined(INVARIANTS))
473*22ce4affSfengbojiang /*
474*22ce4affSfengbojiang  * QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME)
475*22ce4affSfengbojiang  *
476*22ce4affSfengbojiang  * If the list is non-empty, validates that the first element of the list
477*22ce4affSfengbojiang  * points back at 'head.'
478*22ce4affSfengbojiang  */
479a9643ea8Slogwang #define	QMD_LIST_CHECK_HEAD(head, field) do {				\
480a9643ea8Slogwang 	if (LIST_FIRST((head)) != NULL &&				\
481a9643ea8Slogwang 	    LIST_FIRST((head))->field.le_prev !=			\
482a9643ea8Slogwang 	     &LIST_FIRST((head)))					\
483a9643ea8Slogwang 		panic("Bad list head %p first->prev != head", (head));	\
484a9643ea8Slogwang } while (0)
485a9643ea8Slogwang 
486*22ce4affSfengbojiang /*
487*22ce4affSfengbojiang  * QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME)
488*22ce4affSfengbojiang  *
489*22ce4affSfengbojiang  * If an element follows 'elm' in the list, validates that the next element
490*22ce4affSfengbojiang  * points back at 'elm.'
491*22ce4affSfengbojiang  */
492a9643ea8Slogwang #define	QMD_LIST_CHECK_NEXT(elm, field) do {				\
493a9643ea8Slogwang 	if (LIST_NEXT((elm), field) != NULL &&				\
494a9643ea8Slogwang 	    LIST_NEXT((elm), field)->field.le_prev !=			\
495a9643ea8Slogwang 	     &((elm)->field.le_next))					\
496a9643ea8Slogwang 	     	panic("Bad link elm %p next->prev != elm", (elm));	\
497a9643ea8Slogwang } while (0)
498a9643ea8Slogwang 
499*22ce4affSfengbojiang /*
500*22ce4affSfengbojiang  * QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME)
501*22ce4affSfengbojiang  *
502*22ce4affSfengbojiang  * Validates that the previous element (or head of the list) points to 'elm.'
503*22ce4affSfengbojiang  */
504a9643ea8Slogwang #define	QMD_LIST_CHECK_PREV(elm, field) do {				\
505a9643ea8Slogwang 	if (*(elm)->field.le_prev != (elm))				\
506a9643ea8Slogwang 		panic("Bad link elm %p prev->next != elm", (elm));	\
507a9643ea8Slogwang } while (0)
508a9643ea8Slogwang #else
509a9643ea8Slogwang #define	QMD_LIST_CHECK_HEAD(head, field)
510a9643ea8Slogwang #define	QMD_LIST_CHECK_NEXT(elm, field)
511a9643ea8Slogwang #define	QMD_LIST_CHECK_PREV(elm, field)
512a9643ea8Slogwang #endif /* (_KERNEL && INVARIANTS) */
513a9643ea8Slogwang 
514*22ce4affSfengbojiang #define LIST_CONCAT(head1, head2, type, field) do {			      \
515*22ce4affSfengbojiang 	QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1);			      \
516*22ce4affSfengbojiang 	if (curelm == NULL) {						      \
517*22ce4affSfengbojiang 		if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) {	      \
518*22ce4affSfengbojiang 			LIST_FIRST(head2)->field.le_prev =		      \
519*22ce4affSfengbojiang 			    &LIST_FIRST((head1));			      \
520*22ce4affSfengbojiang 			LIST_INIT(head2);				      \
521*22ce4affSfengbojiang 		}							      \
522*22ce4affSfengbojiang 	} else if (LIST_FIRST(head2) != NULL) {				      \
523*22ce4affSfengbojiang 		while (LIST_NEXT(curelm, field) != NULL)		      \
524*22ce4affSfengbojiang 			curelm = LIST_NEXT(curelm, field);		      \
525*22ce4affSfengbojiang 		LIST_NEXT(curelm, field) = LIST_FIRST(head2);		      \
526*22ce4affSfengbojiang 		LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \
527*22ce4affSfengbojiang 		LIST_INIT(head2);					      \
528*22ce4affSfengbojiang 	}								      \
529*22ce4affSfengbojiang } while (0)
530*22ce4affSfengbojiang 
531a9643ea8Slogwang #define	LIST_EMPTY(head)	((head)->lh_first == NULL)
532a9643ea8Slogwang 
533a9643ea8Slogwang #define	LIST_FIRST(head)	((head)->lh_first)
534a9643ea8Slogwang 
535a9643ea8Slogwang #define	LIST_FOREACH(var, head, field)					\
536a9643ea8Slogwang 	for ((var) = LIST_FIRST((head));				\
537a9643ea8Slogwang 	    (var);							\
538a9643ea8Slogwang 	    (var) = LIST_NEXT((var), field))
539a9643ea8Slogwang 
540a9643ea8Slogwang #define	LIST_FOREACH_FROM(var, head, field)				\
541a9643ea8Slogwang 	for ((var) = ((var) ? (var) : LIST_FIRST((head)));		\
542a9643ea8Slogwang 	    (var);							\
543a9643ea8Slogwang 	    (var) = LIST_NEXT((var), field))
544a9643ea8Slogwang 
545a9643ea8Slogwang #define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
546a9643ea8Slogwang 	for ((var) = LIST_FIRST((head));				\
547a9643ea8Slogwang 	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
548a9643ea8Slogwang 	    (var) = (tvar))
549a9643ea8Slogwang 
550a9643ea8Slogwang #define	LIST_FOREACH_FROM_SAFE(var, head, field, tvar)			\
551a9643ea8Slogwang 	for ((var) = ((var) ? (var) : LIST_FIRST((head)));		\
552a9643ea8Slogwang 	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
553a9643ea8Slogwang 	    (var) = (tvar))
554a9643ea8Slogwang 
555a9643ea8Slogwang #define	LIST_INIT(head) do {						\
556a9643ea8Slogwang 	LIST_FIRST((head)) = NULL;					\
557a9643ea8Slogwang } while (0)
558a9643ea8Slogwang 
559a9643ea8Slogwang #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
560a9643ea8Slogwang 	QMD_LIST_CHECK_NEXT(listelm, field);				\
561a9643ea8Slogwang 	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
562a9643ea8Slogwang 		LIST_NEXT((listelm), field)->field.le_prev =		\
563a9643ea8Slogwang 		    &LIST_NEXT((elm), field);				\
564a9643ea8Slogwang 	LIST_NEXT((listelm), field) = (elm);				\
565a9643ea8Slogwang 	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
566a9643ea8Slogwang } while (0)
567a9643ea8Slogwang 
568a9643ea8Slogwang #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
569a9643ea8Slogwang 	QMD_LIST_CHECK_PREV(listelm, field);				\
570a9643ea8Slogwang 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
571a9643ea8Slogwang 	LIST_NEXT((elm), field) = (listelm);				\
572a9643ea8Slogwang 	*(listelm)->field.le_prev = (elm);				\
573a9643ea8Slogwang 	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
574a9643ea8Slogwang } while (0)
575a9643ea8Slogwang 
576a9643ea8Slogwang #define	LIST_INSERT_HEAD(head, elm, field) do {				\
577a9643ea8Slogwang 	QMD_LIST_CHECK_HEAD((head), field);				\
578a9643ea8Slogwang 	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
579a9643ea8Slogwang 		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
580a9643ea8Slogwang 	LIST_FIRST((head)) = (elm);					\
581a9643ea8Slogwang 	(elm)->field.le_prev = &LIST_FIRST((head));			\
582a9643ea8Slogwang } while (0)
583a9643ea8Slogwang 
584a9643ea8Slogwang #define	LIST_NEXT(elm, field)	((elm)->field.le_next)
585a9643ea8Slogwang 
586a9643ea8Slogwang #define	LIST_PREV(elm, head, type, field)			\
587a9643ea8Slogwang 	((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL :	\
588a9643ea8Slogwang 	    __containerof((elm)->field.le_prev,			\
589a9643ea8Slogwang 	    QUEUE_TYPEOF(type), field.le_next))
590a9643ea8Slogwang 
591a9643ea8Slogwang #define	LIST_REMOVE(elm, field) do {					\
592a9643ea8Slogwang 	QMD_SAVELINK(oldnext, (elm)->field.le_next);			\
593a9643ea8Slogwang 	QMD_SAVELINK(oldprev, (elm)->field.le_prev);			\
594a9643ea8Slogwang 	QMD_LIST_CHECK_NEXT(elm, field);				\
595a9643ea8Slogwang 	QMD_LIST_CHECK_PREV(elm, field);				\
596a9643ea8Slogwang 	if (LIST_NEXT((elm), field) != NULL)				\
597a9643ea8Slogwang 		LIST_NEXT((elm), field)->field.le_prev = 		\
598a9643ea8Slogwang 		    (elm)->field.le_prev;				\
599a9643ea8Slogwang 	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
600a9643ea8Slogwang 	TRASHIT(*oldnext);						\
601a9643ea8Slogwang 	TRASHIT(*oldprev);						\
602a9643ea8Slogwang } while (0)
603a9643ea8Slogwang 
604a9643ea8Slogwang #define LIST_SWAP(head1, head2, type, field) do {			\
605a9643ea8Slogwang 	QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1);		\
606a9643ea8Slogwang 	LIST_FIRST((head1)) = LIST_FIRST((head2));			\
607a9643ea8Slogwang 	LIST_FIRST((head2)) = swap_tmp;					\
608a9643ea8Slogwang 	if ((swap_tmp = LIST_FIRST((head1))) != NULL)			\
609a9643ea8Slogwang 		swap_tmp->field.le_prev = &LIST_FIRST((head1));		\
610a9643ea8Slogwang 	if ((swap_tmp = LIST_FIRST((head2))) != NULL)			\
611a9643ea8Slogwang 		swap_tmp->field.le_prev = &LIST_FIRST((head2));		\
612a9643ea8Slogwang } while (0)
613a9643ea8Slogwang 
614a9643ea8Slogwang /*
615a9643ea8Slogwang  * Tail queue declarations.
616a9643ea8Slogwang  */
617a9643ea8Slogwang #define	TAILQ_HEAD(name, type)						\
618a9643ea8Slogwang struct name {								\
619a9643ea8Slogwang 	struct type *tqh_first;	/* first element */			\
620a9643ea8Slogwang 	struct type **tqh_last;	/* addr of last next element */		\
621a9643ea8Slogwang 	TRACEBUF							\
622a9643ea8Slogwang }
623a9643ea8Slogwang 
624a9643ea8Slogwang #define	TAILQ_CLASS_HEAD(name, type)					\
625a9643ea8Slogwang struct name {								\
626a9643ea8Slogwang 	class type *tqh_first;	/* first element */			\
627a9643ea8Slogwang 	class type **tqh_last;	/* addr of last next element */		\
628a9643ea8Slogwang 	TRACEBUF							\
629a9643ea8Slogwang }
630a9643ea8Slogwang 
631a9643ea8Slogwang #define	TAILQ_HEAD_INITIALIZER(head)					\
632a9643ea8Slogwang 	{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
633a9643ea8Slogwang 
634a9643ea8Slogwang #define	TAILQ_ENTRY(type)						\
635a9643ea8Slogwang struct {								\
636a9643ea8Slogwang 	struct type *tqe_next;	/* next element */			\
637a9643ea8Slogwang 	struct type **tqe_prev;	/* address of previous next element */	\
638a9643ea8Slogwang 	TRACEBUF							\
639a9643ea8Slogwang }
640a9643ea8Slogwang 
641a9643ea8Slogwang #define	TAILQ_CLASS_ENTRY(type)						\
642a9643ea8Slogwang struct {								\
643a9643ea8Slogwang 	class type *tqe_next;	/* next element */			\
644a9643ea8Slogwang 	class type **tqe_prev;	/* address of previous next element */	\
645a9643ea8Slogwang 	TRACEBUF							\
646a9643ea8Slogwang }
647a9643ea8Slogwang 
648a9643ea8Slogwang /*
649a9643ea8Slogwang  * Tail queue functions.
650a9643ea8Slogwang  */
651a9643ea8Slogwang #if (defined(_KERNEL) && defined(INVARIANTS))
652*22ce4affSfengbojiang /*
653*22ce4affSfengbojiang  * QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
654*22ce4affSfengbojiang  *
655*22ce4affSfengbojiang  * If the tailq is non-empty, validates that the first element of the tailq
656*22ce4affSfengbojiang  * points back at 'head.'
657*22ce4affSfengbojiang  */
658a9643ea8Slogwang #define	QMD_TAILQ_CHECK_HEAD(head, field) do {				\
659a9643ea8Slogwang 	if (!TAILQ_EMPTY(head) &&					\
660a9643ea8Slogwang 	    TAILQ_FIRST((head))->field.tqe_prev !=			\
661a9643ea8Slogwang 	     &TAILQ_FIRST((head)))					\
662a9643ea8Slogwang 		panic("Bad tailq head %p first->prev != head", (head));	\
663a9643ea8Slogwang } while (0)
664a9643ea8Slogwang 
665*22ce4affSfengbojiang /*
666*22ce4affSfengbojiang  * QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
667*22ce4affSfengbojiang  *
668*22ce4affSfengbojiang  * Validates that the tail of the tailq is a pointer to pointer to NULL.
669*22ce4affSfengbojiang  */
670a9643ea8Slogwang #define	QMD_TAILQ_CHECK_TAIL(head, field) do {				\
671a9643ea8Slogwang 	if (*(head)->tqh_last != NULL)					\
672a9643ea8Slogwang 	    	panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); 	\
673a9643ea8Slogwang } while (0)
674a9643ea8Slogwang 
675*22ce4affSfengbojiang /*
676*22ce4affSfengbojiang  * QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME)
677*22ce4affSfengbojiang  *
678*22ce4affSfengbojiang  * If an element follows 'elm' in the tailq, validates that the next element
679*22ce4affSfengbojiang  * points back at 'elm.'
680*22ce4affSfengbojiang  */
681a9643ea8Slogwang #define	QMD_TAILQ_CHECK_NEXT(elm, field) do {				\
682a9643ea8Slogwang 	if (TAILQ_NEXT((elm), field) != NULL &&				\
683a9643ea8Slogwang 	    TAILQ_NEXT((elm), field)->field.tqe_prev !=			\
684a9643ea8Slogwang 	     &((elm)->field.tqe_next))					\
685a9643ea8Slogwang 		panic("Bad link elm %p next->prev != elm", (elm));	\
686a9643ea8Slogwang } while (0)
687a9643ea8Slogwang 
688*22ce4affSfengbojiang /*
689*22ce4affSfengbojiang  * QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME)
690*22ce4affSfengbojiang  *
691*22ce4affSfengbojiang  * Validates that the previous element (or head of the tailq) points to 'elm.'
692*22ce4affSfengbojiang  */
693a9643ea8Slogwang #define	QMD_TAILQ_CHECK_PREV(elm, field) do {				\
694a9643ea8Slogwang 	if (*(elm)->field.tqe_prev != (elm))				\
695a9643ea8Slogwang 		panic("Bad link elm %p prev->next != elm", (elm));	\
696a9643ea8Slogwang } while (0)
697a9643ea8Slogwang #else
698a9643ea8Slogwang #define	QMD_TAILQ_CHECK_HEAD(head, field)
699a9643ea8Slogwang #define	QMD_TAILQ_CHECK_TAIL(head, headname)
700a9643ea8Slogwang #define	QMD_TAILQ_CHECK_NEXT(elm, field)
701a9643ea8Slogwang #define	QMD_TAILQ_CHECK_PREV(elm, field)
702a9643ea8Slogwang #endif /* (_KERNEL && INVARIANTS) */
703a9643ea8Slogwang 
704a9643ea8Slogwang #define	TAILQ_CONCAT(head1, head2, field) do {				\
705a9643ea8Slogwang 	if (!TAILQ_EMPTY(head2)) {					\
706a9643ea8Slogwang 		*(head1)->tqh_last = (head2)->tqh_first;		\
707a9643ea8Slogwang 		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
708a9643ea8Slogwang 		(head1)->tqh_last = (head2)->tqh_last;			\
709a9643ea8Slogwang 		TAILQ_INIT((head2));					\
710a9643ea8Slogwang 		QMD_TRACE_HEAD(head1);					\
711a9643ea8Slogwang 		QMD_TRACE_HEAD(head2);					\
712a9643ea8Slogwang 	}								\
713a9643ea8Slogwang } while (0)
714a9643ea8Slogwang 
715a9643ea8Slogwang #define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
716a9643ea8Slogwang 
717a9643ea8Slogwang #define	TAILQ_FIRST(head)	((head)->tqh_first)
718a9643ea8Slogwang 
719a9643ea8Slogwang #define	TAILQ_FOREACH(var, head, field)					\
720a9643ea8Slogwang 	for ((var) = TAILQ_FIRST((head));				\
721a9643ea8Slogwang 	    (var);							\
722a9643ea8Slogwang 	    (var) = TAILQ_NEXT((var), field))
723a9643ea8Slogwang 
724a9643ea8Slogwang #define	TAILQ_FOREACH_FROM(var, head, field)				\
725a9643ea8Slogwang 	for ((var) = ((var) ? (var) : TAILQ_FIRST((head)));		\
726a9643ea8Slogwang 	    (var);							\
727a9643ea8Slogwang 	    (var) = TAILQ_NEXT((var), field))
728a9643ea8Slogwang 
729a9643ea8Slogwang #define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
730a9643ea8Slogwang 	for ((var) = TAILQ_FIRST((head));				\
731a9643ea8Slogwang 	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
732a9643ea8Slogwang 	    (var) = (tvar))
733a9643ea8Slogwang 
734a9643ea8Slogwang #define	TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)			\
735a9643ea8Slogwang 	for ((var) = ((var) ? (var) : TAILQ_FIRST((head)));		\
736a9643ea8Slogwang 	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
737a9643ea8Slogwang 	    (var) = (tvar))
738a9643ea8Slogwang 
739a9643ea8Slogwang #define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
740a9643ea8Slogwang 	for ((var) = TAILQ_LAST((head), headname);			\
741a9643ea8Slogwang 	    (var);							\
742a9643ea8Slogwang 	    (var) = TAILQ_PREV((var), headname, field))
743a9643ea8Slogwang 
744a9643ea8Slogwang #define	TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field)		\
745a9643ea8Slogwang 	for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname));	\
746a9643ea8Slogwang 	    (var);							\
747a9643ea8Slogwang 	    (var) = TAILQ_PREV((var), headname, field))
748a9643ea8Slogwang 
749a9643ea8Slogwang #define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
750a9643ea8Slogwang 	for ((var) = TAILQ_LAST((head), headname);			\
751a9643ea8Slogwang 	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
752a9643ea8Slogwang 	    (var) = (tvar))
753a9643ea8Slogwang 
754a9643ea8Slogwang #define	TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
755a9643ea8Slogwang 	for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname));	\
756a9643ea8Slogwang 	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
757a9643ea8Slogwang 	    (var) = (tvar))
758a9643ea8Slogwang 
759a9643ea8Slogwang #define	TAILQ_INIT(head) do {						\
760a9643ea8Slogwang 	TAILQ_FIRST((head)) = NULL;					\
761a9643ea8Slogwang 	(head)->tqh_last = &TAILQ_FIRST((head));			\
762a9643ea8Slogwang 	QMD_TRACE_HEAD(head);						\
763a9643ea8Slogwang } while (0)
764a9643ea8Slogwang 
765a9643ea8Slogwang #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
766a9643ea8Slogwang 	QMD_TAILQ_CHECK_NEXT(listelm, field);				\
767a9643ea8Slogwang 	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
768a9643ea8Slogwang 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
769a9643ea8Slogwang 		    &TAILQ_NEXT((elm), field);				\
770a9643ea8Slogwang 	else {								\
771a9643ea8Slogwang 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
772a9643ea8Slogwang 		QMD_TRACE_HEAD(head);					\
773a9643ea8Slogwang 	}								\
774a9643ea8Slogwang 	TAILQ_NEXT((listelm), field) = (elm);				\
775a9643ea8Slogwang 	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
776a9643ea8Slogwang 	QMD_TRACE_ELEM(&(elm)->field);					\
777a9643ea8Slogwang 	QMD_TRACE_ELEM(&(listelm)->field);				\
778a9643ea8Slogwang } while (0)
779a9643ea8Slogwang 
780a9643ea8Slogwang #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
781a9643ea8Slogwang 	QMD_TAILQ_CHECK_PREV(listelm, field);				\
782a9643ea8Slogwang 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
783a9643ea8Slogwang 	TAILQ_NEXT((elm), field) = (listelm);				\
784a9643ea8Slogwang 	*(listelm)->field.tqe_prev = (elm);				\
785a9643ea8Slogwang 	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
786a9643ea8Slogwang 	QMD_TRACE_ELEM(&(elm)->field);					\
787a9643ea8Slogwang 	QMD_TRACE_ELEM(&(listelm)->field);				\
788a9643ea8Slogwang } while (0)
789a9643ea8Slogwang 
790a9643ea8Slogwang #define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
791a9643ea8Slogwang 	QMD_TAILQ_CHECK_HEAD(head, field);				\
792a9643ea8Slogwang 	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
793a9643ea8Slogwang 		TAILQ_FIRST((head))->field.tqe_prev =			\
794a9643ea8Slogwang 		    &TAILQ_NEXT((elm), field);				\
795a9643ea8Slogwang 	else								\
796a9643ea8Slogwang 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
797a9643ea8Slogwang 	TAILQ_FIRST((head)) = (elm);					\
798a9643ea8Slogwang 	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
799a9643ea8Slogwang 	QMD_TRACE_HEAD(head);						\
800a9643ea8Slogwang 	QMD_TRACE_ELEM(&(elm)->field);					\
801a9643ea8Slogwang } while (0)
802a9643ea8Slogwang 
803a9643ea8Slogwang #define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
804a9643ea8Slogwang 	QMD_TAILQ_CHECK_TAIL(head, field);				\
805a9643ea8Slogwang 	TAILQ_NEXT((elm), field) = NULL;				\
806a9643ea8Slogwang 	(elm)->field.tqe_prev = (head)->tqh_last;			\
807a9643ea8Slogwang 	*(head)->tqh_last = (elm);					\
808a9643ea8Slogwang 	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
809a9643ea8Slogwang 	QMD_TRACE_HEAD(head);						\
810a9643ea8Slogwang 	QMD_TRACE_ELEM(&(elm)->field);					\
811a9643ea8Slogwang } while (0)
812a9643ea8Slogwang 
813a9643ea8Slogwang #define	TAILQ_LAST(head, headname)					\
814a9643ea8Slogwang 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
815a9643ea8Slogwang 
816*22ce4affSfengbojiang /*
817*22ce4affSfengbojiang  * The FAST function is fast in that it causes no data access other
818*22ce4affSfengbojiang  * then the access to the head. The standard LAST function above
819*22ce4affSfengbojiang  * will cause a data access of both the element you want and
820*22ce4affSfengbojiang  * the previous element. FAST is very useful for instances when
821*22ce4affSfengbojiang  * you may want to prefetch the last data element.
822*22ce4affSfengbojiang  */
823*22ce4affSfengbojiang #define	TAILQ_LAST_FAST(head, type, field)			\
824*22ce4affSfengbojiang     (TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next))
825*22ce4affSfengbojiang 
826a9643ea8Slogwang #define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
827a9643ea8Slogwang 
828a9643ea8Slogwang #define	TAILQ_PREV(elm, headname, field)				\
829a9643ea8Slogwang 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
830a9643ea8Slogwang 
831*22ce4affSfengbojiang #define	TAILQ_PREV_FAST(elm, head, type, field)				\
832*22ce4affSfengbojiang     ((elm)->field.tqe_prev == &(head)->tqh_first ? NULL :		\
833*22ce4affSfengbojiang      __containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next))
834*22ce4affSfengbojiang 
835a9643ea8Slogwang #define	TAILQ_REMOVE(head, elm, field) do {				\
836a9643ea8Slogwang 	QMD_SAVELINK(oldnext, (elm)->field.tqe_next);			\
837a9643ea8Slogwang 	QMD_SAVELINK(oldprev, (elm)->field.tqe_prev);			\
838a9643ea8Slogwang 	QMD_TAILQ_CHECK_NEXT(elm, field);				\
839a9643ea8Slogwang 	QMD_TAILQ_CHECK_PREV(elm, field);				\
840a9643ea8Slogwang 	if ((TAILQ_NEXT((elm), field)) != NULL)				\
841a9643ea8Slogwang 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
842a9643ea8Slogwang 		    (elm)->field.tqe_prev;				\
843a9643ea8Slogwang 	else {								\
844a9643ea8Slogwang 		(head)->tqh_last = (elm)->field.tqe_prev;		\
845a9643ea8Slogwang 		QMD_TRACE_HEAD(head);					\
846a9643ea8Slogwang 	}								\
847a9643ea8Slogwang 	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
848a9643ea8Slogwang 	TRASHIT(*oldnext);						\
849a9643ea8Slogwang 	TRASHIT(*oldprev);						\
850a9643ea8Slogwang 	QMD_TRACE_ELEM(&(elm)->field);					\
851a9643ea8Slogwang } while (0)
852a9643ea8Slogwang 
853a9643ea8Slogwang #define TAILQ_SWAP(head1, head2, type, field) do {			\
854a9643ea8Slogwang 	QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first;		\
855a9643ea8Slogwang 	QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last;		\
856a9643ea8Slogwang 	(head1)->tqh_first = (head2)->tqh_first;			\
857a9643ea8Slogwang 	(head1)->tqh_last = (head2)->tqh_last;				\
858a9643ea8Slogwang 	(head2)->tqh_first = swap_first;				\
859a9643ea8Slogwang 	(head2)->tqh_last = swap_last;					\
860a9643ea8Slogwang 	if ((swap_first = (head1)->tqh_first) != NULL)			\
861a9643ea8Slogwang 		swap_first->field.tqe_prev = &(head1)->tqh_first;	\
862a9643ea8Slogwang 	else								\
863a9643ea8Slogwang 		(head1)->tqh_last = &(head1)->tqh_first;		\
864a9643ea8Slogwang 	if ((swap_first = (head2)->tqh_first) != NULL)			\
865a9643ea8Slogwang 		swap_first->field.tqe_prev = &(head2)->tqh_first;	\
866a9643ea8Slogwang 	else								\
867a9643ea8Slogwang 		(head2)->tqh_last = &(head2)->tqh_first;		\
868a9643ea8Slogwang } while (0)
869a9643ea8Slogwang 
870a9643ea8Slogwang #endif /* !_SYS_QUEUE_H_ */
871