xref: /openbmc/linux/drivers/scsi/aic7xxx/queue.h (revision 9938b04472d5c59f8bd8152a548533a8599596a2)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * Copyright (c) 1991, 1993
31da177e4SLinus Torvalds  *	The Regents of the University of California.  All rights reserved.
41da177e4SLinus Torvalds  *
51da177e4SLinus Torvalds  * Redistribution and use in source and binary forms, with or without
61da177e4SLinus Torvalds  * modification, are permitted provided that the following conditions
71da177e4SLinus Torvalds  * are met:
81da177e4SLinus Torvalds  * 1. Redistributions of source code must retain the above copyright
91da177e4SLinus Torvalds  *    notice, this list of conditions and the following disclaimer.
101da177e4SLinus Torvalds  * 2. Redistributions in binary form must reproduce the above copyright
111da177e4SLinus Torvalds  *    notice, this list of conditions and the following disclaimer in the
121da177e4SLinus Torvalds  *    documentation and/or other materials provided with the distribution.
131da177e4SLinus Torvalds  *
141da177e4SLinus Torvalds  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
151da177e4SLinus Torvalds  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161da177e4SLinus Torvalds  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171da177e4SLinus Torvalds  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
181da177e4SLinus Torvalds  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191da177e4SLinus Torvalds  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201da177e4SLinus Torvalds  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211da177e4SLinus Torvalds  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221da177e4SLinus Torvalds  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231da177e4SLinus Torvalds  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241da177e4SLinus Torvalds  * SUCH DAMAGE.
251da177e4SLinus Torvalds  *
261da177e4SLinus Torvalds  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
271da177e4SLinus Torvalds  * $FreeBSD: src/sys/sys/queue.h,v 1.38 2000/05/26 02:06:56 jake Exp $
281da177e4SLinus Torvalds  */
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds #ifndef _SYS_QUEUE_H_
311da177e4SLinus Torvalds #define	_SYS_QUEUE_H_
321da177e4SLinus Torvalds 
331da177e4SLinus Torvalds /*
341da177e4SLinus Torvalds  * This file defines five types of data structures: singly-linked lists,
351da177e4SLinus Torvalds  * singly-linked tail queues, lists, tail queues, and circular queues.
361da177e4SLinus Torvalds  *
371da177e4SLinus Torvalds  * A singly-linked list is headed by a single forward pointer. The elements
381da177e4SLinus Torvalds  * are singly linked for minimum space and pointer manipulation overhead at
391da177e4SLinus Torvalds  * the expense of O(n) removal for arbitrary elements. New elements can be
401da177e4SLinus Torvalds  * added to the list after an existing element or at the head of the list.
411da177e4SLinus Torvalds  * Elements being removed from the head of the list should use the explicit
421da177e4SLinus Torvalds  * macro for this purpose for optimum efficiency. A singly-linked list may
431da177e4SLinus Torvalds  * only be traversed in the forward direction.  Singly-linked lists are ideal
441da177e4SLinus Torvalds  * for applications with large datasets and few or no removals or for
451da177e4SLinus Torvalds  * implementing a LIFO queue.
461da177e4SLinus Torvalds  *
471da177e4SLinus Torvalds  * A singly-linked tail queue is headed by a pair of pointers, one to the
481da177e4SLinus Torvalds  * head of the list and the other to the tail of the list. The elements are
491da177e4SLinus Torvalds  * singly linked for minimum space and pointer manipulation overhead at the
501da177e4SLinus Torvalds  * expense of O(n) removal for arbitrary elements. New elements can be added
511da177e4SLinus Torvalds  * to the list after an existing element, at the head of the list, or at the
521da177e4SLinus Torvalds  * end of the list. Elements being removed from the head of the tail queue
531da177e4SLinus Torvalds  * should use the explicit macro for this purpose for optimum efficiency.
541da177e4SLinus Torvalds  * A singly-linked tail queue may only be traversed in the forward direction.
551da177e4SLinus Torvalds  * Singly-linked tail queues are ideal for applications with large datasets
561da177e4SLinus Torvalds  * and few or no removals or for implementing a FIFO queue.
571da177e4SLinus Torvalds  *
581da177e4SLinus Torvalds  * A list is headed by a single forward pointer (or an array of forward
591da177e4SLinus Torvalds  * pointers for a hash table header). The elements are doubly linked
601da177e4SLinus Torvalds  * so that an arbitrary element can be removed without a need to
611da177e4SLinus Torvalds  * traverse the list. New elements can be added to the list before
621da177e4SLinus Torvalds  * or after an existing element or at the head of the list. A list
631da177e4SLinus Torvalds  * may only be traversed in the forward direction.
641da177e4SLinus Torvalds  *
651da177e4SLinus Torvalds  * A tail queue is headed by a pair of pointers, one to the head of the
661da177e4SLinus Torvalds  * list and the other to the tail of the list. The elements are doubly
671da177e4SLinus Torvalds  * linked so that an arbitrary element can be removed without a need to
681da177e4SLinus Torvalds  * traverse the list. New elements can be added to the list before or
691da177e4SLinus Torvalds  * after an existing element, at the head of the list, or at the end of
701da177e4SLinus Torvalds  * the list. A tail queue may be traversed in either direction.
711da177e4SLinus Torvalds  *
721da177e4SLinus Torvalds  * A circle queue is headed by a pair of pointers, one to the head of the
731da177e4SLinus Torvalds  * list and the other to the tail of the list. The elements are doubly
741da177e4SLinus Torvalds  * linked so that an arbitrary element can be removed without a need to
751da177e4SLinus Torvalds  * traverse the list. New elements can be added to the list before or after
761da177e4SLinus Torvalds  * an existing element, at the head of the list, or at the end of the list.
771da177e4SLinus Torvalds  * A circle queue may be traversed in either direction, but has a more
781da177e4SLinus Torvalds  * complex end of list detection.
791da177e4SLinus Torvalds  *
801da177e4SLinus Torvalds  * For details on the use of these macros, see the queue(3) manual page.
811da177e4SLinus Torvalds  *
821da177e4SLinus Torvalds  *
831da177e4SLinus Torvalds  *			SLIST	LIST	STAILQ	TAILQ	CIRCLEQ
841da177e4SLinus Torvalds  * _HEAD		+	+	+	+	+
851da177e4SLinus Torvalds  * _HEAD_INITIALIZER	+	+	+	+	+
861da177e4SLinus Torvalds  * _ENTRY		+	+	+	+	+
871da177e4SLinus Torvalds  * _INIT		+	+	+	+	+
881da177e4SLinus Torvalds  * _EMPTY		+	+	+	+	+
891da177e4SLinus Torvalds  * _FIRST		+	+	+	+	+
901da177e4SLinus Torvalds  * _NEXT		+	+	+	+	+
911da177e4SLinus Torvalds  * _PREV		-	-	-	+	+
921da177e4SLinus Torvalds  * _LAST		-	-	+	+	+
931da177e4SLinus Torvalds  * _FOREACH		+	+	+	+	+
941da177e4SLinus Torvalds  * _FOREACH_REVERSE	-	-	-	+	+
951da177e4SLinus Torvalds  * _INSERT_HEAD		+	+	+	+	+
961da177e4SLinus Torvalds  * _INSERT_BEFORE	-	+	-	+	+
971da177e4SLinus Torvalds  * _INSERT_AFTER	+	+	+	+	+
981da177e4SLinus Torvalds  * _INSERT_TAIL		-	-	+	+	+
991da177e4SLinus Torvalds  * _REMOVE_HEAD		+	-	+	-	-
1001da177e4SLinus Torvalds  * _REMOVE		+	+	+	+	+
1011da177e4SLinus Torvalds  *
1021da177e4SLinus Torvalds  */
1031da177e4SLinus Torvalds 
1041da177e4SLinus Torvalds /*
1051da177e4SLinus Torvalds  * Singly-linked List declarations.
1061da177e4SLinus Torvalds  */
1071da177e4SLinus Torvalds #define	SLIST_HEAD(name, type)						\
1081da177e4SLinus Torvalds struct name {								\
1091da177e4SLinus Torvalds 	struct type *slh_first;	/* first element */			\
1101da177e4SLinus Torvalds }
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds #define	SLIST_HEAD_INITIALIZER(head)					\
1131da177e4SLinus Torvalds 	{ NULL }
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds #define	SLIST_ENTRY(type)						\
1161da177e4SLinus Torvalds struct {								\
1171da177e4SLinus Torvalds 	struct type *sle_next;	/* next element */			\
1181da177e4SLinus Torvalds }
1191da177e4SLinus Torvalds 
1201da177e4SLinus Torvalds /*
1211da177e4SLinus Torvalds  * Singly-linked List functions.
1221da177e4SLinus Torvalds  */
1231da177e4SLinus Torvalds #define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds #define	SLIST_FIRST(head)	((head)->slh_first)
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds #define	SLIST_FOREACH(var, head, field)					\
1281da177e4SLinus Torvalds 	for ((var) = SLIST_FIRST((head));				\
1291da177e4SLinus Torvalds 	    (var);							\
1301da177e4SLinus Torvalds 	    (var) = SLIST_NEXT((var), field))
1311da177e4SLinus Torvalds 
1321da177e4SLinus Torvalds #define	SLIST_INIT(head) do {						\
1331da177e4SLinus Torvalds 	SLIST_FIRST((head)) = NULL;					\
1341da177e4SLinus Torvalds } while (0)
1351da177e4SLinus Torvalds 
1361da177e4SLinus Torvalds #define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
1371da177e4SLinus Torvalds 	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
1381da177e4SLinus Torvalds 	SLIST_NEXT((slistelm), field) = (elm);				\
1391da177e4SLinus Torvalds } while (0)
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds #define	SLIST_INSERT_HEAD(head, elm, field) do {			\
1421da177e4SLinus Torvalds 	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
1431da177e4SLinus Torvalds 	SLIST_FIRST((head)) = (elm);					\
1441da177e4SLinus Torvalds } while (0)
1451da177e4SLinus Torvalds 
1461da177e4SLinus Torvalds #define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
1471da177e4SLinus Torvalds 
1481da177e4SLinus Torvalds #define	SLIST_REMOVE(head, elm, type, field) do {			\
1491da177e4SLinus Torvalds 	if (SLIST_FIRST((head)) == (elm)) {				\
1501da177e4SLinus Torvalds 		SLIST_REMOVE_HEAD((head), field);			\
1511da177e4SLinus Torvalds 	}								\
1521da177e4SLinus Torvalds 	else {								\
1531da177e4SLinus Torvalds 		struct type *curelm = SLIST_FIRST((head));		\
1541da177e4SLinus Torvalds 		while (SLIST_NEXT(curelm, field) != (elm))		\
1551da177e4SLinus Torvalds 			curelm = SLIST_NEXT(curelm, field);		\
1561da177e4SLinus Torvalds 		SLIST_NEXT(curelm, field) =				\
1571da177e4SLinus Torvalds 		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\
1581da177e4SLinus Torvalds 	}								\
1591da177e4SLinus Torvalds } while (0)
1601da177e4SLinus Torvalds 
1611da177e4SLinus Torvalds #define	SLIST_REMOVE_HEAD(head, field) do {				\
1621da177e4SLinus Torvalds 	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
1631da177e4SLinus Torvalds } while (0)
1641da177e4SLinus Torvalds 
1651da177e4SLinus Torvalds /*
1661da177e4SLinus Torvalds  * Singly-linked Tail queue declarations.
1671da177e4SLinus Torvalds  */
1681da177e4SLinus Torvalds #define	STAILQ_HEAD(name, type)						\
1691da177e4SLinus Torvalds struct name {								\
1701da177e4SLinus Torvalds 	struct type *stqh_first;/* first element */			\
1711da177e4SLinus Torvalds 	struct type **stqh_last;/* addr of last next element */		\
1721da177e4SLinus Torvalds }
1731da177e4SLinus Torvalds 
1741da177e4SLinus Torvalds #define	STAILQ_HEAD_INITIALIZER(head)					\
1751da177e4SLinus Torvalds 	{ NULL, &(head).stqh_first }
1761da177e4SLinus Torvalds 
1771da177e4SLinus Torvalds #define	STAILQ_ENTRY(type)						\
1781da177e4SLinus Torvalds struct {								\
1791da177e4SLinus Torvalds 	struct type *stqe_next;	/* next element */			\
1801da177e4SLinus Torvalds }
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds /*
1831da177e4SLinus Torvalds  * Singly-linked Tail queue functions.
1841da177e4SLinus Torvalds  */
1851da177e4SLinus Torvalds #define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds #define	STAILQ_FIRST(head)	((head)->stqh_first)
1881da177e4SLinus Torvalds 
1891da177e4SLinus Torvalds #define	STAILQ_FOREACH(var, head, field)				\
1901da177e4SLinus Torvalds 	for((var) = STAILQ_FIRST((head));				\
1911da177e4SLinus Torvalds 	   (var);							\
1921da177e4SLinus Torvalds 	   (var) = STAILQ_NEXT((var), field))
1931da177e4SLinus Torvalds 
1941da177e4SLinus Torvalds #define	STAILQ_INIT(head) do {						\
1951da177e4SLinus Torvalds 	STAILQ_FIRST((head)) = NULL;					\
1961da177e4SLinus Torvalds 	(head)->stqh_last = &STAILQ_FIRST((head));			\
1971da177e4SLinus Torvalds } while (0)
1981da177e4SLinus Torvalds 
1991da177e4SLinus Torvalds #define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
2001da177e4SLinus Torvalds 	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
2011da177e4SLinus Torvalds 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
2021da177e4SLinus Torvalds 	STAILQ_NEXT((tqelm), field) = (elm);				\
2031da177e4SLinus Torvalds } while (0)
2041da177e4SLinus Torvalds 
2051da177e4SLinus Torvalds #define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
2061da177e4SLinus Torvalds 	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
2071da177e4SLinus Torvalds 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
2081da177e4SLinus Torvalds 	STAILQ_FIRST((head)) = (elm);					\
2091da177e4SLinus Torvalds } while (0)
2101da177e4SLinus Torvalds 
2111da177e4SLinus Torvalds #define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
2121da177e4SLinus Torvalds 	STAILQ_NEXT((elm), field) = NULL;				\
2131da177e4SLinus Torvalds 	STAILQ_LAST((head)) = (elm);					\
2141da177e4SLinus Torvalds 	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
2151da177e4SLinus Torvalds } while (0)
2161da177e4SLinus Torvalds 
2171da177e4SLinus Torvalds #define	STAILQ_LAST(head)	(*(head)->stqh_last)
2181da177e4SLinus Torvalds 
2191da177e4SLinus Torvalds #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
2201da177e4SLinus Torvalds 
2211da177e4SLinus Torvalds #define	STAILQ_REMOVE(head, elm, type, field) do {			\
2221da177e4SLinus Torvalds 	if (STAILQ_FIRST((head)) == (elm)) {				\
2231da177e4SLinus Torvalds 		STAILQ_REMOVE_HEAD(head, field);			\
2241da177e4SLinus Torvalds 	}								\
2251da177e4SLinus Torvalds 	else {								\
2261da177e4SLinus Torvalds 		struct type *curelm = STAILQ_FIRST((head));		\
2271da177e4SLinus Torvalds 		while (STAILQ_NEXT(curelm, field) != (elm))		\
2281da177e4SLinus Torvalds 			curelm = STAILQ_NEXT(curelm, field);		\
2291da177e4SLinus Torvalds 		if ((STAILQ_NEXT(curelm, field) =			\
2301da177e4SLinus Torvalds 		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
2311da177e4SLinus Torvalds 			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
2321da177e4SLinus Torvalds 	}								\
2331da177e4SLinus Torvalds } while (0)
2341da177e4SLinus Torvalds 
2351da177e4SLinus Torvalds #define	STAILQ_REMOVE_HEAD(head, field) do {				\
2361da177e4SLinus Torvalds 	if ((STAILQ_FIRST((head)) =					\
2371da177e4SLinus Torvalds 	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
2381da177e4SLinus Torvalds 		(head)->stqh_last = &STAILQ_FIRST((head));		\
2391da177e4SLinus Torvalds } while (0)
2401da177e4SLinus Torvalds 
2411da177e4SLinus Torvalds #define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
2421da177e4SLinus Torvalds 	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
2431da177e4SLinus Torvalds 		(head)->stqh_last = &STAILQ_FIRST((head));		\
2441da177e4SLinus Torvalds } while (0)
2451da177e4SLinus Torvalds 
2461da177e4SLinus Torvalds /*
2471da177e4SLinus Torvalds  * List declarations.
2481da177e4SLinus Torvalds  */
249*e594a178SMichal Marek #define	BSD_LIST_HEAD(name, type)					\
2501da177e4SLinus Torvalds struct name {								\
2511da177e4SLinus Torvalds 	struct type *lh_first;	/* first element */			\
2521da177e4SLinus Torvalds }
2531da177e4SLinus Torvalds 
2541da177e4SLinus Torvalds #define	LIST_HEAD_INITIALIZER(head)					\
2551da177e4SLinus Torvalds 	{ NULL }
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds #define	LIST_ENTRY(type)						\
2581da177e4SLinus Torvalds struct {								\
2591da177e4SLinus Torvalds 	struct type *le_next;	/* next element */			\
2601da177e4SLinus Torvalds 	struct type **le_prev;	/* address of previous next element */	\
2611da177e4SLinus Torvalds }
2621da177e4SLinus Torvalds 
2631da177e4SLinus Torvalds /*
2641da177e4SLinus Torvalds  * List functions.
2651da177e4SLinus Torvalds  */
2661da177e4SLinus Torvalds 
2671da177e4SLinus Torvalds #define	LIST_EMPTY(head)	((head)->lh_first == NULL)
2681da177e4SLinus Torvalds 
2691da177e4SLinus Torvalds #define	LIST_FIRST(head)	((head)->lh_first)
2701da177e4SLinus Torvalds 
2711da177e4SLinus Torvalds #define	LIST_FOREACH(var, head, field)					\
2721da177e4SLinus Torvalds 	for ((var) = LIST_FIRST((head));				\
2731da177e4SLinus Torvalds 	    (var);							\
2741da177e4SLinus Torvalds 	    (var) = LIST_NEXT((var), field))
2751da177e4SLinus Torvalds 
2761da177e4SLinus Torvalds #define	LIST_INIT(head) do {						\
2771da177e4SLinus Torvalds 	LIST_FIRST((head)) = NULL;					\
2781da177e4SLinus Torvalds } while (0)
2791da177e4SLinus Torvalds 
2801da177e4SLinus Torvalds #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
2811da177e4SLinus Torvalds 	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
2821da177e4SLinus Torvalds 		LIST_NEXT((listelm), field)->field.le_prev =		\
2831da177e4SLinus Torvalds 		    &LIST_NEXT((elm), field);				\
2841da177e4SLinus Torvalds 	LIST_NEXT((listelm), field) = (elm);				\
2851da177e4SLinus Torvalds 	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
2861da177e4SLinus Torvalds } while (0)
2871da177e4SLinus Torvalds 
2881da177e4SLinus Torvalds #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
2891da177e4SLinus Torvalds 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
2901da177e4SLinus Torvalds 	LIST_NEXT((elm), field) = (listelm);				\
2911da177e4SLinus Torvalds 	*(listelm)->field.le_prev = (elm);				\
2921da177e4SLinus Torvalds 	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
2931da177e4SLinus Torvalds } while (0)
2941da177e4SLinus Torvalds 
2951da177e4SLinus Torvalds #define	LIST_INSERT_HEAD(head, elm, field) do {				\
2961da177e4SLinus Torvalds 	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
2971da177e4SLinus Torvalds 		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
2981da177e4SLinus Torvalds 	LIST_FIRST((head)) = (elm);					\
2991da177e4SLinus Torvalds 	(elm)->field.le_prev = &LIST_FIRST((head));			\
3001da177e4SLinus Torvalds } while (0)
3011da177e4SLinus Torvalds 
3021da177e4SLinus Torvalds #define	LIST_NEXT(elm, field)	((elm)->field.le_next)
3031da177e4SLinus Torvalds 
3041da177e4SLinus Torvalds #define	LIST_REMOVE(elm, field) do {					\
3051da177e4SLinus Torvalds 	if (LIST_NEXT((elm), field) != NULL)				\
3061da177e4SLinus Torvalds 		LIST_NEXT((elm), field)->field.le_prev = 		\
3071da177e4SLinus Torvalds 		    (elm)->field.le_prev;				\
3081da177e4SLinus Torvalds 	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
3091da177e4SLinus Torvalds } while (0)
3101da177e4SLinus Torvalds 
3111da177e4SLinus Torvalds /*
3121da177e4SLinus Torvalds  * Tail queue declarations.
3131da177e4SLinus Torvalds  */
3141da177e4SLinus Torvalds #define	TAILQ_HEAD(name, type)						\
3151da177e4SLinus Torvalds struct name {								\
3161da177e4SLinus Torvalds 	struct type *tqh_first;	/* first element */			\
3171da177e4SLinus Torvalds 	struct type **tqh_last;	/* addr of last next element */		\
3181da177e4SLinus Torvalds }
3191da177e4SLinus Torvalds 
3201da177e4SLinus Torvalds #define	TAILQ_HEAD_INITIALIZER(head)					\
3211da177e4SLinus Torvalds 	{ NULL, &(head).tqh_first }
3221da177e4SLinus Torvalds 
3231da177e4SLinus Torvalds #define	TAILQ_ENTRY(type)						\
3241da177e4SLinus Torvalds struct {								\
3251da177e4SLinus Torvalds 	struct type *tqe_next;	/* next element */			\
3261da177e4SLinus Torvalds 	struct type **tqe_prev;	/* address of previous next element */	\
3271da177e4SLinus Torvalds }
3281da177e4SLinus Torvalds 
3291da177e4SLinus Torvalds /*
3301da177e4SLinus Torvalds  * Tail queue functions.
3311da177e4SLinus Torvalds  */
3321da177e4SLinus Torvalds #define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
3331da177e4SLinus Torvalds 
3341da177e4SLinus Torvalds #define	TAILQ_FIRST(head)	((head)->tqh_first)
3351da177e4SLinus Torvalds 
3361da177e4SLinus Torvalds #define	TAILQ_FOREACH(var, head, field)					\
3371da177e4SLinus Torvalds 	for ((var) = TAILQ_FIRST((head));				\
3381da177e4SLinus Torvalds 	    (var);							\
3391da177e4SLinus Torvalds 	    (var) = TAILQ_NEXT((var), field))
3401da177e4SLinus Torvalds 
3411da177e4SLinus Torvalds #define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
3421da177e4SLinus Torvalds 	for ((var) = TAILQ_LAST((head), headname);			\
3431da177e4SLinus Torvalds 	    (var);							\
3441da177e4SLinus Torvalds 	    (var) = TAILQ_PREV((var), headname, field))
3451da177e4SLinus Torvalds 
3461da177e4SLinus Torvalds #define	TAILQ_INIT(head) do {						\
3471da177e4SLinus Torvalds 	TAILQ_FIRST((head)) = NULL;					\
3481da177e4SLinus Torvalds 	(head)->tqh_last = &TAILQ_FIRST((head));			\
3491da177e4SLinus Torvalds } while (0)
3501da177e4SLinus Torvalds 
3511da177e4SLinus Torvalds #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
3521da177e4SLinus Torvalds 	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
3531da177e4SLinus Torvalds 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
3541da177e4SLinus Torvalds 		    &TAILQ_NEXT((elm), field);				\
3551da177e4SLinus Torvalds 	else								\
3561da177e4SLinus Torvalds 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
3571da177e4SLinus Torvalds 	TAILQ_NEXT((listelm), field) = (elm);				\
3581da177e4SLinus Torvalds 	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
3591da177e4SLinus Torvalds } while (0)
3601da177e4SLinus Torvalds 
3611da177e4SLinus Torvalds #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
3621da177e4SLinus Torvalds 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
3631da177e4SLinus Torvalds 	TAILQ_NEXT((elm), field) = (listelm);				\
3641da177e4SLinus Torvalds 	*(listelm)->field.tqe_prev = (elm);				\
3651da177e4SLinus Torvalds 	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
3661da177e4SLinus Torvalds } while (0)
3671da177e4SLinus Torvalds 
3681da177e4SLinus Torvalds #define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
3691da177e4SLinus Torvalds 	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
3701da177e4SLinus Torvalds 		TAILQ_FIRST((head))->field.tqe_prev =			\
3711da177e4SLinus Torvalds 		    &TAILQ_NEXT((elm), field);				\
3721da177e4SLinus Torvalds 	else								\
3731da177e4SLinus Torvalds 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
3741da177e4SLinus Torvalds 	TAILQ_FIRST((head)) = (elm);					\
3751da177e4SLinus Torvalds 	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
3761da177e4SLinus Torvalds } while (0)
3771da177e4SLinus Torvalds 
3781da177e4SLinus Torvalds #define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
3791da177e4SLinus Torvalds 	TAILQ_NEXT((elm), field) = NULL;				\
3801da177e4SLinus Torvalds 	(elm)->field.tqe_prev = (head)->tqh_last;			\
3811da177e4SLinus Torvalds 	*(head)->tqh_last = (elm);					\
3821da177e4SLinus Torvalds 	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
3831da177e4SLinus Torvalds } while (0)
3841da177e4SLinus Torvalds 
3851da177e4SLinus Torvalds #define	TAILQ_LAST(head, headname)					\
3861da177e4SLinus Torvalds 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
3871da177e4SLinus Torvalds 
3881da177e4SLinus Torvalds #define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
3891da177e4SLinus Torvalds 
3901da177e4SLinus Torvalds #define	TAILQ_PREV(elm, headname, field)				\
3911da177e4SLinus Torvalds 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
3921da177e4SLinus Torvalds 
3931da177e4SLinus Torvalds #define	TAILQ_REMOVE(head, elm, field) do {				\
3941da177e4SLinus Torvalds 	if ((TAILQ_NEXT((elm), field)) != NULL)				\
3951da177e4SLinus Torvalds 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
3961da177e4SLinus Torvalds 		    (elm)->field.tqe_prev;				\
3971da177e4SLinus Torvalds 	else								\
3981da177e4SLinus Torvalds 		(head)->tqh_last = (elm)->field.tqe_prev;		\
3991da177e4SLinus Torvalds 	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
4001da177e4SLinus Torvalds } while (0)
4011da177e4SLinus Torvalds 
4021da177e4SLinus Torvalds /*
4031da177e4SLinus Torvalds  * Circular queue declarations.
4041da177e4SLinus Torvalds  */
4051da177e4SLinus Torvalds #define	CIRCLEQ_HEAD(name, type)					\
4061da177e4SLinus Torvalds struct name {								\
4071da177e4SLinus Torvalds 	struct type *cqh_first;		/* first element */		\
4081da177e4SLinus Torvalds 	struct type *cqh_last;		/* last element */		\
4091da177e4SLinus Torvalds }
4101da177e4SLinus Torvalds 
4111da177e4SLinus Torvalds #define	CIRCLEQ_HEAD_INITIALIZER(head)					\
4121da177e4SLinus Torvalds 	{ (void *)&(head), (void *)&(head) }
4131da177e4SLinus Torvalds 
4141da177e4SLinus Torvalds #define	CIRCLEQ_ENTRY(type)						\
4151da177e4SLinus Torvalds struct {								\
4161da177e4SLinus Torvalds 	struct type *cqe_next;		/* next element */		\
4171da177e4SLinus Torvalds 	struct type *cqe_prev;		/* previous element */		\
4181da177e4SLinus Torvalds }
4191da177e4SLinus Torvalds 
4201da177e4SLinus Torvalds /*
4211da177e4SLinus Torvalds  * Circular queue functions.
4221da177e4SLinus Torvalds  */
4231da177e4SLinus Torvalds #define	CIRCLEQ_EMPTY(head)	((head)->cqh_first == (void *)(head))
4241da177e4SLinus Torvalds 
4251da177e4SLinus Torvalds #define	CIRCLEQ_FIRST(head)	((head)->cqh_first)
4261da177e4SLinus Torvalds 
4271da177e4SLinus Torvalds #define	CIRCLEQ_FOREACH(var, head, field)				\
4281da177e4SLinus Torvalds 	for ((var) = CIRCLEQ_FIRST((head));				\
4291da177e4SLinus Torvalds 	    (var) != (void *)(head);					\
4301da177e4SLinus Torvalds 	    (var) = CIRCLEQ_NEXT((var), field))
4311da177e4SLinus Torvalds 
4321da177e4SLinus Torvalds #define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
4331da177e4SLinus Torvalds 	for ((var) = CIRCLEQ_LAST((head));				\
4341da177e4SLinus Torvalds 	    (var) != (void *)(head);					\
4351da177e4SLinus Torvalds 	    (var) = CIRCLEQ_PREV((var), field))
4361da177e4SLinus Torvalds 
4371da177e4SLinus Torvalds #define	CIRCLEQ_INIT(head) do {						\
4381da177e4SLinus Torvalds 	CIRCLEQ_FIRST((head)) = (void *)(head);				\
4391da177e4SLinus Torvalds 	CIRCLEQ_LAST((head)) = (void *)(head);				\
4401da177e4SLinus Torvalds } while (0)
4411da177e4SLinus Torvalds 
4421da177e4SLinus Torvalds #define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
4431da177e4SLinus Torvalds 	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field);	\
4441da177e4SLinus Torvalds 	CIRCLEQ_PREV((elm), field) = (listelm);				\
4451da177e4SLinus Torvalds 	if (CIRCLEQ_NEXT((listelm), field) == (void *)(head))		\
4461da177e4SLinus Torvalds 		CIRCLEQ_LAST((head)) = (elm);				\
4471da177e4SLinus Torvalds 	else								\
4481da177e4SLinus Torvalds 		CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
4491da177e4SLinus Torvalds 	CIRCLEQ_NEXT((listelm), field) = (elm);				\
4501da177e4SLinus Torvalds } while (0)
4511da177e4SLinus Torvalds 
4521da177e4SLinus Torvalds #define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
4531da177e4SLinus Torvalds 	CIRCLEQ_NEXT((elm), field) = (listelm);				\
4541da177e4SLinus Torvalds 	CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field);	\
4551da177e4SLinus Torvalds 	if (CIRCLEQ_PREV((listelm), field) == (void *)(head))		\
4561da177e4SLinus Torvalds 		CIRCLEQ_FIRST((head)) = (elm);				\
4571da177e4SLinus Torvalds 	else								\
4581da177e4SLinus Torvalds 		CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
4591da177e4SLinus Torvalds 	CIRCLEQ_PREV((listelm), field) = (elm);				\
4601da177e4SLinus Torvalds } while (0)
4611da177e4SLinus Torvalds 
4621da177e4SLinus Torvalds #define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
4631da177e4SLinus Torvalds 	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head));		\
4641da177e4SLinus Torvalds 	CIRCLEQ_PREV((elm), field) = (void *)(head);			\
4651da177e4SLinus Torvalds 	if (CIRCLEQ_LAST((head)) == (void *)(head))			\
4661da177e4SLinus Torvalds 		CIRCLEQ_LAST((head)) = (elm);				\
4671da177e4SLinus Torvalds 	else								\
4681da177e4SLinus Torvalds 		CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm);	\
4691da177e4SLinus Torvalds 	CIRCLEQ_FIRST((head)) = (elm);					\
4701da177e4SLinus Torvalds } while (0)
4711da177e4SLinus Torvalds 
4721da177e4SLinus Torvalds #define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
4731da177e4SLinus Torvalds 	CIRCLEQ_NEXT((elm), field) = (void *)(head);			\
4741da177e4SLinus Torvalds 	CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head));		\
4751da177e4SLinus Torvalds 	if (CIRCLEQ_FIRST((head)) == (void *)(head))			\
4761da177e4SLinus Torvalds 		CIRCLEQ_FIRST((head)) = (elm);				\
4771da177e4SLinus Torvalds 	else								\
4781da177e4SLinus Torvalds 		CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm);	\
4791da177e4SLinus Torvalds 	CIRCLEQ_LAST((head)) = (elm);					\
4801da177e4SLinus Torvalds } while (0)
4811da177e4SLinus Torvalds 
4821da177e4SLinus Torvalds #define	CIRCLEQ_LAST(head)	((head)->cqh_last)
4831da177e4SLinus Torvalds 
4841da177e4SLinus Torvalds #define	CIRCLEQ_NEXT(elm,field)	((elm)->field.cqe_next)
4851da177e4SLinus Torvalds 
4861da177e4SLinus Torvalds #define	CIRCLEQ_PREV(elm,field)	((elm)->field.cqe_prev)
4871da177e4SLinus Torvalds 
4881da177e4SLinus Torvalds #define	CIRCLEQ_REMOVE(head, elm, field) do {				\
4891da177e4SLinus Torvalds 	if (CIRCLEQ_NEXT((elm), field) == (void *)(head))		\
4901da177e4SLinus Torvalds 		CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field);	\
4911da177e4SLinus Torvalds 	else								\
4921da177e4SLinus Torvalds 		CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) =	\
4931da177e4SLinus Torvalds 		    CIRCLEQ_PREV((elm), field);				\
4941da177e4SLinus Torvalds 	if (CIRCLEQ_PREV((elm), field) == (void *)(head))		\
4951da177e4SLinus Torvalds 		CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field);	\
4961da177e4SLinus Torvalds 	else								\
4971da177e4SLinus Torvalds 		CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) =	\
4981da177e4SLinus Torvalds 		    CIRCLEQ_NEXT((elm), field);				\
4991da177e4SLinus Torvalds } while (0)
5001da177e4SLinus Torvalds 
5011da177e4SLinus Torvalds #endif /* !_SYS_QUEUE_H_ */
502