xref: /netbsd-src/external/bsd/ntp/dist/include/ntp_lists.h (revision 9e9fa66ad400fe02341b89216c5270e23a212d33)
1*9e9fa66aSchristos /*	$NetBSD: ntp_lists.h,v 1.8 2024/10/01 20:59:51 christos Exp $	*/
2abb0f93cSkardel 
3abb0f93cSkardel /*
4f003fb54Skardel  * ntp_lists.h - linked lists common code
5f003fb54Skardel  *
6f003fb54Skardel  * SLIST: singly-linked lists
7f003fb54Skardel  * ==========================
8abb0f93cSkardel  *
9abb0f93cSkardel  * These macros implement a simple singly-linked list template.  Both
10abb0f93cSkardel  * the listhead and per-entry next fields are declared as pointers to
11abb0f93cSkardel  * the list entry struct type.  Initialization to NULL is typically
12abb0f93cSkardel  * implicit (for globals and statics) or handled by zeroing of the
13abb0f93cSkardel  * containing structure.
14abb0f93cSkardel  *
15abb0f93cSkardel  * The name of the next link field is passed as an argument to allow
16abb0f93cSkardel  * membership in several lists at once using multiple next link fields.
17abb0f93cSkardel  *
18abb0f93cSkardel  * When possible, placing the link field first in the entry structure
19abb0f93cSkardel  * allows slightly smaller code to be generated on some platforms.
20abb0f93cSkardel  *
21abb0f93cSkardel  * LINK_SLIST(listhead, pentry, nextlink)
22abb0f93cSkardel  *	add entry at head
23abb0f93cSkardel  *
24abb0f93cSkardel  * LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)
25f003fb54Skardel  *	add entry at tail.  This is O(n), if this is a common
26f003fb54Skardel  *	operation the FIFO template may be more appropriate.
27f003fb54Skardel  *
28f003fb54Skardel  * LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink, entrytype)
29f003fb54Skardel  *	add entry in sorted order.  beforecur is an expression comparing
30f003fb54Skardel  *	pentry with the current list entry.  The current entry can be
31f003fb54Skardel  *	referenced within beforecur as L_S_S_CUR(), which is short for
32f003fb54Skardel  *	LINK_SORT_SLIST_CUR().  beforecur is nonzero if pentry sorts
33f003fb54Skardel  *	before L_S_S_CUR().
34abb0f93cSkardel  *
35abb0f93cSkardel  * UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)
36abb0f93cSkardel  *	unlink first entry and point punlinked to it, or set punlinked
37abb0f93cSkardel  *	to NULL if the list is empty.
38abb0f93cSkardel  *
39abb0f93cSkardel  * UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink, entrytype)
40abb0f93cSkardel  *	unlink entry pointed to by ptounlink.  punlinked is set to NULL
41abb0f93cSkardel  *	if the entry is not found on the list, otherwise it is set to
42abb0f93cSkardel  *	ptounlink.
43abb0f93cSkardel  *
44abb0f93cSkardel  * UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink, entrytype)
45abb0f93cSkardel  *	unlink entry where expression expr is nonzero.  expr can refer
46f003fb54Skardel  *	to the entry being tested using UNLINK_EXPR_SLIST_CURRENT(),
47f003fb54Skardel  *	alias U_E_S_CUR().  See the implementation of UNLINK_SLIST()
48f003fb54Skardel  *	below for an example. U_E_S_CUR() is NULL iff the list is empty.
49abb0f93cSkardel  *	punlinked is pointed to the removed entry or NULL if none
50abb0f93cSkardel  *	satisfy expr.
51f003fb54Skardel  *
52f003fb54Skardel  * FIFO: singly-linked lists plus tail pointer
53f003fb54Skardel  * ===========================================
54f003fb54Skardel  *
55f003fb54Skardel  * This is the same as FreeBSD's sys/queue.h STAILQ -- a singly-linked
56f003fb54Skardel  * list implementation with tail-pointer maintenance, so that adding
57f003fb54Skardel  * at the tail for first-in, first-out access is O(1).
58f003fb54Skardel  *
59f003fb54Skardel  * DECL_FIFO_ANCHOR(entrytype)
60f003fb54Skardel  *	provides the type specification portion of the declaration for
61f003fb54Skardel  *	a variable to refer to a FIFO queue (similar to listhead).  The
62f003fb54Skardel  *	anchor contains the head and indirect tail pointers.  Example:
63f003fb54Skardel  *
64f003fb54Skardel  *		#include "ntp_lists.h"
65f003fb54Skardel  *
66f003fb54Skardel  *		typedef struct myentry_tag myentry;
67f003fb54Skardel  *		struct myentry_tag {
68f003fb54Skardel  *			myentry *next_link;
69f003fb54Skardel  *			...
70f003fb54Skardel  *		};
71f003fb54Skardel  *
72f003fb54Skardel  *		DECL_FIFO_ANCHOR(myentry) my_fifo;
73f003fb54Skardel  *
74f003fb54Skardel  *		void somefunc(myentry *pentry)
75f003fb54Skardel  *		{
76f003fb54Skardel  *			LINK_FIFO(my_fifo, pentry, next_link);
77f003fb54Skardel  *		}
78f003fb54Skardel  *
79f003fb54Skardel  *	If DECL_FIFO_ANCHOR is used with stack or heap storage, it
80f003fb54Skardel  *	should be initialized to NULL pointers using a = { NULL };
81f003fb54Skardel  *	initializer or memset.
82f003fb54Skardel  *
83f003fb54Skardel  * HEAD_FIFO(anchor)
84f003fb54Skardel  * TAIL_FIFO(anchor)
85f003fb54Skardel  *	Pointer to first/last entry, NULL if FIFO is empty.
86f003fb54Skardel  *
87f003fb54Skardel  * LINK_FIFO(anchor, pentry, nextlink)
88f003fb54Skardel  *	add entry at tail.
89f003fb54Skardel  *
90f003fb54Skardel  * UNLINK_FIFO(punlinked, anchor, nextlink)
91f003fb54Skardel  *	unlink head entry and point punlinked to it, or set punlinked
92f003fb54Skardel  *	to NULL if the list is empty.
93f003fb54Skardel  *
94f003fb54Skardel  * CONCAT_FIFO(q1, q2, nextlink)
95f003fb54Skardel  *	empty fifoq q2 moving its nodes to q1 following q1's existing
96f003fb54Skardel  *	nodes.
97f003fb54Skardel  *
98f003fb54Skardel  * DLIST: doubly-linked lists
99f003fb54Skardel  * ==========================
100f003fb54Skardel  *
101f003fb54Skardel  * Elements on DLISTs always have non-NULL forward and back links,
102f003fb54Skardel  * because both link chains are circular.  The beginning/end is marked
103f003fb54Skardel  * by the listhead, which is the same type as elements for simplicity.
104f003fb54Skardel  * An empty list's listhead has both links set to its own address.
105f003fb54Skardel  *
106f003fb54Skardel  *
107abb0f93cSkardel  */
108abb0f93cSkardel #ifndef NTP_LISTS_H
109abb0f93cSkardel #define NTP_LISTS_H
110abb0f93cSkardel 
111f003fb54Skardel #include "ntp_types.h"		/* TRUE and FALSE */
112f003fb54Skardel #include "ntp_assert.h"
113f003fb54Skardel 
114f003fb54Skardel #ifdef DEBUG
115f003fb54Skardel # define NTP_DEBUG_LISTS_H
116abb0f93cSkardel #endif
117abb0f93cSkardel 
118f003fb54Skardel /*
119f003fb54Skardel  * If list debugging is not enabled, save a little time by not clearing
120f003fb54Skardel  * an entry's link pointer when it is unlinked, as the stale pointer
121f003fb54Skardel  * is harmless as long as it is ignored when the entry is not in a
122f003fb54Skardel  * list.
123f003fb54Skardel  */
124f003fb54Skardel #ifndef NTP_DEBUG_LISTS_H
125f003fb54Skardel #define MAYBE_Z_LISTS(p)	do { } while (FALSE)
126f003fb54Skardel #else
127f003fb54Skardel #define MAYBE_Z_LISTS(p)	(p) = NULL
128f003fb54Skardel #endif
129abb0f93cSkardel 
130abb0f93cSkardel #define LINK_SLIST(listhead, pentry, nextlink)			\
131abb0f93cSkardel do {								\
132abb0f93cSkardel 	(pentry)->nextlink = (listhead);			\
133abb0f93cSkardel 	(listhead) = (pentry);					\
134f003fb54Skardel } while (FALSE)
135abb0f93cSkardel 
136abb0f93cSkardel #define LINK_TAIL_SLIST(listhead, pentry, nextlink, entrytype)	\
137abb0f93cSkardel do {								\
138abb0f93cSkardel 	entrytype **pptail;					\
139abb0f93cSkardel 								\
140abb0f93cSkardel 	pptail = &(listhead);					\
141abb0f93cSkardel 	while (*pptail != NULL)					\
142abb0f93cSkardel 		pptail = &((*pptail)->nextlink);		\
143abb0f93cSkardel 								\
144abb0f93cSkardel 	(pentry)->nextlink = NULL;				\
145abb0f93cSkardel 	*pptail = (pentry);					\
146f003fb54Skardel } while (FALSE)
147f003fb54Skardel 
148f003fb54Skardel #define LINK_SORT_SLIST_CURRENT()	(*ppentry)
149f003fb54Skardel #define	L_S_S_CUR()			LINK_SORT_SLIST_CURRENT()
150f003fb54Skardel 
151f003fb54Skardel #define LINK_SORT_SLIST(listhead, pentry, beforecur, nextlink,	\
152f003fb54Skardel 			entrytype)				\
153f003fb54Skardel do {								\
154f003fb54Skardel 	entrytype **ppentry;					\
155f003fb54Skardel 								\
156f003fb54Skardel 	ppentry = &(listhead);					\
157f003fb54Skardel 	while (TRUE) {						\
158*9e9fa66aSchristos 		if (beforecur) {				\
159f003fb54Skardel 			(pentry)->nextlink = *ppentry;		\
160f003fb54Skardel 			*ppentry = (pentry);			\
161f003fb54Skardel 			break;					\
162f003fb54Skardel 		}						\
163f003fb54Skardel 		ppentry = &((*ppentry)->nextlink);		\
164f003fb54Skardel 		if (NULL == *ppentry) {				\
165f003fb54Skardel 			(pentry)->nextlink = NULL;		\
166f003fb54Skardel 			*ppentry = (pentry);			\
167f003fb54Skardel 			break;					\
168f003fb54Skardel 		}						\
169f003fb54Skardel 	}							\
170f003fb54Skardel } while (FALSE)
171abb0f93cSkardel 
172abb0f93cSkardel #define UNLINK_HEAD_SLIST(punlinked, listhead, nextlink)	\
173abb0f93cSkardel do {								\
174abb0f93cSkardel 	(punlinked) = (listhead);				\
175abb0f93cSkardel 	if (NULL != (punlinked)) {				\
176abb0f93cSkardel 		(listhead) = (punlinked)->nextlink;		\
177f003fb54Skardel 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
178abb0f93cSkardel 	}							\
179f003fb54Skardel } while (FALSE)
180f003fb54Skardel 
181f003fb54Skardel #define UNLINK_EXPR_SLIST_CURRENT()	(*ppentry)
182f003fb54Skardel #define	U_E_S_CUR()			UNLINK_EXPR_SLIST_CURRENT()
183abb0f93cSkardel 
184abb0f93cSkardel #define UNLINK_EXPR_SLIST(punlinked, listhead, expr, nextlink,	\
185abb0f93cSkardel 			  entrytype)				\
186eabc0478Schristos if (NULL != (listhead)) {					\
187abb0f93cSkardel 	entrytype **ppentry;					\
188abb0f93cSkardel 								\
189abb0f93cSkardel 	ppentry = &(listhead);					\
190abb0f93cSkardel 								\
191abb0f93cSkardel 	while (!(expr))						\
192f003fb54Skardel 		if (*ppentry != NULL &&				\
193f003fb54Skardel 		    (*ppentry)->nextlink != NULL) {		\
194abb0f93cSkardel 			ppentry = &((*ppentry)->nextlink);	\
195f003fb54Skardel 		} else {					\
196abb0f93cSkardel 			ppentry = NULL;				\
197abb0f93cSkardel 			break;					\
198abb0f93cSkardel 		}						\
199abb0f93cSkardel 								\
200abb0f93cSkardel 	if (ppentry != NULL) {					\
201abb0f93cSkardel 		(punlinked) = *ppentry;				\
202abb0f93cSkardel 		*ppentry = (punlinked)->nextlink;		\
203f003fb54Skardel 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
204f003fb54Skardel 	} else {						\
205abb0f93cSkardel 		(punlinked) = NULL;				\
206f003fb54Skardel 	}							\
207eabc0478Schristos } else do {							\
208eabc0478Schristos 	(punlinked) = NULL;					\
209f003fb54Skardel } while (FALSE)
210abb0f93cSkardel 
211abb0f93cSkardel #define UNLINK_SLIST(punlinked, listhead, ptounlink, nextlink,	\
212abb0f93cSkardel 		     entrytype)					\
213abb0f93cSkardel 	UNLINK_EXPR_SLIST(punlinked, listhead, (ptounlink) ==	\
214f003fb54Skardel 	    U_E_S_CUR(), nextlink, entrytype)
215f003fb54Skardel 
216f003fb54Skardel #define CHECK_SLIST(listhead, nextlink, entrytype)		\
217f003fb54Skardel do {								\
218f003fb54Skardel 	entrytype *pentry;					\
219f003fb54Skardel 								\
220f003fb54Skardel 	for (pentry = (listhead);				\
221f003fb54Skardel 	     pentry != NULL;					\
222f003fb54Skardel 	     pentry = pentry->nextlink) {			\
223af12ab5eSchristos 		INSIST(pentry != pentry->nextlink);		\
224af12ab5eSchristos 		INSIST((listhead) != pentry->nextlink);		\
225f003fb54Skardel 	}							\
226f003fb54Skardel } while (FALSE)
227f003fb54Skardel 
228f003fb54Skardel /*
229f003fb54Skardel  * FIFO
230f003fb54Skardel  */
231f003fb54Skardel 
232f003fb54Skardel #define DECL_FIFO_ANCHOR(entrytype)				\
233f003fb54Skardel struct {							\
234f003fb54Skardel 	entrytype *	phead;	/* NULL if list empty */	\
235f003fb54Skardel 	entrytype **	pptail;	/* NULL if list empty */	\
236f003fb54Skardel }
237f003fb54Skardel 
238f003fb54Skardel #define HEAD_FIFO(anchor)	((anchor).phead)
239f003fb54Skardel #define TAIL_FIFO(anchor)	((NULL == (anchor).pptail)	\
240f003fb54Skardel 					? NULL			\
241f003fb54Skardel 					: *((anchor).pptail))
242f003fb54Skardel 
243f003fb54Skardel /*
244f003fb54Skardel  * For DEBUG builds only, verify both or neither of the anchor pointers
245f003fb54Skardel  * are NULL with each operation.
246f003fb54Skardel  */
247f003fb54Skardel #if !defined(NTP_DEBUG_LISTS_H)
248f003fb54Skardel #define	CHECK_FIFO_CONSISTENCY(anchor)	do { } while (FALSE)
249f003fb54Skardel #else
250f003fb54Skardel #define	CHECK_FIFO_CONSISTENCY(anchor)				\
251f003fb54Skardel 	check_gen_fifo_consistency(&(anchor))
252f003fb54Skardel void	check_gen_fifo_consistency(void *fifo);
253f003fb54Skardel #endif
254f003fb54Skardel 
255f003fb54Skardel /*
256f003fb54Skardel  * generic FIFO element used to access any FIFO where each element
257f003fb54Skardel  * begins with the link pointer
258f003fb54Skardel  */
259f003fb54Skardel typedef struct gen_node_tag gen_node;
260f003fb54Skardel struct gen_node_tag {
261f003fb54Skardel 	gen_node *	link;
262f003fb54Skardel };
263f003fb54Skardel 
264f003fb54Skardel /* generic FIFO */
265f003fb54Skardel typedef DECL_FIFO_ANCHOR(gen_node) gen_fifo;
266f003fb54Skardel 
267f003fb54Skardel 
268f003fb54Skardel #define LINK_FIFO(anchor, pentry, nextlink)			\
269f003fb54Skardel do {								\
270f003fb54Skardel 	CHECK_FIFO_CONSISTENCY(anchor);				\
271f003fb54Skardel 								\
272f003fb54Skardel 	(pentry)->nextlink = NULL;				\
273f003fb54Skardel 	if (NULL != (anchor).pptail) {				\
274f003fb54Skardel 		(*((anchor).pptail))->nextlink = (pentry);	\
275f003fb54Skardel 		(anchor).pptail =				\
276f003fb54Skardel 		    &(*((anchor).pptail))->nextlink;		\
277f003fb54Skardel 	} else {						\
278f003fb54Skardel 		(anchor).phead = (pentry);			\
279f003fb54Skardel 		(anchor).pptail = &(anchor).phead;		\
280f003fb54Skardel 	}							\
281f003fb54Skardel 								\
282f003fb54Skardel 	CHECK_FIFO_CONSISTENCY(anchor);				\
283f003fb54Skardel } while (FALSE)
284f003fb54Skardel 
285f003fb54Skardel #define UNLINK_FIFO(punlinked, anchor, nextlink)		\
286f003fb54Skardel do {								\
287f003fb54Skardel 	CHECK_FIFO_CONSISTENCY(anchor);				\
288f003fb54Skardel 								\
289f003fb54Skardel 	(punlinked) = (anchor).phead;				\
290f003fb54Skardel 	if (NULL != (punlinked)) {				\
291f003fb54Skardel 		(anchor).phead = (punlinked)->nextlink;		\
292f003fb54Skardel 		if (NULL == (anchor).phead)			\
293f003fb54Skardel 			(anchor).pptail = NULL;			\
294f003fb54Skardel 		else if ((anchor).pptail ==			\
295f003fb54Skardel 			 &(punlinked)->nextlink)		\
296f003fb54Skardel 			(anchor).pptail = &(anchor).phead;	\
297f003fb54Skardel 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
298f003fb54Skardel 		CHECK_FIFO_CONSISTENCY(anchor);			\
299f003fb54Skardel 	}							\
300f003fb54Skardel } while (FALSE)
301f003fb54Skardel 
302f003fb54Skardel #define UNLINK_MID_FIFO(punlinked, anchor, tounlink, nextlink,	\
303f003fb54Skardel 			entrytype)				\
304f003fb54Skardel do {								\
305f003fb54Skardel 	entrytype **ppentry;					\
306f003fb54Skardel 								\
307f003fb54Skardel 	CHECK_FIFO_CONSISTENCY(anchor);				\
308f003fb54Skardel 								\
309f003fb54Skardel 	ppentry = &(anchor).phead;				\
310f003fb54Skardel 								\
311f003fb54Skardel 	while ((tounlink) != *ppentry)				\
312f003fb54Skardel 		if ((*ppentry)->nextlink != NULL) {		\
313f003fb54Skardel 			ppentry = &((*ppentry)->nextlink);	\
314f003fb54Skardel 		} else {					\
315f003fb54Skardel 			ppentry = NULL;				\
316f003fb54Skardel 			break;					\
317f003fb54Skardel 		}						\
318f003fb54Skardel 								\
319f003fb54Skardel 	if (ppentry != NULL) {					\
320f003fb54Skardel 		(punlinked) = *ppentry;				\
321f003fb54Skardel 		*ppentry = (punlinked)->nextlink;		\
322f003fb54Skardel 		if (NULL == *ppentry)				\
323f003fb54Skardel 			(anchor).pptail = NULL;			\
324f003fb54Skardel 		else if ((anchor).pptail ==			\
325f003fb54Skardel 			 &(punlinked)->nextlink)		\
326f003fb54Skardel 			(anchor).pptail = &(anchor).phead;	\
327f003fb54Skardel 		MAYBE_Z_LISTS((punlinked)->nextlink);		\
328f003fb54Skardel 		CHECK_FIFO_CONSISTENCY(anchor);			\
329f003fb54Skardel 	} else {						\
330f003fb54Skardel 		(punlinked) = NULL;				\
331f003fb54Skardel 	}							\
332f003fb54Skardel } while (FALSE)
333f003fb54Skardel 
334f003fb54Skardel #define CONCAT_FIFO(f1, f2, nextlink)				\
335f003fb54Skardel do {								\
336f003fb54Skardel 	CHECK_FIFO_CONSISTENCY(f1);				\
337f003fb54Skardel 	CHECK_FIFO_CONSISTENCY(f2);				\
338f003fb54Skardel 								\
339f003fb54Skardel 	if ((f2).pptail != NULL) {				\
340f003fb54Skardel 		if ((f1).pptail != NULL) {			\
341f003fb54Skardel 			(*(f1).pptail)->nextlink = (f2).phead;	\
342f003fb54Skardel 			if ((f2).pptail == &(f2).phead)		\
343f003fb54Skardel 				(f1).pptail =			\
344f003fb54Skardel 				    &(*(f1).pptail)->nextlink;	\
345f003fb54Skardel 			else					\
346f003fb54Skardel 				(f1).pptail = (f2).pptail;	\
347f003fb54Skardel 			CHECK_FIFO_CONSISTENCY(f1);		\
348f003fb54Skardel 		} else	{					\
349f003fb54Skardel 			(f1) = (f2);				\
350f003fb54Skardel 		}						\
351f003fb54Skardel 		MAYBE_Z_LISTS((f2).phead);			\
352f003fb54Skardel 		MAYBE_Z_LISTS((f2).pptail);			\
353f003fb54Skardel 	}							\
354f003fb54Skardel } while (FALSE)
355f003fb54Skardel 
356f003fb54Skardel /*
357f003fb54Skardel  * DLIST
358f003fb54Skardel  */
359f003fb54Skardel #define DECL_DLIST_LINK(entrytype, link)			\
360f003fb54Skardel struct {							\
361f003fb54Skardel 	entrytype *	b;					\
362f003fb54Skardel 	entrytype *	f;					\
363f003fb54Skardel } link
364f003fb54Skardel 
365f003fb54Skardel #define INIT_DLIST(listhead, link)				\
366f003fb54Skardel do {								\
367f003fb54Skardel 	(listhead).link.f = &(listhead);			\
368f003fb54Skardel 	(listhead).link.b = &(listhead);			\
369f003fb54Skardel } while (FALSE)
370f003fb54Skardel 
371f003fb54Skardel #define HEAD_DLIST(listhead, link)				\
372f003fb54Skardel 	(							\
373f003fb54Skardel 		(&(listhead) != (listhead).link.f)		\
374f003fb54Skardel 		    ? (listhead).link.f				\
375f003fb54Skardel 		    : NULL					\
376f003fb54Skardel 	)
377f003fb54Skardel 
378f003fb54Skardel #define TAIL_DLIST(listhead, link)				\
379f003fb54Skardel 	(							\
380f003fb54Skardel 		(&(listhead) != (listhead).link.b)		\
381f003fb54Skardel 		    ? (listhead).link.b				\
382f003fb54Skardel 		    : NULL					\
383f003fb54Skardel 	)
384f003fb54Skardel 
385f003fb54Skardel #define NEXT_DLIST(listhead, entry, link)			\
386f003fb54Skardel 	(							\
387f003fb54Skardel 		(&(listhead) != (entry)->link.f)		\
388f003fb54Skardel 		    ? (entry)->link.f				\
389f003fb54Skardel 		    : NULL					\
390f003fb54Skardel 	)
391f003fb54Skardel 
392f003fb54Skardel #define PREV_DLIST(listhead, entry, link)			\
393f003fb54Skardel 	(							\
394f003fb54Skardel 		(&(listhead) != (entry)->link.b)		\
395f003fb54Skardel 		    ? (entry)->link.b				\
396f003fb54Skardel 		    : NULL					\
397f003fb54Skardel 	)
398f003fb54Skardel 
399f003fb54Skardel #define LINK_DLIST(listhead, pentry, link)			\
400f003fb54Skardel do {								\
401f003fb54Skardel 	(pentry)->link.f = (listhead).link.f;			\
402f003fb54Skardel 	(pentry)->link.b = &(listhead);				\
403f003fb54Skardel 	(listhead).link.f->link.b = (pentry);			\
404f003fb54Skardel 	(listhead).link.f = (pentry);				\
405f003fb54Skardel } while (FALSE)
406f003fb54Skardel 
407f003fb54Skardel #define LINK_TAIL_DLIST(listhead, pentry, link)			\
408f003fb54Skardel do {								\
409f003fb54Skardel 	(pentry)->link.b = (listhead).link.b;			\
410f003fb54Skardel 	(pentry)->link.f = &(listhead);				\
411f003fb54Skardel 	(listhead).link.b->link.f = (pentry);			\
412f003fb54Skardel 	(listhead).link.b = (pentry);				\
413f003fb54Skardel } while (FALSE)
414f003fb54Skardel 
415f003fb54Skardel #define UNLINK_DLIST(ptounlink, link)				\
416f003fb54Skardel do {								\
417f003fb54Skardel 	(ptounlink)->link.b->link.f = (ptounlink)->link.f;	\
418f003fb54Skardel 	(ptounlink)->link.f->link.b = (ptounlink)->link.b;	\
419f003fb54Skardel 	MAYBE_Z_LISTS((ptounlink)->link.b);			\
420f003fb54Skardel 	MAYBE_Z_LISTS((ptounlink)->link.f);			\
421f003fb54Skardel } while (FALSE)
422f003fb54Skardel 
423f003fb54Skardel #define ITER_DLIST_BEGIN(listhead, iter, link, entrytype)	\
424f003fb54Skardel {								\
425f003fb54Skardel 	entrytype *i_dl_nextiter;				\
426f003fb54Skardel 								\
427f003fb54Skardel 	for ((iter) = (listhead).link.f;			\
428f003fb54Skardel 	     (iter) != &(listhead)				\
429f003fb54Skardel 	     && ((i_dl_nextiter = (iter)->link.f), TRUE);	\
430f003fb54Skardel 	     (iter) = i_dl_nextiter) {
431f003fb54Skardel #define ITER_DLIST_END()					\
432f003fb54Skardel 	}							\
433f003fb54Skardel }
434f003fb54Skardel 
435f003fb54Skardel #define REV_ITER_DLIST_BEGIN(listhead, iter, link, entrytype)	\
436f003fb54Skardel {								\
437f003fb54Skardel 	entrytype *i_dl_nextiter;				\
438f003fb54Skardel 								\
439f003fb54Skardel 	for ((iter) = (listhead).link.b;			\
440f003fb54Skardel 	     (iter) != &(listhead)				\
441f003fb54Skardel 	     && ((i_dl_nextiter = (iter)->link.b), TRUE);	\
442f003fb54Skardel 	     (iter) = i_dl_nextiter) {
443f003fb54Skardel #define REV_ITER_DLIST_END()					\
444f003fb54Skardel 	}							\
445f003fb54Skardel }
446abb0f93cSkardel 
447abb0f93cSkardel #endif	/* NTP_LISTS_H */
448