xref: /freebsd-src/contrib/ntp/include/ntp_lists.h (revision f5f40dd63bc7acbb5312b26ac1ea1103c12352a6)
12b15cb3dSCy Schubert /*
22b15cb3dSCy Schubert  * ntp_lists.h - linked lists common code
32b15cb3dSCy Schubert  *
42b15cb3dSCy Schubert  * SLIST: singly-linked lists
52b15cb3dSCy Schubert  * ==========================
62b15cb3dSCy Schubert  *
72b15cb3dSCy Schubert  * These macros implement a simple singly-linked list template.  Both
82b15cb3dSCy Schubert  * the listhead and per-entry next fields are declared as pointers to
92b15cb3dSCy Schubert  * the list entry struct type.  Initialization to NULL is typically
102b15cb3dSCy Schubert  * implicit (for globals and statics) or handled by zeroing of the
112b15cb3dSCy Schubert  * containing structure.
122b15cb3dSCy Schubert  *
132b15cb3dSCy Schubert  * The name of the next link field is passed as an argument to allow
142b15cb3dSCy Schubert  * membership in several lists at once using multiple next link fields.
152b15cb3dSCy Schubert  *
162b15cb3dSCy Schubert  * When possible, placing the link field first in the entry structure
172b15cb3dSCy Schubert  * allows slightly smaller code to be generated on some platforms.
182b15cb3dSCy Schubert  *
192b15cb3dSCy Schubert  * LINK_SLIST(listhead, pentry, nextlink)
202b15cb3dSCy Schubert  *	add entry at head
212b15cb3dSCy Schubert  *
222b15cb3dSCy Schubert  * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)
232b15cb3dSCy Schubert  *	add entry at tail.  This is O(n), if this is a common
242b15cb3dSCy Schubert  *	operation the FIFO template may be more appropriate.
252b15cb3dSCy Schubert  *
262b15cb3dSCy Schubert  * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype)
272b15cb3dSCy Schubert  *	add entry in sorted order.  beforecur is an expression comparing
282b15cb3dSCy Schubert  *	pentry with the current list entry.  The current entry can be
292b15cb3dSCy Schubert  *	referenced within beforecur as L_S_S_CUR(), which is short for
302b15cb3dSCy Schubert  *	LINK_SORT_SLIST_CUR().  beforecur is nonzero if pentry sorts
312b15cb3dSCy Schubert  *	before L_S_S_CUR().
322b15cb3dSCy Schubert  *
332b15cb3dSCy Schubert  * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)
342b15cb3dSCy Schubert  *	unlink first entry and point punlinked to it, or set punlinked
352b15cb3dSCy Schubert  *	to NULL if the list is empty.
362b15cb3dSCy Schubert  *
372b15cb3dSCy Schubert  * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype)
382b15cb3dSCy Schubert  *	unlink entry pointed to by ptounlink.  punlinked is set to NULL
392b15cb3dSCy Schubert  *	if the entry is not found on the list, otherwise it is set to
402b15cb3dSCy Schubert  *	ptounlink.
412b15cb3dSCy Schubert  *
422b15cb3dSCy Schubert  * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype)
432b15cb3dSCy Schubert  *	unlink entry where expression expr is nonzero.  expr can refer
442b15cb3dSCy Schubert  *	to the entry being tested using UNLINK_EXPR_SLIST_CURRENT(),
452b15cb3dSCy Schubert  *	alias U_E_S_CUR().  See the implementation of UNLINK_SLIST()
462b15cb3dSCy Schubert  *	below for an example. U_E_S_CUR() is NULL iff the list is empty.
472b15cb3dSCy Schubert  *	punlinked is pointed to the removed entry or NULL if none
482b15cb3dSCy Schubert  *	satisfy expr.
492b15cb3dSCy Schubert  *
502b15cb3dSCy Schubert  * FIFO: singly-linked lists plus tail pointer
512b15cb3dSCy Schubert  * ===========================================
522b15cb3dSCy Schubert  *
532b15cb3dSCy Schubert  * This is the same as FreeBSD's sys/queue.h STAILQ -- a singly-linked
542b15cb3dSCy Schubert  * list implementation with tail-pointer maintenance, so that adding
552b15cb3dSCy Schubert  * at the tail for first-in, first-out access is O(1).
562b15cb3dSCy Schubert  *
572b15cb3dSCy Schubert  * DECL_FIFO_ANCHOR(entrytype)
582b15cb3dSCy Schubert  *	provides the type specification portion of the declaration for
592b15cb3dSCy Schubert  *	a variable to refer to a FIFO queue (similar to listhead).  The
602b15cb3dSCy Schubert  *	anchor contains the head and indirect tail pointers.  Example:
612b15cb3dSCy Schubert  *
622b15cb3dSCy Schubert  *		#include "ntp_lists.h"
632b15cb3dSCy Schubert  *
642b15cb3dSCy Schubert  *		typedef struct myentry_tag myentry;
652b15cb3dSCy Schubert  *		struct myentry_tag {
662b15cb3dSCy Schubert  *			myentry *next_link;
672b15cb3dSCy Schubert  *			...
682b15cb3dSCy Schubert  *		};
692b15cb3dSCy Schubert  *
702b15cb3dSCy Schubert  *		DECL_FIFO_ANCHOR(myentry) my_fifo;
712b15cb3dSCy Schubert  *
722b15cb3dSCy Schubert  *		void somefunc(myentry *pentry)
732b15cb3dSCy Schubert  *		{
742b15cb3dSCy Schubert  *			LINK_FIFO(my_fifo, pentry, next_link);
752b15cb3dSCy Schubert  *		}
762b15cb3dSCy Schubert  *
772b15cb3dSCy Schubert  *	If DECL_FIFO_ANCHOR is used with stack or heap storage, it
782b15cb3dSCy Schubert  *	should be initialized to NULL pointers using a = { NULL };
792b15cb3dSCy Schubert  *	initializer or memset.
802b15cb3dSCy Schubert  *
812b15cb3dSCy Schubert  * HEAD_FIFO(anchor)
822b15cb3dSCy Schubert  * TAIL_FIFO(anchor)
832b15cb3dSCy Schubert  *	Pointer to first/last entry, NULL if FIFO is empty.
842b15cb3dSCy Schubert  *
852b15cb3dSCy Schubert  * LINK_FIFO(anchor, pentry, nextlink)
862b15cb3dSCy Schubert  *	add entry at tail.
872b15cb3dSCy Schubert  *
882b15cb3dSCy Schubert  * UNLINK_FIFO(punlinked, anchor, nextlink)
892b15cb3dSCy Schubert  *	unlink head entry and point punlinked to it, or set punlinked
902b15cb3dSCy Schubert  *	to NULL if the list is empty.
912b15cb3dSCy Schubert  *
922b15cb3dSCy Schubert  * CONCAT_FIFO(q1, q2, nextlink)
932b15cb3dSCy Schubert  *	empty fifoq q2 moving its nodes to q1 following q1's existing
942b15cb3dSCy Schubert  *	nodes.
952b15cb3dSCy Schubert  *
962b15cb3dSCy Schubert  * DLIST: doubly-linked lists
972b15cb3dSCy Schubert  * ==========================
982b15cb3dSCy Schubert  *
992b15cb3dSCy Schubert  * Elements on DLISTs always have non-NULL forward and back links,
1002b15cb3dSCy Schubert  * because both link chains are circular.  The beginning/end is marked
1012b15cb3dSCy Schubert  * by the listhead, which is the same type as elements for simplicity.
1022b15cb3dSCy Schubert  * An empty list's listhead has both links set to its own address.
1032b15cb3dSCy Schubert  *
1042b15cb3dSCy Schubert  *
1052b15cb3dSCy Schubert  */
1062b15cb3dSCy Schubert #ifndef NTP_LISTS_H
1072b15cb3dSCy Schubert #define NTP_LISTS_H
1082b15cb3dSCy Schubert 
1092b15cb3dSCy Schubert #include "ntp_types.h"		/* TRUE and FALSE */
1102b15cb3dSCy Schubert #include "ntp_assert.h"
1112b15cb3dSCy Schubert 
1122b15cb3dSCy Schubert #ifdef DEBUG
1132b15cb3dSCy Schubert # define NTP_DEBUG_LISTS_H
1142b15cb3dSCy Schubert #endif
1152b15cb3dSCy Schubert 
1162b15cb3dSCy Schubert /*
1172b15cb3dSCy Schubert  * If list debugging is not enabled, save a little time by not clearing
1182b15cb3dSCy Schubert  * an entry's link pointer when it is unlinked, as the stale pointer
1192b15cb3dSCy Schubert  * is harmless as long as it is ignored when the entry is not in a
1202b15cb3dSCy Schubert  * list.
1212b15cb3dSCy Schubert  */
1222b15cb3dSCy Schubert #ifndef NTP_DEBUG_LISTS_H
1232b15cb3dSCy Schubert #define MAYBE_Z_LISTS(p)	do { } while (FALSE)
1242b15cb3dSCy Schubert #else
1252b15cb3dSCy Schubert #define MAYBE_Z_LISTS(p)	(p) = NULL
1262b15cb3dSCy Schubert #endif
1272b15cb3dSCy Schubert 
1282b15cb3dSCy Schubert #define LINK_SLIST(listhead, pentry, nextlink)			\
1292b15cb3dSCy Schubert do {								\
1302b15cb3dSCy Schubert 	(pentry)->nextlink = (listhead);			\
1312b15cb3dSCy Schubert 	(listhead) = (pentry);					\
1322b15cb3dSCy Schubert } while (FALSE)
1332b15cb3dSCy Schubert 
1342b15cb3dSCy Schubert #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)	\
1352b15cb3dSCy Schubert do {								\
1362b15cb3dSCy Schubert 	entrytype **pptail;					\
1372b15cb3dSCy Schubert 								\
1382b15cb3dSCy Schubert 	pptail = &(listhead);					\
1392b15cb3dSCy Schubert 	while (*pptail != NULL)					\
1402b15cb3dSCy Schubert 		pptail = &((*pptail)->nextlink);		\
1412b15cb3dSCy Schubert 								\
1422b15cb3dSCy Schubert 	(pentry)->nextlink = NULL;				\
1432b15cb3dSCy Schubert 	*pptail = (pentry);					\
1442b15cb3dSCy Schubert } while (FALSE)
1452b15cb3dSCy Schubert 
1462b15cb3dSCy Schubert #define LINK_SORT_SLIST_CURRENT()	(*ppentry)
1472b15cb3dSCy Schubert #define	L_S_S_CUR()			LINK_SORT_SLIST_CURRENT()
1482b15cb3dSCy Schubert 
1492b15cb3dSCy Schubert #define LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink,	\
1502b15cb3dSCy Schubert 			entrytype)				\
1512b15cb3dSCy Schubert do {								\
1522b15cb3dSCy Schubert 	entrytype **ppentry;					\
1532b15cb3dSCy Schubert 								\
1542b15cb3dSCy Schubert 	ppentry = &(listhead);					\
1552b15cb3dSCy Schubert 	while (TRUE) {						\
1562b15cb3dSCy Schubert 		if (NULL == *ppentry || (beforecur)) {		\
1572b15cb3dSCy Schubert 			(pentry)->nextlink = *ppentry;		\
1582b15cb3dSCy Schubert 			*ppentry = (pentry);			\
1592b15cb3dSCy Schubert 			break;					\
1602b15cb3dSCy Schubert 		}						\
1612b15cb3dSCy Schubert 		ppentry = &((*ppentry)->nextlink);		\
1622b15cb3dSCy Schubert 		if (NULL == *ppentry) {				\
1632b15cb3dSCy Schubert 			(pentry)->nextlink = NULL;		\
1642b15cb3dSCy Schubert 			*ppentry = (pentry);			\
1652b15cb3dSCy Schubert 			break;					\
1662b15cb3dSCy Schubert 		}						\
1672b15cb3dSCy Schubert 	}							\
1682b15cb3dSCy Schubert } while (FALSE)
1692b15cb3dSCy Schubert 
1702b15cb3dSCy Schubert #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)	\
1712b15cb3dSCy Schubert do {								\
1722b15cb3dSCy Schubert 	(punlinked) = (listhead);				\
1732b15cb3dSCy Schubert 	if (NULL != (punlinked)) {				\
1742b15cb3dSCy Schubert 		(listhead) = (punlinked)->nextlink;		\
1752b15cb3dSCy Schubert 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
1762b15cb3dSCy Schubert 	}							\
1772b15cb3dSCy Schubert } while (FALSE)
1782b15cb3dSCy Schubert 
1792b15cb3dSCy Schubert #define UNLINK_EXPR_SLIST_CURRENT()	(*ppentry)
1802b15cb3dSCy Schubert #define	U_E_S_CUR()			UNLINK_EXPR_SLIST_CURRENT()
1812b15cb3dSCy Schubert 
1822b15cb3dSCy Schubert #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink,	\
1832b15cb3dSCy Schubert 			  entrytype)				\
184*f5f40dd6SCy Schubert if (NULL != (listhead)) {					\
1852b15cb3dSCy Schubert 	entrytype **ppentry;					\
1862b15cb3dSCy Schubert 								\
1872b15cb3dSCy Schubert 	ppentry = &(listhead);					\
1882b15cb3dSCy Schubert 								\
1892b15cb3dSCy Schubert 	while (!(expr))						\
1902b15cb3dSCy Schubert 		if (*ppentry != NULL &&				\
1912b15cb3dSCy Schubert 		    (*ppentry)->nextlink != NULL) {		\
1922b15cb3dSCy Schubert 			ppentry = &((*ppentry)->nextlink);	\
1932b15cb3dSCy Schubert 		} else {					\
1942b15cb3dSCy Schubert 			ppentry = NULL;				\
1952b15cb3dSCy Schubert 			break;					\
1962b15cb3dSCy Schubert 		}						\
1972b15cb3dSCy Schubert 								\
1982b15cb3dSCy Schubert 	if (ppentry != NULL) {					\
1992b15cb3dSCy Schubert 		(punlinked) = *ppentry;				\
2002b15cb3dSCy Schubert 		*ppentry = (punlinked)->nextlink;		\
2012b15cb3dSCy Schubert 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
2022b15cb3dSCy Schubert 	} else {						\
2032b15cb3dSCy Schubert 		(punlinked) = NULL;				\
2042b15cb3dSCy Schubert 	}							\
205*f5f40dd6SCy Schubert } else do {							\
206*f5f40dd6SCy Schubert 	(punlinked) = NULL;					\
2072b15cb3dSCy Schubert } while (FALSE)
2082b15cb3dSCy Schubert 
2092b15cb3dSCy Schubert #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink,	\
2102b15cb3dSCy Schubert 		     entrytype)					\
2112b15cb3dSCy Schubert 	UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) ==	\
2122b15cb3dSCy Schubert 	    U_E_S_CUR(), nextlink, entrytype)
2132b15cb3dSCy Schubert 
2142b15cb3dSCy Schubert #define CHECK_SLIST(listhead, nextlink, entrytype)		\
2152b15cb3dSCy Schubert do {								\
2162b15cb3dSCy Schubert 	entrytype *pentry;					\
2172b15cb3dSCy Schubert 								\
2182b15cb3dSCy Schubert 	for (pentry = (listhead);				\
2192b15cb3dSCy Schubert 	     pentry != NULL;					\
2202b15cb3dSCy Schubert 	     pentry = pentry->nextlink) {			\
2219034852cSGleb Smirnoff 		INSIST(pentry != pentry->nextlink);		\
2229034852cSGleb Smirnoff 		INSIST((listhead) != pentry->nextlink);		\
2232b15cb3dSCy Schubert 	}							\
2242b15cb3dSCy Schubert } while (FALSE)
2252b15cb3dSCy Schubert 
2262b15cb3dSCy Schubert /*
2272b15cb3dSCy Schubert  * FIFO
2282b15cb3dSCy Schubert  */
2292b15cb3dSCy Schubert 
2302b15cb3dSCy Schubert #define DECL_FIFO_ANCHOR(entrytype)				\
2312b15cb3dSCy Schubert struct {							\
2322b15cb3dSCy Schubert 	entrytype *	phead;	/* NULL if list empty */	\
2332b15cb3dSCy Schubert 	entrytype **	pptail;	/* NULL if list empty */	\
2342b15cb3dSCy Schubert }
2352b15cb3dSCy Schubert 
2362b15cb3dSCy Schubert #define HEAD_FIFO(anchor)	((anchor).phead)
2372b15cb3dSCy Schubert #define TAIL_FIFO(anchor)	((NULL == (anchor).pptail)	\
2382b15cb3dSCy Schubert 					? NULL			\
2392b15cb3dSCy Schubert 					: *((anchor).pptail))
2402b15cb3dSCy Schubert 
2412b15cb3dSCy Schubert /*
2422b15cb3dSCy Schubert  * For DEBUG builds only, verify both or neither of the anchor pointers
2432b15cb3dSCy Schubert  * are NULL with each operation.
2442b15cb3dSCy Schubert  */
2452b15cb3dSCy Schubert #if !defined(NTP_DEBUG_LISTS_H)
2462b15cb3dSCy Schubert #define	CHECK_FIFO_CONSISTENCY(anchor)	do { } while (FALSE)
2472b15cb3dSCy Schubert #else
2482b15cb3dSCy Schubert #define	CHECK_FIFO_CONSISTENCY(anchor)				\
2492b15cb3dSCy Schubert 	check_gen_fifo_consistency(&(anchor))
2502b15cb3dSCy Schubert void	check_gen_fifo_consistency(void *fifo);
2512b15cb3dSCy Schubert #endif
2522b15cb3dSCy Schubert 
2532b15cb3dSCy Schubert /*
2542b15cb3dSCy Schubert  * generic FIFO element used to access any FIFO where each element
2552b15cb3dSCy Schubert  * begins with the link pointer
2562b15cb3dSCy Schubert  */
2572b15cb3dSCy Schubert typedef struct gen_node_tag gen_node;
2582b15cb3dSCy Schubert struct gen_node_tag {
2592b15cb3dSCy Schubert 	gen_node *	link;
2602b15cb3dSCy Schubert };
2612b15cb3dSCy Schubert 
2622b15cb3dSCy Schubert /* generic FIFO */
2632b15cb3dSCy Schubert typedef DECL_FIFO_ANCHOR(gen_node) gen_fifo;
2642b15cb3dSCy Schubert 
2652b15cb3dSCy Schubert 
2662b15cb3dSCy Schubert #define LINK_FIFO(anchor, pentry, nextlink)			\
2672b15cb3dSCy Schubert do {								\
2682b15cb3dSCy Schubert 	CHECK_FIFO_CONSISTENCY(anchor);				\
2692b15cb3dSCy Schubert 								\
2702b15cb3dSCy Schubert 	(pentry)->nextlink = NULL;				\
2712b15cb3dSCy Schubert 	if (NULL != (anchor).pptail) {				\
2722b15cb3dSCy Schubert 		(*((anchor).pptail))->nextlink = (pentry);	\
2732b15cb3dSCy Schubert 		(anchor).pptail =				\
2742b15cb3dSCy Schubert 		    &(*((anchor).pptail))->nextlink;		\
2752b15cb3dSCy Schubert 	} else {						\
2762b15cb3dSCy Schubert 		(anchor).phead = (pentry);			\
2772b15cb3dSCy Schubert 		(anchor).pptail = &(anchor).phead;		\
2782b15cb3dSCy Schubert 	}							\
2792b15cb3dSCy Schubert 								\
2802b15cb3dSCy Schubert 	CHECK_FIFO_CONSISTENCY(anchor);				\
2812b15cb3dSCy Schubert } while (FALSE)
2822b15cb3dSCy Schubert 
2832b15cb3dSCy Schubert #define UNLINK_FIFO(punlinked, anchor, nextlink)		\
2842b15cb3dSCy Schubert do {								\
2852b15cb3dSCy Schubert 	CHECK_FIFO_CONSISTENCY(anchor);				\
2862b15cb3dSCy Schubert 								\
2872b15cb3dSCy Schubert 	(punlinked) = (anchor).phead;				\
2882b15cb3dSCy Schubert 	if (NULL != (punlinked)) {				\
2892b15cb3dSCy Schubert 		(anchor).phead = (punlinked)->nextlink;		\
2902b15cb3dSCy Schubert 		if (NULL == (anchor).phead)			\
2912b15cb3dSCy Schubert 			(anchor).pptail = NULL;			\
2922b15cb3dSCy Schubert 		else if ((anchor).pptail ==			\
2932b15cb3dSCy Schubert 			 &(punlinked)->nextlink)		\
2942b15cb3dSCy Schubert 			(anchor).pptail = &(anchor).phead;	\
2952b15cb3dSCy Schubert 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
2962b15cb3dSCy Schubert 		CHECK_FIFO_CONSISTENCY(anchor);			\
2972b15cb3dSCy Schubert 	}							\
2982b15cb3dSCy Schubert } while (FALSE)
2992b15cb3dSCy Schubert 
3002b15cb3dSCy Schubert #define UNLINK_MID_FIFO(punlinked, anchor, tounlink, nextlink,	\
3012b15cb3dSCy Schubert 			entrytype)				\
3022b15cb3dSCy Schubert do {								\
3032b15cb3dSCy Schubert 	entrytype **ppentry;					\
3042b15cb3dSCy Schubert 								\
3052b15cb3dSCy Schubert 	CHECK_FIFO_CONSISTENCY(anchor);				\
3062b15cb3dSCy Schubert 								\
3072b15cb3dSCy Schubert 	ppentry = &(anchor).phead;				\
3082b15cb3dSCy Schubert 								\
3092b15cb3dSCy Schubert 	while ((tounlink) != *ppentry)				\
3102b15cb3dSCy Schubert 		if ((*ppentry)->nextlink != NULL) {		\
3112b15cb3dSCy Schubert 			ppentry = &((*ppentry)->nextlink);	\
3122b15cb3dSCy Schubert 		} else {					\
3132b15cb3dSCy Schubert 			ppentry = NULL;				\
3142b15cb3dSCy Schubert 			break;					\
3152b15cb3dSCy Schubert 		}						\
3162b15cb3dSCy Schubert 								\
3172b15cb3dSCy Schubert 	if (ppentry != NULL) {					\
3182b15cb3dSCy Schubert 		(punlinked) = *ppentry;				\
3192b15cb3dSCy Schubert 		*ppentry = (punlinked)->nextlink;		\
3202b15cb3dSCy Schubert 		if (NULL == *ppentry)				\
3212b15cb3dSCy Schubert 			(anchor).pptail = NULL;			\
3222b15cb3dSCy Schubert 		else if ((anchor).pptail ==			\
3232b15cb3dSCy Schubert 			 &(punlinked)->nextlink)		\
3242b15cb3dSCy Schubert 			(anchor).pptail = &(anchor).phead;	\
3252b15cb3dSCy Schubert 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
3262b15cb3dSCy Schubert 		CHECK_FIFO_CONSISTENCY(anchor);			\
3272b15cb3dSCy Schubert 	} else {						\
3282b15cb3dSCy Schubert 		(punlinked) = NULL;				\
3292b15cb3dSCy Schubert 	}							\
3302b15cb3dSCy Schubert } while (FALSE)
3312b15cb3dSCy Schubert 
3322b15cb3dSCy Schubert #define CONCAT_FIFO(f1, f2, nextlink)				\
3332b15cb3dSCy Schubert do {								\
3342b15cb3dSCy Schubert 	CHECK_FIFO_CONSISTENCY(f1);				\
3352b15cb3dSCy Schubert 	CHECK_FIFO_CONSISTENCY(f2);				\
3362b15cb3dSCy Schubert 								\
3372b15cb3dSCy Schubert 	if ((f2).pptail != NULL) {				\
3382b15cb3dSCy Schubert 		if ((f1).pptail != NULL) {			\
3392b15cb3dSCy Schubert 			(*(f1).pptail)->nextlink = (f2).phead;	\
3402b15cb3dSCy Schubert 			if ((f2).pptail == &(f2).phead)		\
3412b15cb3dSCy Schubert 				(f1).pptail =			\
3422b15cb3dSCy Schubert 				    &(*(f1).pptail)->nextlink;	\
3432b15cb3dSCy Schubert 			else					\
3442b15cb3dSCy Schubert 				(f1).pptail = (f2).pptail;	\
3452b15cb3dSCy Schubert 			CHECK_FIFO_CONSISTENCY(f1);		\
3462b15cb3dSCy Schubert 		} else	{					\
3472b15cb3dSCy Schubert 			(f1) = (f2);				\
3482b15cb3dSCy Schubert 		}						\
3492b15cb3dSCy Schubert 		MAYBE_Z_LISTS((f2).phead);			\
3502b15cb3dSCy Schubert 		MAYBE_Z_LISTS((f2).pptail);			\
3512b15cb3dSCy Schubert 	}							\
3522b15cb3dSCy Schubert } while (FALSE)
3532b15cb3dSCy Schubert 
3542b15cb3dSCy Schubert /*
3552b15cb3dSCy Schubert  * DLIST
3562b15cb3dSCy Schubert  */
3572b15cb3dSCy Schubert #define DECL_DLIST_LINK(entrytype, link)			\
3582b15cb3dSCy Schubert struct {							\
3592b15cb3dSCy Schubert 	entrytype *	b;					\
3602b15cb3dSCy Schubert 	entrytype *	f;					\
3612b15cb3dSCy Schubert } link
3622b15cb3dSCy Schubert 
3632b15cb3dSCy Schubert #define INIT_DLIST(listhead, link)				\
3642b15cb3dSCy Schubert do {								\
3652b15cb3dSCy Schubert 	(listhead).link.f = &(listhead);			\
3662b15cb3dSCy Schubert 	(listhead).link.b = &(listhead);			\
3672b15cb3dSCy Schubert } while (FALSE)
3682b15cb3dSCy Schubert 
3692b15cb3dSCy Schubert #define HEAD_DLIST(listhead, link)				\
3702b15cb3dSCy Schubert 	(							\
3712b15cb3dSCy Schubert 		(&(listhead) != (listhead).link.f)		\
3722b15cb3dSCy Schubert 		    ? (listhead).link.f				\
3732b15cb3dSCy Schubert 		    : NULL					\
3742b15cb3dSCy Schubert 	)
3752b15cb3dSCy Schubert 
3762b15cb3dSCy Schubert #define TAIL_DLIST(listhead, link)				\
3772b15cb3dSCy Schubert 	(							\
3782b15cb3dSCy Schubert 		(&(listhead) != (listhead).link.b)		\
3792b15cb3dSCy Schubert 		    ? (listhead).link.b				\
3802b15cb3dSCy Schubert 		    : NULL					\
3812b15cb3dSCy Schubert 	)
3822b15cb3dSCy Schubert 
3832b15cb3dSCy Schubert #define NEXT_DLIST(listhead, entry, link)			\
3842b15cb3dSCy Schubert 	(							\
3852b15cb3dSCy Schubert 		(&(listhead) != (entry)->link.f)		\
3862b15cb3dSCy Schubert 		    ? (entry)->link.f				\
3872b15cb3dSCy Schubert 		    : NULL					\
3882b15cb3dSCy Schubert 	)
3892b15cb3dSCy Schubert 
3902b15cb3dSCy Schubert #define PREV_DLIST(listhead, entry, link)			\
3912b15cb3dSCy Schubert 	(							\
3922b15cb3dSCy Schubert 		(&(listhead) != (entry)->link.b)		\
3932b15cb3dSCy Schubert 		    ? (entry)->link.b				\
3942b15cb3dSCy Schubert 		    : NULL					\
3952b15cb3dSCy Schubert 	)
3962b15cb3dSCy Schubert 
3972b15cb3dSCy Schubert #define LINK_DLIST(listhead, pentry, link)			\
3982b15cb3dSCy Schubert do {								\
3992b15cb3dSCy Schubert 	(pentry)->link.f = (listhead).link.f;			\
4002b15cb3dSCy Schubert 	(pentry)->link.b = &(listhead);				\
4012b15cb3dSCy Schubert 	(listhead).link.f->link.b = (pentry);			\
4022b15cb3dSCy Schubert 	(listhead).link.f = (pentry);				\
4032b15cb3dSCy Schubert } while (FALSE)
4042b15cb3dSCy Schubert 
4052b15cb3dSCy Schubert #define LINK_TAIL_DLIST(listhead, pentry, link)			\
4062b15cb3dSCy Schubert do {								\
4072b15cb3dSCy Schubert 	(pentry)->link.b = (listhead).link.b;			\
4082b15cb3dSCy Schubert 	(pentry)->link.f = &(listhead);				\
4092b15cb3dSCy Schubert 	(listhead).link.b->link.f = (pentry);			\
4102b15cb3dSCy Schubert 	(listhead).link.b = (pentry);				\
4112b15cb3dSCy Schubert } while (FALSE)
4122b15cb3dSCy Schubert 
4132b15cb3dSCy Schubert #define UNLINK_DLIST(ptounlink, link)				\
4142b15cb3dSCy Schubert do {								\
4152b15cb3dSCy Schubert 	(ptounlink)->link.b->link.f = (ptounlink)->link.f;	\
4162b15cb3dSCy Schubert 	(ptounlink)->link.f->link.b = (ptounlink)->link.b;	\
4172b15cb3dSCy Schubert 	MAYBE_Z_LISTS((ptounlink)->link.b);			\
4182b15cb3dSCy Schubert 	MAYBE_Z_LISTS((ptounlink)->link.f);			\
4192b15cb3dSCy Schubert } while (FALSE)
4202b15cb3dSCy Schubert 
4212b15cb3dSCy Schubert #define ITER_DLIST_BEGIN(listhead, iter, link, entrytype)	\
4222b15cb3dSCy Schubert {								\
4232b15cb3dSCy Schubert 	entrytype *i_dl_nextiter;				\
4242b15cb3dSCy Schubert 								\
4252b15cb3dSCy Schubert 	for ((iter) = (listhead).link.f;			\
4262b15cb3dSCy Schubert 	     (iter) != &(listhead)				\
4272b15cb3dSCy Schubert 	     && ((i_dl_nextiter = (iter)->link.f), TRUE);	\
4282b15cb3dSCy Schubert 	     (iter) = i_dl_nextiter) {
4292b15cb3dSCy Schubert #define ITER_DLIST_END()					\
4302b15cb3dSCy Schubert 	}							\
4312b15cb3dSCy Schubert }
4322b15cb3dSCy Schubert 
4332b15cb3dSCy Schubert #define REV_ITER_DLIST_BEGIN(listhead, iter, link, entrytype)	\
4342b15cb3dSCy Schubert {								\
4352b15cb3dSCy Schubert 	entrytype *i_dl_nextiter;				\
4362b15cb3dSCy Schubert 								\
4372b15cb3dSCy Schubert 	for ((iter) = (listhead).link.b;			\
4382b15cb3dSCy Schubert 	     (iter) != &(listhead)				\
4392b15cb3dSCy Schubert 	     && ((i_dl_nextiter = (iter)->link.b), TRUE);	\
4402b15cb3dSCy Schubert 	     (iter) = i_dl_nextiter) {
4412b15cb3dSCy Schubert #define REV_ITER_DLIST_END()					\
4422b15cb3dSCy Schubert 	}							\
4432b15cb3dSCy Schubert }
4442b15cb3dSCy Schubert 
4452b15cb3dSCy Schubert #endif	/* NTP_LISTS_H */
446