]>
git.saurik.com Git - apple/xnu.git/blob - bsd/sys/queue.h
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (c) 1991, 1993
24 * The Regents of the University of California. All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions
29 * 1. Redistributions of source code must retain the above copyright
30 * notice, this list of conditions and the following disclaimer.
31 * 2. Redistributions in binary form must reproduce the above copyright
32 * notice, this list of conditions and the following disclaimer in the
33 * documentation and/or other materials provided with the distribution.
34 * 3. All advertising materials mentioning features or use of this software
35 * must display the following acknowledgement:
36 * This product includes software developed by the University of
37 * California, Berkeley and its contributors.
38 * 4. Neither the name of the University nor the names of its contributors
39 * may be used to endorse or promote products derived from this software
40 * without specific prior written permission.
42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * @(#)queue.h 8.5 (Berkeley) 8/20/94
61 * This file defines five types of data structures: singly-linked lists,
62 * slingly-linked tail queues, lists, tail queues, and circular queues.
64 * A singly-linked list is headed by a single forward pointer. The elements
65 * are singly linked for minimum space and pointer manipulation overhead at
66 * the expense of O(n) removal for arbitrary elements. New elements can be
67 * added to the list after an existing element or at the head of the list.
68 * Elements being removed from the head of the list should use the explicit
69 * macro for this purpose for optimum efficiency. A singly-linked list may
70 * only be traversed in the forward direction. Singly-linked lists are ideal
71 * for applications with large datasets and few or no removals or for
72 * implementing a LIFO queue.
74 * A singly-linked tail queue is headed by a pair of pointers, one to the
75 * head of the list and the other to the tail of the list. The elements are
76 * singly linked for minimum space and pointer manipulation overhead at the
77 * expense of O(n) removal for arbitrary elements. New elements can be added
78 * to the list after an existing element, at the head of the list, or at the
79 * end of the list. Elements being removed from the head of the tail queue
80 * should use the explicit macro for this purpose for optimum efficiency.
81 * A singly-linked tail queue may only be traversed in the forward direction.
82 * Singly-linked tail queues are ideal for applications with large datasets
83 * and few or no removals or for implementing a FIFO queue.
85 * A list is headed by a single forward pointer (or an array of forward
86 * pointers for a hash table header). The elements are doubly linked
87 * so that an arbitrary element can be removed without a need to
88 * traverse the list. New elements can be added to the list before
89 * or after an existing element or at the head of the list. A list
90 * may only be traversed in the forward direction.
92 * A tail queue is headed by a pair of pointers, one to the head of the
93 * list and the other to the tail of the list. The elements are doubly
94 * linked so that an arbitrary element can be removed without a need to
95 * traverse the list. New elements can be added to the list before or
96 * after an existing element, at the head of the list, or at the end of
97 * the list. A tail queue may only be traversed in the forward direction.
99 * A circle queue is headed by a pair of pointers, one to the head of the
100 * list and the other to the tail of the list. The elements are doubly
101 * linked so that an arbitrary element can be removed without a need to
102 * traverse the list. New elements can be added to the list before or after
103 * an existing element, at the head of the list, or at the end of the list.
104 * A circle queue may be traversed in either direction, but has a more
105 * complex end of list detection.
107 * For details on the use of these macros, see the queue(3) manual page.
110 * SLIST LIST STAILQ TAILQ CIRCLEQ
120 * _INSERT_HEAD + + + + +
121 * _INSERT_BEFORE - + - + +
122 * _INSERT_AFTER + + + + +
123 * _INSERT_TAIL - - + + +
124 * _REMOVE_HEAD + - + - -
130 * Singly-linked List definitions.
132 #define SLIST_HEAD(name, type) \
134 struct type *slh_first; /* first element */ \
137 #define SLIST_ENTRY(type) \
139 struct type *sle_next; /* next element */ \
143 * Singly-linked List functions.
145 #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
147 #define SLIST_FIRST(head) ((head)->slh_first)
149 #define SLIST_FOREACH(var, head, field) \
150 for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
152 #define SLIST_INIT(head) { \
153 (head)->slh_first = NULL; \
156 #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
157 (elm)->field.sle_next = (slistelm)->field.sle_next; \
158 (slistelm)->field.sle_next = (elm); \
161 #define SLIST_INSERT_HEAD(head, elm, field) do { \
162 (elm)->field.sle_next = (head)->slh_first; \
163 (head)->slh_first = (elm); \
166 #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
168 #define SLIST_REMOVE_HEAD(head, field) do { \
169 (head)->slh_first = (head)->slh_first->field.sle_next; \
172 #define SLIST_REMOVE(head, elm, type, field) do { \
173 if ((head)->slh_first == (elm)) { \
174 SLIST_REMOVE_HEAD((head), field); \
177 struct type *curelm = (head)->slh_first; \
178 while( curelm->field.sle_next != (elm) ) \
179 curelm = curelm->field.sle_next; \
180 curelm->field.sle_next = \
181 curelm->field.sle_next->field.sle_next; \
186 * Singly-linked Tail queue definitions.
188 #define STAILQ_HEAD(name, type) \
190 struct type *stqh_first;/* first element */ \
191 struct type **stqh_last;/* addr of last next element */ \
194 #define STAILQ_HEAD_INITIALIZER(head) \
195 { NULL, &(head).stqh_first }
197 #define STAILQ_ENTRY(type) \
199 struct type *stqe_next; /* next element */ \
203 * Singly-linked Tail queue functions.
205 #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
207 #define STAILQ_INIT(head) do { \
208 (head)->stqh_first = NULL; \
209 (head)->stqh_last = &(head)->stqh_first; \
212 #define STAILQ_FIRST(head) ((head)->stqh_first)
213 #define STAILQ_LAST(head) (*(head)->stqh_last)
215 #define STAILQ_INSERT_HEAD(head, elm, field) do { \
216 if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
217 (head)->stqh_last = &(elm)->field.stqe_next; \
218 (head)->stqh_first = (elm); \
221 #define STAILQ_INSERT_TAIL(head, elm, field) do { \
222 (elm)->field.stqe_next = NULL; \
223 *(head)->stqh_last = (elm); \
224 (head)->stqh_last = &(elm)->field.stqe_next; \
227 #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
228 if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
229 (head)->stqh_last = &(elm)->field.stqe_next; \
230 (tqelm)->field.stqe_next = (elm); \
233 #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
235 #define STAILQ_REMOVE_HEAD(head, field) do { \
236 if (((head)->stqh_first = \
237 (head)->stqh_first->field.stqe_next) == NULL) \
238 (head)->stqh_last = &(head)->stqh_first; \
241 #define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
242 if (((head)->stqh_first = (elm)->field.stqe_next) == NULL) \
243 (head)->stqh_last = &(head)->stqh_first; \
247 #define STAILQ_REMOVE(head, elm, type, field) do { \
248 if ((head)->stqh_first == (elm)) { \
249 STAILQ_REMOVE_HEAD(head, field); \
252 struct type *curelm = (head)->stqh_first; \
253 while( curelm->field.stqe_next != (elm) ) \
254 curelm = curelm->field.stqe_next; \
255 if((curelm->field.stqe_next = \
256 curelm->field.stqe_next->field.stqe_next) == NULL) \
257 (head)->stqh_last = &(curelm)->field.stqe_next; \
264 #define LIST_HEAD(name, type) \
266 struct type *lh_first; /* first element */ \
269 #define LIST_HEAD_INITIALIZER(head) \
272 #define LIST_ENTRY(type) \
274 struct type *le_next; /* next element */ \
275 struct type **le_prev; /* address of previous next element */ \
282 #define LIST_EMPTY(head) ((head)->lh_first == NULL)
284 #define LIST_FIRST(head) ((head)->lh_first)
286 #define LIST_FOREACH(var, head, field) \
287 for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
289 #define LIST_INIT(head) do { \
290 (head)->lh_first = NULL; \
293 #define LIST_INSERT_AFTER(listelm, elm, field) do { \
294 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
295 (listelm)->field.le_next->field.le_prev = \
296 &(elm)->field.le_next; \
297 (listelm)->field.le_next = (elm); \
298 (elm)->field.le_prev = &(listelm)->field.le_next; \
301 #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
302 (elm)->field.le_prev = (listelm)->field.le_prev; \
303 (elm)->field.le_next = (listelm); \
304 *(listelm)->field.le_prev = (elm); \
305 (listelm)->field.le_prev = &(elm)->field.le_next; \
308 #define LIST_INSERT_HEAD(head, elm, field) do { \
309 if (((elm)->field.le_next = (head)->lh_first) != NULL) \
310 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
311 (head)->lh_first = (elm); \
312 (elm)->field.le_prev = &(head)->lh_first; \
315 #define LIST_NEXT(elm, field) ((elm)->field.le_next)
317 #define LIST_REMOVE(elm, field) do { \
318 if ((elm)->field.le_next != NULL) \
319 (elm)->field.le_next->field.le_prev = \
320 (elm)->field.le_prev; \
321 *(elm)->field.le_prev = (elm)->field.le_next; \
325 * Tail queue definitions.
327 #define TAILQ_HEAD(name, type) \
329 struct type *tqh_first; /* first element */ \
330 struct type **tqh_last; /* addr of last next element */ \
333 #define TAILQ_HEAD_INITIALIZER(head) \
334 { NULL, &(head).tqh_first }
336 #define TAILQ_ENTRY(type) \
338 struct type *tqe_next; /* next element */ \
339 struct type **tqe_prev; /* address of previous next element */ \
343 * Tail queue functions.
345 #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
347 #define TAILQ_FOREACH(var, head, field) \
348 for (var = TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))
350 #define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
351 for (var = TAILQ_LAST(head, headname); \
352 var; var = TAILQ_PREV(var, headname, field))
354 #define TAILQ_FIRST(head) ((head)->tqh_first)
356 #define TAILQ_LAST(head, headname) \
357 (*(((struct headname *)((head)->tqh_last))->tqh_last))
359 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
361 #define TAILQ_PREV(elm, headname, field) \
362 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
364 #define TAILQ_INIT(head) do { \
365 (head)->tqh_first = NULL; \
366 (head)->tqh_last = &(head)->tqh_first; \
369 #define TAILQ_INSERT_HEAD(head, elm, field) do { \
370 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
371 (head)->tqh_first->field.tqe_prev = \
372 &(elm)->field.tqe_next; \
374 (head)->tqh_last = &(elm)->field.tqe_next; \
375 (head)->tqh_first = (elm); \
376 (elm)->field.tqe_prev = &(head)->tqh_first; \
379 #define TAILQ_INSERT_TAIL(head, elm, field) do { \
380 (elm)->field.tqe_next = NULL; \
381 (elm)->field.tqe_prev = (head)->tqh_last; \
382 *(head)->tqh_last = (elm); \
383 (head)->tqh_last = &(elm)->field.tqe_next; \
386 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
387 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
388 (elm)->field.tqe_next->field.tqe_prev = \
389 &(elm)->field.tqe_next; \
391 (head)->tqh_last = &(elm)->field.tqe_next; \
392 (listelm)->field.tqe_next = (elm); \
393 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
396 #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
397 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
398 (elm)->field.tqe_next = (listelm); \
399 *(listelm)->field.tqe_prev = (elm); \
400 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
403 #define TAILQ_REMOVE(head, elm, field) do { \
404 if (((elm)->field.tqe_next) != NULL) \
405 (elm)->field.tqe_next->field.tqe_prev = \
406 (elm)->field.tqe_prev; \
408 (head)->tqh_last = (elm)->field.tqe_prev; \
409 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
413 * Circular queue definitions.
415 #define CIRCLEQ_HEAD(name, type) \
417 struct type *cqh_first; /* first element */ \
418 struct type *cqh_last; /* last element */ \
421 #define CIRCLEQ_ENTRY(type) \
423 struct type *cqe_next; /* next element */ \
424 struct type *cqe_prev; /* previous element */ \
428 * Circular queue functions.
430 #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
432 #define CIRCLEQ_FIRST(head) ((head)->cqh_first)
434 #define CIRCLEQ_FOREACH(var, head, field) \
435 for((var) = (head)->cqh_first; \
436 (var) != (void *)(head); \
437 (var) = (var)->field.cqe_next)
439 #define CIRCLEQ_INIT(head) do { \
440 (head)->cqh_first = (void *)(head); \
441 (head)->cqh_last = (void *)(head); \
444 #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
445 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
446 (elm)->field.cqe_prev = (listelm); \
447 if ((listelm)->field.cqe_next == (void *)(head)) \
448 (head)->cqh_last = (elm); \
450 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
451 (listelm)->field.cqe_next = (elm); \
454 #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
455 (elm)->field.cqe_next = (listelm); \
456 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
457 if ((listelm)->field.cqe_prev == (void *)(head)) \
458 (head)->cqh_first = (elm); \
460 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
461 (listelm)->field.cqe_prev = (elm); \
464 #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
465 (elm)->field.cqe_next = (head)->cqh_first; \
466 (elm)->field.cqe_prev = (void *)(head); \
467 if ((head)->cqh_last == (void *)(head)) \
468 (head)->cqh_last = (elm); \
470 (head)->cqh_first->field.cqe_prev = (elm); \
471 (head)->cqh_first = (elm); \
474 #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
475 (elm)->field.cqe_next = (void *)(head); \
476 (elm)->field.cqe_prev = (head)->cqh_last; \
477 if ((head)->cqh_first == (void *)(head)) \
478 (head)->cqh_first = (elm); \
480 (head)->cqh_last->field.cqe_next = (elm); \
481 (head)->cqh_last = (elm); \
484 #define CIRCLEQ_LAST(head) ((head)->cqh_last)
486 #define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
488 #define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
490 #define CIRCLEQ_REMOVE(head, elm, field) do { \
491 if ((elm)->field.cqe_next == (void *)(head)) \
492 (head)->cqh_last = (elm)->field.cqe_prev; \
494 (elm)->field.cqe_next->field.cqe_prev = \
495 (elm)->field.cqe_prev; \
496 if ((elm)->field.cqe_prev == (void *)(head)) \
497 (head)->cqh_first = (elm)->field.cqe_next; \
499 (elm)->field.cqe_prev->field.cqe_next = \
500 (elm)->field.cqe_next; \
508 * XXX insque() and remque() are an old way of handling certain queues.
509 * They bogusly assumes that all queue heads look alike.
513 struct quehead
*qh_link
;
514 struct quehead
*qh_rlink
;
520 insque(void *a
, void *b
)
522 struct quehead
*element
= a
, *head
= b
;
524 element
->qh_link
= head
->qh_link
;
525 element
->qh_rlink
= head
;
526 head
->qh_link
= element
;
527 element
->qh_link
->qh_rlink
= element
;
533 struct quehead
*element
= a
;
535 element
->qh_link
->qh_rlink
= element
->qh_rlink
;
536 element
->qh_rlink
->qh_link
= element
->qh_link
;
537 element
->qh_rlink
= 0;
540 #else /* !__GNUC__ */
542 void insque
__P((void *a
, void *b
));
543 void remque
__P((void *a
));
545 #endif /* __GNUC__ */
550 #endif /* !_SYS_QUEUE_H_ */