1 /*
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * modified for flow-tools to prevent conflicts with sys/queue.h on some
34  * systems.
35  *
36  *	@(#)queue.h	8.5 (Berkeley) 8/20/94
37  * $Id: ftqueue.h,v 1.2 2001/04/08 13:43:01 maf Exp $
38  */
39 
40 #ifndef _FT_QUEUE_H_
41 #define	_FT_QUEUE_H_
42 
43 /*
44  * This file defines five types of data structures: singly-linked lists,
45  * slingly-linked tail queues, lists, tail queues, and circular queues.
46  *
47  * A singly-linked list is headed by a single forward pointer. The elements
48  * are singly linked for minimum space and pointer manipulation overhead at
49  * the expense of O(n) removal for arbitrary elements. New elements can be
50  * added to the list after an existing element or at the head of the list.
51  * Elements being removed from the head of the list should use the explicit
52  * macro for this purpose for optimum efficiency. A singly-linked list may
53  * only be traversed in the forward direction.  Singly-linked lists are ideal
54  * for applications with large datasets and few or no removals or for
55  * implementing a LIFO queue.
56  *
57  * A singly-linked tail queue is headed by a pair of pointers, one to the
58  * head of the list and the other to the tail of the list. The elements are
59  * singly linked for minimum space and pointer manipulation overhead at the
60  * expense of O(n) removal for arbitrary elements. New elements can be added
61  * to the list after an existing element, at the head of the list, or at the
62  * end of the list. Elements being removed from the head of the tail queue
63  * should use the explicit macro for this purpose for optimum efficiency.
64  * A singly-linked tail queue may only be traversed in the forward direction.
65  * Singly-linked tail queues are ideal for applications with large datasets
66  * and few or no removals or for implementing a FIFO queue.
67  *
68  * A list is headed by a single forward pointer (or an array of forward
69  * pointers for a hash table header). The elements are doubly linked
70  * so that an arbitrary element can be removed without a need to
71  * traverse the list. New elements can be added to the list before
72  * or after an existing element or at the head of the list. A list
73  * may only be traversed in the forward direction.
74  *
75  * A tail queue is headed by a pair of pointers, one to the head of the
76  * list and the other to the tail of the list. The elements are doubly
77  * linked so that an arbitrary element can be removed without a need to
78  * traverse the list. New elements can be added to the list before or
79  * after an existing element, at the head of the list, or at the end of
80  * the list. A tail queue may only be traversed in the forward direction.
81  *
82  * A circle queue is headed by a pair of pointers, one to the head of the
83  * list and the other to the tail of the list. The elements are doubly
84  * linked so that an arbitrary element can be removed without a need to
85  * traverse the list. New elements can be added to the list before or after
86  * an existing element, at the head of the list, or at the end of the list.
87  * A circle queue may be traversed in either direction, but has a more
88  * complex end of list detection.
89  *
90  * For details on the use of these macros, see the queue(3) manual page.
91  *
92  *
93  *			SLIST	LIST	STAILQ	TAILQ	CIRCLEQ
94  * _HEAD		+	+	+	+	+
95  * _ENTRY		+	+	+	+	+
96  * _INIT		+	+	+	+	+
97  * _EMPTY		+	+	+	+	+
98  * _FIRST		+	+	-	+	+
99  * _NEXT		+	+	-	+	+
100  * _PREV		-	-	-	+	+
101  * _LAST		-	-	-	+	+
102  * _FOREACH		+	+	-	+	-
103  * _INSERT_HEAD		+	+	+	+	+
104  * _INSERT_BEFORE	-	+	-	+	+
105  * _INSERT_AFTER	+	+	+	+	+
106  * _INSERT_TAIL		-	-	+	+	+
107  * _REMOVE_HEAD		+	-	+	-	-
108  * _REMOVE		+	+	+	+	+
109  *
110  */
111 
112 /*
113  * Singly-linked List definitions.
114  */
115 #define FT_SLIST_HEAD(name, type)					\
116 struct name {								\
117 	struct type *slh_first;	/* first element */			\
118 }
119 
120 #define FT_SLIST_ENTRY(type)						\
121 struct {								\
122 	struct type *sle_next;	/* next element */			\
123 }
124 
125 /*
126  * Singly-linked List functions.
127  */
128 #define	FT_SLIST_EMPTY(head)	((head)->slh_first == NULL)
129 
130 #define	FT_SLIST_FIRST(head)	((head)->slh_first)
131 
132 #define FT_SLIST_FOREACH(var, head, field)				\
133 	for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
134 
135 #define FT_SLIST_INIT(head) {						\
136 	(head)->slh_first = NULL;					\
137 }
138 
139 #define FT_SLIST_INSERT_AFTER(slistelm, elm, field) do  {		\
140 	(elm)->field.sle_next = (slistelm)->field.sle_next;		\
141 	(slistelm)->field.sle_next = (elm);				\
142 } while (0)
143 
144 #define FT_SLIST_INSERT_HEAD(head, elm, field) do {			\
145 	(elm)->field.sle_next = (head)->slh_first;			\
146 	(head)->slh_first = (elm);					\
147 } while (0)
148 
149 #define FT_SLIST_NEXT(elm, field)	((elm)->field.sle_next)
150 
151 #define FT_SLIST_REMOVE_HEAD(head, field) do {				\
152 	(head)->slh_first = (head)->slh_first->field.sle_next;		\
153 } while (0)
154 
155 #define FT_SLIST_REMOVE(head, elm, type, field) do {			\
156 	if ((head)->slh_first == (elm)) {				\
157 		FT_SLIST_REMOVE_HEAD((head), field);			\
158 	}								\
159 	else {								\
160 		struct type *curelm = (head)->slh_first;		\
161 		while( curelm->field.sle_next != (elm) )		\
162 			curelm = curelm->field.sle_next;		\
163 		curelm->field.sle_next =				\
164 		    curelm->field.sle_next->field.sle_next;		\
165 	}								\
166 } while (0)
167 
168 /*
169  * Singly-linked Tail queue definitions.
170  */
171 #define FT_STAILQ_HEAD(name, type)					\
172 struct name {								\
173 	struct type *stqh_first;/* first element */			\
174 	struct type **stqh_last;/* addr of last next element */		\
175 }
176 
177 #define FT_STAILQ_ENTRY(type)						\
178 struct {								\
179 	struct type *stqe_next;	/* next element */			\
180 }
181 
182 /*
183  * Singly-linked Tail queue functions.
184  */
185 #define FT_STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
186 
187 #define	FT_STAILQ_INIT(head) do {					\
188 	(head)->stqh_first = NULL;					\
189 	(head)->stqh_last = &(head)->stqh_first;			\
190 } while (0)
191 
192 #define FT_STAILQ_FIRST(head)	((head)->stqh_first)
193 #define FT_STAILQ_LAST(head)	(*(head)->stqh_last)
194 
195 #define FT_STAILQ_INSERT_HEAD(head, elm, field) do {			\
196 	if (((elm)->field.stqe_next = (head)->stqh_first) == NULL)	\
197 		(head)->stqh_last = &(elm)->field.stqe_next;		\
198 	(head)->stqh_first = (elm);					\
199 } while (0)
200 
201 #define FT_STAILQ_INSERT_TAIL(head, elm, field) do {			\
202 	(elm)->field.stqe_next = NULL;					\
203 	*(head)->stqh_last = (elm);					\
204 	(head)->stqh_last = &(elm)->field.stqe_next;			\
205 } while (0)
206 
207 #define FT_STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
208 	if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
209 		(head)->stqh_last = &(elm)->field.stqe_next;		\
210 	(tqelm)->field.stqe_next = (elm);				\
211 } while (0)
212 
213 #define FT_STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
214 
215 #define FT_STAILQ_FOREACH(var, head, field)                    \
216 	for (var = FT_STAILQ_FIRST(head); var; var = FT_STAILQ_NEXT(var, field))
217 
218 #define FT_STAILQ_REMOVE_HEAD(head, field) do {				\
219 	if (((head)->stqh_first =					\
220 	     (head)->stqh_first->field.stqe_next) == NULL)		\
221 		(head)->stqh_last = &(head)->stqh_first;		\
222 } while (0)
223 
224 #define FT_STAILQ_REMOVE(head, elm, type, field) do {			\
225 	if ((head)->stqh_first == (elm)) {				\
226 		FT_STAILQ_REMOVE_HEAD(head, field);			\
227 	}								\
228 	else {								\
229 		struct type *curelm = (head)->stqh_first;		\
230 		while( curelm->field.stqe_next != (elm) )		\
231 			curelm = curelm->field.stqe_next;		\
232 		if((curelm->field.stqe_next =				\
233 		    curelm->field.stqe_next->field.stqe_next) == NULL)	\
234 			(head)->stqh_last = &(curelm)->field.stqe_next;	\
235 	}								\
236 } while (0)
237 
238 /*
239  * List definitions.
240  */
241 #define FT_LIST_HEAD(name, type)					\
242 struct name {								\
243 	struct type *lh_first;	/* first element */			\
244 }
245 
246 #define FT_LIST_ENTRY(type)						\
247 struct {								\
248 	struct type *le_next;	/* next element */			\
249 	struct type **le_prev;	/* address of previous next element */	\
250 }
251 
252 /*
253  * List functions.
254  */
255 
256 #define	FT_LIST_EMPTY(head) ((head)->lh_first == NULL)
257 
258 #define FT_LIST_FIRST(head)	((head)->lh_first)
259 
260 #define FT_LIST_FOREACH(var, head, field)				\
261 	for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
262 
263 #define	FT_LIST_INIT(head) do {						\
264 	(head)->lh_first = NULL;					\
265 } while (0)
266 
267 #define FT_LIST_INSERT_AFTER(listelm, elm, field) do {			\
268 	if (((elm)->field.le_next = (listelm)->field.le_next) != NULL)	\
269 		(listelm)->field.le_next->field.le_prev =		\
270 		    &(elm)->field.le_next;				\
271 	(listelm)->field.le_next = (elm);				\
272 	(elm)->field.le_prev = &(listelm)->field.le_next;		\
273 } while (0)
274 
275 #define FT_LIST_INSERT_BEFORE(listelm, elm, field) do {			\
276 	(elm)->field.le_prev = (listelm)->field.le_prev;		\
277 	(elm)->field.le_next = (listelm);				\
278 	*(listelm)->field.le_prev = (elm);				\
279 	(listelm)->field.le_prev = &(elm)->field.le_next;		\
280 } while (0)
281 
282 #define FT_LIST_INSERT_HEAD(head, elm, field) do {			\
283 	if (((elm)->field.le_next = (head)->lh_first) != NULL)		\
284 		(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
285 	(head)->lh_first = (elm);					\
286 	(elm)->field.le_prev = &(head)->lh_first;			\
287 } while (0)
288 
289 #define FT_LIST_NEXT(elm, field)	((elm)->field.le_next)
290 
291 #define FT_LIST_REMOVE(elm, field) do {					\
292 	if ((elm)->field.le_next != NULL)				\
293 		(elm)->field.le_next->field.le_prev = 			\
294 		    (elm)->field.le_prev;				\
295 	*(elm)->field.le_prev = (elm)->field.le_next;			\
296 } while (0)
297 
298 /*
299  * Tail queue definitions.
300  */
301 #define FT_TAILQ_HEAD(name, type)					\
302 struct name {								\
303 	struct type *tqh_first;	/* first element */			\
304 	struct type **tqh_last;	/* addr of last next element */		\
305 }
306 
307 #define FT_TAILQ_HEAD_INITIALIZER(head)					\
308 	{ NULL, &(head).tqh_first }
309 
310 #define FT_TAILQ_ENTRY(type)						\
311 struct {								\
312 	struct type *tqe_next;	/* next element */			\
313 	struct type **tqe_prev;	/* address of previous next element */	\
314 }
315 
316 /*
317  * Tail queue functions.
318  */
319 #define	FT_TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
320 
321 #define FT_TAILQ_FOREACH(var, head, field)				\
322 	for (var = FT_TAILQ_FIRST(head); var; var = FT_TAILQ_NEXT(var, field))
323 
324 #define	FT_TAILQ_FIRST(head) ((head)->tqh_first)
325 
326 #define	FT_TAILQ_LAST(head, headname) \
327 	(*(((struct headname *)((head)->tqh_last))->tqh_last))
328 
329 #define	FT_TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
330 
331 #define FT_TAILQ_PREV(elm, headname, field) \
332 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
333 
334 #define	FT_TAILQ_INIT(head) do {					\
335 	(head)->tqh_first = NULL;					\
336 	(head)->tqh_last = &(head)->tqh_first;				\
337 } while (0)
338 
339 #define FT_TAILQ_INSERT_HEAD(head, elm, field) do {			\
340 	if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)	\
341 		(head)->tqh_first->field.tqe_prev =			\
342 		    &(elm)->field.tqe_next;				\
343 	else								\
344 		(head)->tqh_last = &(elm)->field.tqe_next;		\
345 	(head)->tqh_first = (elm);					\
346 	(elm)->field.tqe_prev = &(head)->tqh_first;			\
347 } while (0)
348 
349 #define FT_TAILQ_INSERT_TAIL(head, elm, field) do {			\
350 	(elm)->field.tqe_next = NULL;					\
351 	(elm)->field.tqe_prev = (head)->tqh_last;			\
352 	*(head)->tqh_last = (elm);					\
353 	(head)->tqh_last = &(elm)->field.tqe_next;			\
354 } while (0)
355 
356 #define FT_TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
357 	if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
358 		(elm)->field.tqe_next->field.tqe_prev = 		\
359 		    &(elm)->field.tqe_next;				\
360 	else								\
361 		(head)->tqh_last = &(elm)->field.tqe_next;		\
362 	(listelm)->field.tqe_next = (elm);				\
363 	(elm)->field.tqe_prev = &(listelm)->field.tqe_next;		\
364 } while (0)
365 
366 #define FT_TAILQ_INSERT_BEFORE(listelm, elm, field) do {		\
367 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
368 	(elm)->field.tqe_next = (listelm);				\
369 	*(listelm)->field.tqe_prev = (elm);				\
370 	(listelm)->field.tqe_prev = &(elm)->field.tqe_next;		\
371 } while (0)
372 
373 #define FT_TAILQ_REMOVE(head, elm, field) do {				\
374 	if (((elm)->field.tqe_next) != NULL)				\
375 		(elm)->field.tqe_next->field.tqe_prev = 		\
376 		    (elm)->field.tqe_prev;				\
377 	else								\
378 		(head)->tqh_last = (elm)->field.tqe_prev;		\
379 	*(elm)->field.tqe_prev = (elm)->field.tqe_next;			\
380 } while (0)
381 
382 /*
383  * Circular queue definitions.
384  */
385 #define FT_CIRCLEQ_HEAD(name, type)					\
386 struct name {								\
387 	struct type *cqh_first;		/* first element */		\
388 	struct type *cqh_last;		/* last element */		\
389 }
390 
391 #define FT_CIRCLEQ_ENTRY(type)						\
392 struct {								\
393 	struct type *cqe_next;		/* next element */		\
394 	struct type *cqe_prev;		/* previous element */		\
395 }
396 
397 /*
398  * Circular queue functions.
399  */
400 #define FT_CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
401 
402 #define FT_CIRCLEQ_FIRST(head) ((head)->cqh_first)
403 
404 #define FT_CIRCLEQ_FOREACH(var, head, field)				\
405 	for((var) = (head)->cqh_first;					\
406 	    (var) != (void *)(head);					\
407 	    (var) = (var)->field.cqe_next)
408 
409 #define	FT_CIRCLEQ_INIT(head) do {					\
410 	(head)->cqh_first = (void *)(head);				\
411 	(head)->cqh_last = (void *)(head);				\
412 } while (0)
413 
414 #define FT_CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
415 	(elm)->field.cqe_next = (listelm)->field.cqe_next;		\
416 	(elm)->field.cqe_prev = (listelm);				\
417 	if ((listelm)->field.cqe_next == (void *)(head))		\
418 		(head)->cqh_last = (elm);				\
419 	else								\
420 		(listelm)->field.cqe_next->field.cqe_prev = (elm);	\
421 	(listelm)->field.cqe_next = (elm);				\
422 } while (0)
423 
424 #define FT_CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {	\
425 	(elm)->field.cqe_next = (listelm);				\
426 	(elm)->field.cqe_prev = (listelm)->field.cqe_prev;		\
427 	if ((listelm)->field.cqe_prev == (void *)(head))		\
428 		(head)->cqh_first = (elm);				\
429 	else								\
430 		(listelm)->field.cqe_prev->field.cqe_next = (elm);	\
431 	(listelm)->field.cqe_prev = (elm);				\
432 } while (0)
433 
434 #define FT_CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
435 	(elm)->field.cqe_next = (head)->cqh_first;			\
436 	(elm)->field.cqe_prev = (void *)(head);				\
437 	if ((head)->cqh_last == (void *)(head))				\
438 		(head)->cqh_last = (elm);				\
439 	else								\
440 		(head)->cqh_first->field.cqe_prev = (elm);		\
441 	(head)->cqh_first = (elm);					\
442 } while (0)
443 
444 #define FT_CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
445 	(elm)->field.cqe_next = (void *)(head);				\
446 	(elm)->field.cqe_prev = (head)->cqh_last;			\
447 	if ((head)->cqh_first == (void *)(head))			\
448 		(head)->cqh_first = (elm);				\
449 	else								\
450 		(head)->cqh_last->field.cqe_next = (elm);		\
451 	(head)->cqh_last = (elm);					\
452 } while (0)
453 
454 #define FT_CIRCLEQ_LAST(head) ((head)->cqh_last)
455 
456 #define FT_CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
457 
458 #define FT_CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
459 
460 #define	FT_CIRCLEQ_REMOVE(head, elm, field) do {			\
461 	if ((elm)->field.cqe_next == (void *)(head))			\
462 		(head)->cqh_last = (elm)->field.cqe_prev;		\
463 	else								\
464 		(elm)->field.cqe_next->field.cqe_prev =			\
465 		    (elm)->field.cqe_prev;				\
466 	if ((elm)->field.cqe_prev == (void *)(head))			\
467 		(head)->cqh_first = (elm)->field.cqe_next;		\
468 	else								\
469 		(elm)->field.cqe_prev->field.cqe_next =			\
470 		    (elm)->field.cqe_next;				\
471 } while (0)
472 
473 #ifdef KERNEL
474 
475 /*
476  * XXX insque() and remque() are an old way of handling certain queues.
477  * They bogusly assumes that all queue heads look alike.
478  */
479 
480 struct quehead {
481 	struct quehead *qh_link;
482 	struct quehead *qh_rlink;
483 };
484 
485 #ifdef	__GNUC__
486 
487 static __inline void
insque(void * a,void * b)488 insque(void *a, void *b)
489 {
490 	struct quehead *element = a, *head = b;
491 
492 	element->qh_link = head->qh_link;
493 	element->qh_rlink = head;
494 	head->qh_link = element;
495 	element->qh_link->qh_rlink = element;
496 }
497 
498 static __inline void
remque(void * a)499 remque(void *a)
500 {
501 	struct quehead *element = a;
502 
503 	element->qh_link->qh_rlink = element->qh_rlink;
504 	element->qh_rlink->qh_link = element->qh_link;
505 	element->qh_rlink = 0;
506 }
507 
508 #else /* !__GNUC__ */
509 
510 void	insque __P((void *a, void *b));
511 void	remque __P((void *a));
512 
513 #endif /* __GNUC__ */
514 
515 #endif /* KERNEL */
516 
517 #endif /* !_FT_QUEUE_H_ */
518