PageRenderTime 27ms CodeModel.GetById 12ms app.highlight 10ms RepoModel.GetById 1ms app.codeStats 0ms

/filesystems/unixfs/common/darwin/queue.h

http://macfuse.googlecode.com/
C++ Header | 716 lines | 444 code | 102 blank | 170 comment | 117 complexity | 6813e680d10c0ddf323e15d5fecd04b2 MD5 | raw file
  1/*
  2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
  3 *
  4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  5 * 
  6 * This file contains Original Code and/or Modifications of Original Code
  7 * as defined in and that are subject to the Apple Public Source License
  8 * Version 2.0 (the 'License'). You may not use this file except in
  9 * compliance with the License. The rights granted to you under the License
 10 * may not be used to create, or enable the creation or redistribution of,
 11 * unlawful or unlicensed copies of an Apple operating system, or to
 12 * circumvent, violate, or enable the circumvention or violation of, any
 13 * terms of an Apple operating system software license agreement.
 14 * 
 15 * Please obtain a copy of the License at
 16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
 17 * 
 18 * The Original Code and all software distributed under the License are
 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 23 * Please see the License for the specific language governing rights and
 24 * limitations under the License.
 25 * 
 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
 27 */
 28/*-
 29 * Copyright (c) 1991, 1993
 30 *	The Regents of the University of California.  All rights reserved.
 31 *
 32 * Redistribution and use in source and binary forms, with or without
 33 * modification, are permitted provided that the following conditions
 34 * are met:
 35 * 1. Redistributions of source code must retain the above copyright
 36 *    notice, this list of conditions and the following disclaimer.
 37 * 2. Redistributions in binary form must reproduce the above copyright
 38 *    notice, this list of conditions and the following disclaimer in the
 39 *    documentation and/or other materials provided with the distribution.
 40 * 4. Neither the name of the University nor the names of its contributors
 41 *    may be used to endorse or promote products derived from this software
 42 *    without specific prior written permission.
 43 *
 44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 47 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 54 * SUCH DAMAGE.
 55 *
 56 *	@(#)queue.h	8.5 (Berkeley) 8/20/94
 57 */
 58
 59#ifndef _SYS_QUEUE_H_
 60#define	_SYS_QUEUE_H_
 61
 62/*
 63 * This file defines five types of data structures: singly-linked lists,
 64 * singly-linked tail queues, lists, tail queues, and circular queues.
 65 *
 66 * A singly-linked list is headed by a single forward pointer. The elements
 67 * are singly linked for minimum space and pointer manipulation overhead at
 68 * the expense of O(n) removal for arbitrary elements. New elements can be
 69 * added to the list after an existing element or at the head of the list.
 70 * Elements being removed from the head of the list should use the explicit
 71 * macro for this purpose for optimum efficiency. A singly-linked list may
 72 * only be traversed in the forward direction.  Singly-linked lists are ideal
 73 * for applications with large datasets and few or no removals or for
 74 * implementing a LIFO queue.
 75 *
 76 * A singly-linked tail queue is headed by a pair of pointers, one to the
 77 * head of the list and the other to the tail of the list. The elements are
 78 * singly linked for minimum space and pointer manipulation overhead at the
 79 * expense of O(n) removal for arbitrary elements. New elements can be added
 80 * to the list after an existing element, at the head of the list, or at the
 81 * end of the list. Elements being removed from the head of the tail queue
 82 * should use the explicit macro for this purpose for optimum efficiency.
 83 * A singly-linked tail queue may only be traversed in the forward direction.
 84 * Singly-linked tail queues are ideal for applications with large datasets
 85 * and few or no removals or for implementing a FIFO queue.
 86 *
 87 * A list is headed by a single forward pointer (or an array of forward
 88 * pointers for a hash table header). The elements are doubly linked
 89 * so that an arbitrary element can be removed without a need to
 90 * traverse the list. New elements can be added to the list before
 91 * or after an existing element or at the head of the list. A list
 92 * may only be traversed in the forward direction.
 93 *
 94 * A tail queue is headed by a pair of pointers, one to the head of the
 95 * list and the other to the tail of the list. The elements are doubly
 96 * linked so that an arbitrary element can be removed without a need to
 97 * traverse the list. New elements can be added to the list before or
 98 * after an existing element, at the head of the list, or at the end of
 99 * the list. A tail queue may be traversed in either direction.
100 *
101 * A circle queue is headed by a pair of pointers, one to the head of the
102 * list and the other to the tail of the list. The elements are doubly
103 * linked so that an arbitrary element can be removed without a need to
104 * traverse the list. New elements can be added to the list before or after
105 * an existing element, at the head of the list, or at the end of the list.
106 * A circle queue may be traversed in either direction, but has a more
107 * complex end of list detection.
108 * Note that circle queues are deprecated, because, as the removal log
109 * in FreeBSD states, "CIRCLEQs are a disgrace to everything Knuth taught
110 * us in Volume 1 Chapter 2. [...] Use TAILQ instead, it provides the same
111 * functionality." Code using them will continue to compile, but they
112 * are no longer documented on the man page.
113 *
114 * For details on the use of these macros, see the queue(3) manual page.
115 *
116 *
117 *				SLIST	LIST	STAILQ	TAILQ	CIRCLEQ
118 * _HEAD			+	+	+	+	+
119 * _HEAD_INITIALIZER		+	+	+	+	-
120 * _ENTRY			+	+	+	+	+
121 * _INIT			+	+	+	+	+
122 * _EMPTY			+	+	+	+	+
123 * _FIRST			+	+	+	+	+
124 * _NEXT			+	+	+	+	+
125 * _PREV			-	-	-	+	+
126 * _LAST			-	-	+	+	+
127 * _FOREACH			+	+	+	+	+
128 * _FOREACH_SAFE		+	+	+	+	-
129 * _FOREACH_REVERSE		-	-	-	+	-
130 * _FOREACH_REVERSE_SAFE	-	-	-	+	-
131 * _INSERT_HEAD			+	+	+	+	+
132 * _INSERT_BEFORE		-	+	-	+	+
133 * _INSERT_AFTER		+	+	+	+	+
134 * _INSERT_TAIL			-	-	+	+	+
135 * _CONCAT			-	-	+	+	-
136 * _REMOVE_HEAD			+	-	+	-	-
137 * _REMOVE			+	+	+	+	+
138 *
139 */
140#ifdef QUEUE_MACRO_DEBUG
141/* Store the last 2 places the queue element or head was altered */
142struct qm_trace {
143	char * lastfile;
144	int lastline;
145	char * prevfile;
146	int prevline;
147};
148
149#define	TRACEBUF	struct qm_trace trace;
150#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
151
152#define	QMD_TRACE_HEAD(head) do {					\
153	(head)->trace.prevline = (head)->trace.lastline;		\
154	(head)->trace.prevfile = (head)->trace.lastfile;		\
155	(head)->trace.lastline = __LINE__;				\
156	(head)->trace.lastfile = __FILE__;				\
157} while (0)
158
159#define	QMD_TRACE_ELEM(elem) do {					\
160	(elem)->trace.prevline = (elem)->trace.lastline;		\
161	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
162	(elem)->trace.lastline = __LINE__;				\
163	(elem)->trace.lastfile = __FILE__;				\
164} while (0)
165
166#else
167#define	QMD_TRACE_ELEM(elem)
168#define	QMD_TRACE_HEAD(head)
169#define	TRACEBUF
170#define	TRASHIT(x)
171#endif	/* QUEUE_MACRO_DEBUG */
172
173/*
174 * Singly-linked List declarations.
175 */
176#define	SLIST_HEAD(name, type)						\
177struct name {								\
178	struct type *slh_first;	/* first element */			\
179}
180
181#define	SLIST_HEAD_INITIALIZER(head)					\
182	{ NULL }
183
184#define	SLIST_ENTRY(type)						\
185struct {								\
186	struct type *sle_next;	/* next element */			\
187}
188
189/*
190 * Singly-linked List functions.
191 */
192#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
193
194#define	SLIST_FIRST(head)	((head)->slh_first)
195
196#define	SLIST_FOREACH(var, head, field)					\
197	for ((var) = SLIST_FIRST((head));				\
198	    (var);							\
199	    (var) = SLIST_NEXT((var), field))
200
201#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
202	for ((var) = SLIST_FIRST((head));				\
203	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
204	    (var) = (tvar))
205
206#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
207	for ((varp) = &SLIST_FIRST((head));				\
208	    ((var) = *(varp)) != NULL;					\
209	    (varp) = &SLIST_NEXT((var), field))
210
211#define	SLIST_INIT(head) do {						\
212	SLIST_FIRST((head)) = NULL;					\
213} while (0)
214
215#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
216	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
217	SLIST_NEXT((slistelm), field) = (elm);				\
218} while (0)
219
220#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
221	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
222	SLIST_FIRST((head)) = (elm);					\
223} while (0)
224
225#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
226
227#define	SLIST_REMOVE(head, elm, type, field) do {			\
228	if (SLIST_FIRST((head)) == (elm)) {				\
229		SLIST_REMOVE_HEAD((head), field);			\
230	}								\
231	else {								\
232		struct type *curelm = SLIST_FIRST((head));		\
233		while (SLIST_NEXT(curelm, field) != (elm))		\
234			curelm = SLIST_NEXT(curelm, field);		\
235		SLIST_NEXT(curelm, field) =				\
236		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
237	}								\
238	TRASHIT((elm)->field.sle_next);					\
239} while (0)
240
241#define	SLIST_REMOVE_HEAD(head, field) do {				\
242	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
243} while (0)
244
245/*
246 * Singly-linked Tail queue declarations.
247 */
248#define	STAILQ_HEAD(name, type)						\
249struct name {								\
250	struct type *stqh_first;/* first element */			\
251	struct type **stqh_last;/* addr of last next element */		\
252}
253
254#define	STAILQ_HEAD_INITIALIZER(head)					\
255	{ NULL, &(head).stqh_first }
256
257#define	STAILQ_ENTRY(type)						\
258struct {								\
259	struct type *stqe_next;	/* next element */			\
260}
261
262/*
263 * Singly-linked Tail queue functions.
264 */
265#define	STAILQ_CONCAT(head1, head2) do {				\
266	if (!STAILQ_EMPTY((head2))) {					\
267		*(head1)->stqh_last = (head2)->stqh_first;		\
268		(head1)->stqh_last = (head2)->stqh_last;		\
269		STAILQ_INIT((head2));					\
270	}								\
271} while (0)
272
273#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
274
275#define	STAILQ_FIRST(head)	((head)->stqh_first)
276
277#define	STAILQ_FOREACH(var, head, field)				\
278	for((var) = STAILQ_FIRST((head));				\
279	   (var);							\
280	   (var) = STAILQ_NEXT((var), field))
281
282
283#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
284	for ((var) = STAILQ_FIRST((head));				\
285	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
286	    (var) = (tvar))
287
288#define	STAILQ_INIT(head) do {						\
289	STAILQ_FIRST((head)) = NULL;					\
290	(head)->stqh_last = &STAILQ_FIRST((head));			\
291} while (0)
292
293#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
294	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
295		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
296	STAILQ_NEXT((tqelm), field) = (elm);				\
297} while (0)
298
299#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
300	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
301		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
302	STAILQ_FIRST((head)) = (elm);					\
303} while (0)
304
305#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
306	STAILQ_NEXT((elm), field) = NULL;				\
307	*(head)->stqh_last = (elm);					\
308	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
309} while (0)
310
311#define	STAILQ_LAST(head, type, field)					\
312	(STAILQ_EMPTY((head)) ?						\
313		NULL :							\
314	        ((struct type *)(void *)				\
315		((char *)((head)->stqh_last) - __offsetof(struct type, field))))
316
317#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
318
319#define	STAILQ_REMOVE(head, elm, type, field) do {			\
320	if (STAILQ_FIRST((head)) == (elm)) {				\
321		STAILQ_REMOVE_HEAD((head), field);			\
322	}								\
323	else {								\
324		struct type *curelm = STAILQ_FIRST((head));		\
325		while (STAILQ_NEXT(curelm, field) != (elm))		\
326			curelm = STAILQ_NEXT(curelm, field);		\
327		if ((STAILQ_NEXT(curelm, field) =			\
328		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
329			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
330	}								\
331	TRASHIT((elm)->field.stqe_next);				\
332} while (0)
333
334#define	STAILQ_REMOVE_HEAD(head, field) do {				\
335	if ((STAILQ_FIRST((head)) =					\
336	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
337		(head)->stqh_last = &STAILQ_FIRST((head));		\
338} while (0)
339
340#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
341	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
342		(head)->stqh_last = &STAILQ_FIRST((head));		\
343} while (0)
344
345/*
346 * List declarations.
347 */
348#define	LIST_HEAD(name, type)						\
349struct name {								\
350	struct type *lh_first;	/* first element */			\
351}
352
353#define	LIST_HEAD_INITIALIZER(head)					\
354	{ NULL }
355
356#define	LIST_ENTRY(type)						\
357struct {								\
358	struct type *le_next;	/* next element */			\
359	struct type **le_prev;	/* address of previous next element */	\
360}
361
362/*
363 * List functions.
364 */
365
366#if (defined(_KERNEL) && defined(INVARIANTS)) || defined(QUEUE_MACRO_DEBUG)
367#define	QMD_LIST_CHECK_HEAD(head, field) do {				\
368	if (LIST_FIRST((head)) != NULL &&				\
369	    LIST_FIRST((head))->field.le_prev !=			\
370	     &LIST_FIRST((head)))					\
371		panic("Bad list head %p first->prev != head", (head));	\
372} while (0)
373
374#define	QMD_LIST_CHECK_NEXT(elm, field) do {				\
375	if (LIST_NEXT((elm), field) != NULL &&				\
376	    LIST_NEXT((elm), field)->field.le_prev !=			\
377	     &((elm)->field.le_next))					\
378	     	panic("Bad link elm %p next->prev != elm", (elm));	\
379} while (0)
380
381#define	QMD_LIST_CHECK_PREV(elm, field) do {				\
382	if (*(elm)->field.le_prev != (elm))				\
383		panic("Bad link elm %p prev->next != elm", (elm));	\
384} while (0)
385#else
386#define	QMD_LIST_CHECK_HEAD(head, field)
387#define	QMD_LIST_CHECK_NEXT(elm, field)
388#define	QMD_LIST_CHECK_PREV(elm, field)
389#endif /* (_KERNEL && INVARIANTS) || QUEUE_MACRO_DEBUG */
390
391#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
392
393#define	LIST_FIRST(head)	((head)->lh_first)
394
395#define	LIST_FOREACH(var, head, field)					\
396	for ((var) = LIST_FIRST((head));				\
397	    (var);							\
398	    (var) = LIST_NEXT((var), field))
399
400#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
401	for ((var) = LIST_FIRST((head));				\
402	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
403	    (var) = (tvar))
404
405#define	LIST_INIT(head) do {						\
406	LIST_FIRST((head)) = NULL;					\
407} while (0)
408
409#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
410	QMD_LIST_CHECK_NEXT(listelm, field);				\
411	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
412		LIST_NEXT((listelm), field)->field.le_prev =		\
413		    &LIST_NEXT((elm), field);				\
414	LIST_NEXT((listelm), field) = (elm);				\
415	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
416} while (0)
417
418#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
419	QMD_LIST_CHECK_PREV(listelm, field);				\
420	(elm)->field.le_prev = (listelm)->field.le_prev;		\
421	LIST_NEXT((elm), field) = (listelm);				\
422	*(listelm)->field.le_prev = (elm);				\
423	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
424} while (0)
425
426#define	LIST_INSERT_HEAD(head, elm, field) do {				\
427	QMD_LIST_CHECK_HEAD((head), field);				\
428	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
429		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
430	LIST_FIRST((head)) = (elm);					\
431	(elm)->field.le_prev = &LIST_FIRST((head));			\
432} while (0)
433
434#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
435
436#define	LIST_REMOVE(elm, field) do {					\
437	QMD_LIST_CHECK_NEXT(elm, field);				\
438	QMD_LIST_CHECK_PREV(elm, field);				\
439	if (LIST_NEXT((elm), field) != NULL)				\
440		LIST_NEXT((elm), field)->field.le_prev = 		\
441		    (elm)->field.le_prev;				\
442	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
443	TRASHIT((elm)->field.le_next);					\
444	TRASHIT((elm)->field.le_prev);					\
445} while (0)
446
447/*
448 * Tail queue declarations.
449 */
450#define	TAILQ_HEAD(name, type)						\
451struct name {								\
452	struct type *tqh_first;	/* first element */			\
453	struct type **tqh_last;	/* addr of last next element */		\
454	TRACEBUF							\
455}
456
457#define	TAILQ_HEAD_INITIALIZER(head)					\
458	{ NULL, &(head).tqh_first }
459
460#define	TAILQ_ENTRY(type)						\
461struct {								\
462	struct type *tqe_next;	/* next element */			\
463	struct type **tqe_prev;	/* address of previous next element */	\
464	TRACEBUF							\
465}
466
467/*
468 * Tail queue functions.
469 */
470#define	TAILQ_CONCAT(head1, head2, field) do {				\
471	if (!TAILQ_EMPTY(head2)) {					\
472		*(head1)->tqh_last = (head2)->tqh_first;		\
473		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
474		(head1)->tqh_last = (head2)->tqh_last;			\
475		TAILQ_INIT((head2));					\
476		QMD_TRACE_HEAD(head1);					\
477		QMD_TRACE_HEAD(head2);					\
478	}								\
479} while (0)
480
481#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
482
483#define	TAILQ_FIRST(head)	((head)->tqh_first)
484
485#define	TAILQ_FOREACH(var, head, field)					\
486	for ((var) = TAILQ_FIRST((head));				\
487	    (var);							\
488	    (var) = TAILQ_NEXT((var), field))
489
490#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
491	for ((var) = TAILQ_FIRST((head));				\
492	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
493	    (var) = (tvar))
494
495#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
496	for ((var) = TAILQ_LAST((head), headname);			\
497	    (var);							\
498	    (var) = TAILQ_PREV((var), headname, field))
499
500#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
501	for ((var) = TAILQ_LAST((head), headname);			\
502	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
503	    (var) = (tvar))
504
505#define	TAILQ_INIT(head) do {						\
506	TAILQ_FIRST((head)) = NULL;					\
507	(head)->tqh_last = &TAILQ_FIRST((head));			\
508	QMD_TRACE_HEAD(head);						\
509} while (0)
510
511#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
512	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
513		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
514		    &TAILQ_NEXT((elm), field);				\
515	else {								\
516		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
517		QMD_TRACE_HEAD(head);					\
518	}								\
519	TAILQ_NEXT((listelm), field) = (elm);				\
520	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
521	QMD_TRACE_ELEM(&(elm)->field);					\
522	QMD_TRACE_ELEM(&listelm->field);				\
523} while (0)
524
525#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
526	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
527	TAILQ_NEXT((elm), field) = (listelm);				\
528	*(listelm)->field.tqe_prev = (elm);				\
529	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
530	QMD_TRACE_ELEM(&(elm)->field);					\
531	QMD_TRACE_ELEM(&listelm->field);				\
532} while (0)
533
534#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
535	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
536		TAILQ_FIRST((head))->field.tqe_prev =			\
537		    &TAILQ_NEXT((elm), field);				\
538	else								\
539		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
540	TAILQ_FIRST((head)) = (elm);					\
541	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
542	QMD_TRACE_HEAD(head);						\
543	QMD_TRACE_ELEM(&(elm)->field);					\
544} while (0)
545
546#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
547	TAILQ_NEXT((elm), field) = NULL;				\
548	(elm)->field.tqe_prev = (head)->tqh_last;			\
549	*(head)->tqh_last = (elm);					\
550	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
551	QMD_TRACE_HEAD(head);						\
552	QMD_TRACE_ELEM(&(elm)->field);					\
553} while (0)
554
555#define	TAILQ_LAST(head, headname)					\
556	(*(((struct headname *)((head)->tqh_last))->tqh_last))
557
558#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
559
560#define	TAILQ_PREV(elm, headname, field)				\
561	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
562
563#define	TAILQ_REMOVE(head, elm, field) do {				\
564	if ((TAILQ_NEXT((elm), field)) != NULL)				\
565		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
566		    (elm)->field.tqe_prev;				\
567	else {								\
568		(head)->tqh_last = (elm)->field.tqe_prev;		\
569		QMD_TRACE_HEAD(head);					\
570	}								\
571	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
572	TRASHIT((elm)->field.tqe_next);					\
573	TRASHIT((elm)->field.tqe_prev);					\
574	QMD_TRACE_ELEM(&(elm)->field);					\
575} while (0)
576
577/*
578 * Circular queue definitions.
579 */
580#define CIRCLEQ_HEAD(name, type)					\
581struct name {								\
582	struct type *cqh_first;		/* first element */		\
583	struct type *cqh_last;		/* last element */		\
584}
585
586#define CIRCLEQ_ENTRY(type)						\
587struct {								\
588	struct type *cqe_next;		/* next element */		\
589	struct type *cqe_prev;		/* previous element */		\
590}
591
592/*
593 * Circular queue functions.
594 */
595#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
596
597#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
598
599#define CIRCLEQ_FOREACH(var, head, field)				\
600	for((var) = (head)->cqh_first;					\
601	    (var) != (void *)(head);					\
602	    (var) = (var)->field.cqe_next)
603
604#define	CIRCLEQ_INIT(head) do {						\
605	(head)->cqh_first = (void *)(head);				\
606	(head)->cqh_last = (void *)(head);				\
607} while (0)
608
609#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
610	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
611	(elm)->field.cqe_prev = (listelm);				\
612	if ((listelm)->field.cqe_next == (void *)(head))		\
613		(head)->cqh_last = (elm);				\
614	else								\
615		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
616	(listelm)->field.cqe_next = (elm);				\
617} while (0)
618
619#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
620	(elm)->field.cqe_next = (listelm);				\
621	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
622	if ((listelm)->field.cqe_prev == (void *)(head))		\
623		(head)->cqh_first = (elm);				\
624	else								\
625		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
626	(listelm)->field.cqe_prev = (elm);				\
627} while (0)
628
629#define CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
630	(elm)->field.cqe_next = (head)->cqh_first;			\
631	(elm)->field.cqe_prev = (void *)(head);				\
632	if ((head)->cqh_last == (void *)(head))				\
633		(head)->cqh_last = (elm);				\
634	else								\
635		(head)->cqh_first->field.cqe_prev = (elm);		\
636	(head)->cqh_first = (elm);					\
637} while (0)
638
639#define CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
640	(elm)->field.cqe_next = (void *)(head);				\
641	(elm)->field.cqe_prev = (head)->cqh_last;			\
642	if ((head)->cqh_first == (void *)(head))			\
643		(head)->cqh_first = (elm);				\
644	else								\
645		(head)->cqh_last->field.cqe_next = (elm);		\
646	(head)->cqh_last = (elm);					\
647} while (0)
648
649#define CIRCLEQ_LAST(head) ((head)->cqh_last)
650
651#define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
652
653#define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
654
655#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
656	if ((elm)->field.cqe_next == (void *)(head))			\
657		(head)->cqh_last = (elm)->field.cqe_prev;		\
658	else								\
659		(elm)->field.cqe_next->field.cqe_prev =			\
660		    (elm)->field.cqe_prev;				\
661	if ((elm)->field.cqe_prev == (void *)(head))			\
662		(head)->cqh_first = (elm)->field.cqe_next;		\
663	else								\
664		(elm)->field.cqe_prev->field.cqe_next =			\
665		    (elm)->field.cqe_next;				\
666} while (0)
667
668#ifdef _KERNEL
669
670#if NOTFB31
671
672/*
673 * XXX insque() and remque() are an old way of handling certain queues.
674 * They bogusly assumes that all queue heads look alike.
675 */
676
677struct quehead {
678	struct quehead *qh_link;
679	struct quehead *qh_rlink;
680};
681
682#ifdef __GNUC__
683
684static __inline void
685insque(void *a, void *b)
686{
687	struct quehead *element = (struct quehead *)a,
688		 *head = (struct quehead *)b;
689
690	element->qh_link = head->qh_link;
691	element->qh_rlink = head;
692	head->qh_link = element;
693	element->qh_link->qh_rlink = element;
694}
695
696static __inline void
697remque(void *a)
698{
699	struct quehead *element = (struct quehead *)a;
700
701	element->qh_link->qh_rlink = element->qh_rlink;
702	element->qh_rlink->qh_link = element->qh_link;
703	element->qh_rlink = 0;
704}
705
706#else /* !__GNUC__ */
707
708void	insque(void *a, void *b);
709void	remque(void *a);
710
711#endif /* __GNUC__ */
712
713#endif
714#endif /* _KERNEL */
715
716#endif /* !_SYS_QUEUE_H_ */