master
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*-
29 * Copyright (c) 1991, 1993
30 * The Regents of the University of California. All rights reserved.
31 *
32 * Redistribution and use in source and binary forms, with or without
33 * modification, are permitted provided that the following conditions
34 * are met:
35 * 1. Redistributions of source code must retain the above copyright
36 * notice, this list of conditions and the following disclaimer.
37 * 2. Redistributions in binary form must reproduce the above copyright
38 * notice, this list of conditions and the following disclaimer in the
39 * documentation and/or other materials provided with the distribution.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 *
56 * @(#)queue.h 8.5 (Berkeley) 8/20/94
57 */
58
59#ifndef _SYS_QUEUE_H_
60#define _SYS_QUEUE_H_
61
62#ifndef __improbable
63#define __improbable(x) (x) /* noop in userspace */
64#endif /* __improbable */
65
66/*
67 * This file defines five types of data structures: singly-linked lists,
68 * singly-linked tail queues, lists, tail queues, and circular queues.
69 *
70 * A singly-linked list is headed by a single forward pointer. The elements
71 * are singly linked for minimum space and pointer manipulation overhead at
72 * the expense of O(n) removal for arbitrary elements. New elements can be
73 * added to the list after an existing element or at the head of the list.
74 * Elements being removed from the head of the list should use the explicit
75 * macro for this purpose for optimum efficiency. A singly-linked list may
76 * only be traversed in the forward direction. Singly-linked lists are ideal
77 * for applications with large datasets and few or no removals or for
78 * implementing a LIFO queue.
79 *
80 * A singly-linked tail queue is headed by a pair of pointers, one to the
81 * head of the list and the other to the tail of the list. The elements are
82 * singly linked for minimum space and pointer manipulation overhead at the
83 * expense of O(n) removal for arbitrary elements. New elements can be added
84 * to the list after an existing element, at the head of the list, or at the
85 * end of the list. Elements being removed from the head of the tail queue
86 * should use the explicit macro for this purpose for optimum efficiency.
87 * A singly-linked tail queue may only be traversed in the forward direction.
88 * Singly-linked tail queues are ideal for applications with large datasets
89 * and few or no removals or for implementing a FIFO queue.
90 *
91 * A list is headed by a single forward pointer (or an array of forward
92 * pointers for a hash table header). The elements are doubly linked
93 * so that an arbitrary element can be removed without a need to
94 * traverse the list. New elements can be added to the list before
95 * or after an existing element or at the head of the list. A list
96 * may only be traversed in the forward direction.
97 *
98 * A tail queue is headed by a pair of pointers, one to the head of the
99 * list and the other to the tail of the list. The elements are doubly
100 * linked so that an arbitrary element can be removed without a need to
101 * traverse the list. New elements can be added to the list before or
102 * after an existing element, at the head of the list, or at the end of
103 * the list. A tail queue may be traversed in either direction.
104 *
105 * A circle queue is headed by a pair of pointers, one to the head of the
106 * list and the other to the tail of the list. The elements are doubly
107 * linked so that an arbitrary element can be removed without a need to
108 * traverse the list. New elements can be added to the list before or after
109 * an existing element, at the head of the list, or at the end of the list.
110 * A circle queue may be traversed in either direction, but has a more
111 * complex end of list detection.
112 * Note that circle queues are deprecated, because, as the removal log
113 * in FreeBSD states, "CIRCLEQs are a disgrace to everything Knuth taught
114 * us in Volume 1 Chapter 2. [...] Use TAILQ instead, it provides the same
115 * functionality." Code using them will continue to compile, but they
116 * are no longer documented on the man page.
117 *
118 * For details on the use of these macros, see the queue(3) manual page.
119 *
120 *
121 * SLIST LIST STAILQ TAILQ CIRCLEQ
122 * _HEAD + + + + +
123 * _HEAD_INITIALIZER + + + + -
124 * _ENTRY + + + + +
125 * _INIT + + + + +
126 * _EMPTY + + + + +
127 * _FIRST + + + + +
128 * _NEXT + + + + +
129 * _PREV - - - + +
130 * _LAST - - + + +
131 * _FOREACH + + + + +
132 * _FOREACH_SAFE + + + + -
133 * _FOREACH_REVERSE - - - + -
134 * _FOREACH_REVERSE_SAFE - - - + -
135 * _INSERT_HEAD + + + + +
136 * _INSERT_BEFORE - + - + +
137 * _INSERT_AFTER + + + + +
138 * _INSERT_TAIL - - + + +
139 * _CONCAT - - + + -
140 * _REMOVE_AFTER + - + - -
141 * _REMOVE_HEAD + - + - -
142 * _REMOVE_HEAD_UNTIL - - + - -
143 * _REMOVE + + + + +
144 * _SWAP - + + + -
145 *
146 */
147#ifdef QUEUE_MACRO_DEBUG
148/* Store the last 2 places the queue element or head was altered */
149struct qm_trace {
150 char * lastfile;
151 int lastline;
152 char * prevfile;
153 int prevline;
154};
155
156#define TRACEBUF struct qm_trace trace;
157#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
158
159#define QMD_TRACE_HEAD(head) do { \
160 (head)->trace.prevline = (head)->trace.lastline; \
161 (head)->trace.prevfile = (head)->trace.lastfile; \
162 (head)->trace.lastline = __LINE__; \
163 (head)->trace.lastfile = __FILE__; \
164} while (0)
165
166#define QMD_TRACE_ELEM(elem) do { \
167 (elem)->trace.prevline = (elem)->trace.lastline; \
168 (elem)->trace.prevfile = (elem)->trace.lastfile; \
169 (elem)->trace.lastline = __LINE__; \
170 (elem)->trace.lastfile = __FILE__; \
171} while (0)
172
173#else
174#define QMD_TRACE_ELEM(elem)
175#define QMD_TRACE_HEAD(head)
176#define TRACEBUF
177#define TRASHIT(x)
178#endif /* QUEUE_MACRO_DEBUG */
179
180/*
181 * Horrible macros to enable use of code that was meant to be C-specific
182 * (and which push struct onto type) in C++; without these, C++ code
183 * that uses these macros in the context of a class will blow up
184 * due to "struct" being preprended to "type" by the macros, causing
185 * inconsistent use of tags.
186 *
187 * This approach is necessary because these are macros; we have to use
188 * these on a per-macro basis (because the queues are implemented as
189 * macros, disabling this warning in the scope of the header file is
190 * insufficient), whuch means we can't use #pragma, and have to use
191 * _Pragma. We only need to use these for the queue macros that
192 * prepend "struct" to "type" and will cause C++ to blow up.
193 */
194#if defined(__clang__) && defined(__cplusplus)
195#define __MISMATCH_TAGS_PUSH \
196 _Pragma("clang diagnostic push") \
197 _Pragma("clang diagnostic ignored \"-Wmismatched-tags\"")
198#define __MISMATCH_TAGS_POP \
199 _Pragma("clang diagnostic pop")
200#else
201#define __MISMATCH_TAGS_PUSH
202#define __MISMATCH_TAGS_POP
203#endif
204
205/*!
206 * Ensures that these macros can safely be used in structs when compiling with
207 * clang. The macros do not allow for nullability attributes to be specified due
208 * to how they are expanded. For example:
209 *
210 * SLIST_HEAD(, foo _Nullable) bar;
211 *
212 * expands to
213 *
214 * struct {
215 * struct foo _Nullable *slh_first;
216 * }
217 *
218 * which is not valid because the nullability specifier has to apply to the
219 * pointer. So just ignore nullability completeness in all the places where this
220 * is an issue.
221 */
222#if defined(__clang__)
223#define __NULLABILITY_COMPLETENESS_PUSH \
224 _Pragma("clang diagnostic push") \
225 _Pragma("clang diagnostic ignored \"-Wnullability-completeness\"")
226#define __NULLABILITY_COMPLETENESS_POP \
227 _Pragma("clang diagnostic pop")
228#else
229#define __NULLABILITY_COMPLETENESS_PUSH
230#define __NULLABILITY_COMPLETENESS_POP
231#endif
232
233/*
234 * Singly-linked List declarations.
235 */
236#define SLIST_HEAD(name, type) \
237__MISMATCH_TAGS_PUSH \
238__NULLABILITY_COMPLETENESS_PUSH \
239struct name { \
240 struct type *slh_first; /* first element */ \
241} \
242__NULLABILITY_COMPLETENESS_POP \
243__MISMATCH_TAGS_POP
244
245#define SLIST_HEAD_INITIALIZER(head) \
246 { NULL }
247
248#define SLIST_ENTRY(type) \
249__MISMATCH_TAGS_PUSH \
250__NULLABILITY_COMPLETENESS_PUSH \
251struct { \
252 struct type *sle_next; /* next element */ \
253} \
254__NULLABILITY_COMPLETENESS_POP \
255__MISMATCH_TAGS_POP
256
257/*
258 * Singly-linked List functions.
259 */
260#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
261
262#define SLIST_FIRST(head) ((head)->slh_first)
263
264#define SLIST_FOREACH(var, head, field) \
265 for ((var) = SLIST_FIRST((head)); \
266 (var); \
267 (var) = SLIST_NEXT((var), field))
268
269#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
270 for ((var) = SLIST_FIRST((head)); \
271 (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
272 (var) = (tvar))
273
274#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
275 for ((varp) = &SLIST_FIRST((head)); \
276 ((var) = *(varp)) != NULL; \
277 (varp) = &SLIST_NEXT((var), field))
278
279#define SLIST_INIT(head) do { \
280 SLIST_FIRST((head)) = NULL; \
281} while (0)
282
283#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
284 SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
285 SLIST_NEXT((slistelm), field) = (elm); \
286} while (0)
287
288#define SLIST_INSERT_HEAD(head, elm, field) do { \
289 SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
290 SLIST_FIRST((head)) = (elm); \
291} while (0)
292
293#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
294
295#define SLIST_REMOVE(head, elm, type, field) \
296__MISMATCH_TAGS_PUSH \
297__NULLABILITY_COMPLETENESS_PUSH \
298do { \
299 if (SLIST_FIRST((head)) == (elm)) { \
300 SLIST_REMOVE_HEAD((head), field); \
301 } \
302 else { \
303 struct type *curelm = SLIST_FIRST((head)); \
304 while (SLIST_NEXT(curelm, field) != (elm)) \
305 curelm = SLIST_NEXT(curelm, field); \
306 SLIST_REMOVE_AFTER(curelm, field); \
307 } \
308 TRASHIT((elm)->field.sle_next); \
309} while (0) \
310__NULLABILITY_COMPLETENESS_POP \
311__MISMATCH_TAGS_POP
312
313#define SLIST_REMOVE_AFTER(elm, field) do { \
314 SLIST_NEXT(elm, field) = \
315 SLIST_NEXT(SLIST_NEXT(elm, field), field); \
316} while (0)
317
318#define SLIST_REMOVE_HEAD(head, field) do { \
319 SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
320} while (0)
321
322/*
323 * Singly-linked Tail queue declarations.
324 */
325#define STAILQ_HEAD(name, type) \
326__MISMATCH_TAGS_PUSH \
327__NULLABILITY_COMPLETENESS_PUSH \
328struct name { \
329 struct type *stqh_first;/* first element */ \
330 struct type **stqh_last;/* addr of last next element */ \
331} \
332__NULLABILITY_COMPLETENESS_POP \
333__MISMATCH_TAGS_POP
334
335#define STAILQ_HEAD_INITIALIZER(head) \
336 { NULL, &(head).stqh_first }
337
338#define STAILQ_ENTRY(type) \
339__MISMATCH_TAGS_PUSH \
340__NULLABILITY_COMPLETENESS_PUSH \
341struct { \
342 struct type *stqe_next; /* next element */ \
343} \
344__NULLABILITY_COMPLETENESS_POP \
345__MISMATCH_TAGS_POP
346
347/*
348 * Singly-linked Tail queue functions.
349 */
350#define STAILQ_CONCAT(head1, head2) do { \
351 if (!STAILQ_EMPTY((head2))) { \
352 *(head1)->stqh_last = (head2)->stqh_first; \
353 (head1)->stqh_last = (head2)->stqh_last; \
354 STAILQ_INIT((head2)); \
355 } \
356} while (0)
357
358#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
359
360#define STAILQ_FIRST(head) ((head)->stqh_first)
361
362#define STAILQ_FOREACH(var, head, field) \
363 for((var) = STAILQ_FIRST((head)); \
364 (var); \
365 (var) = STAILQ_NEXT((var), field))
366
367
368#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
369 for ((var) = STAILQ_FIRST((head)); \
370 (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
371 (var) = (tvar))
372
373#define STAILQ_INIT(head) do { \
374 STAILQ_FIRST((head)) = NULL; \
375 (head)->stqh_last = &STAILQ_FIRST((head)); \
376} while (0)
377
378#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
379 if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
380 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
381 STAILQ_NEXT((tqelm), field) = (elm); \
382} while (0)
383
384#define STAILQ_INSERT_HEAD(head, elm, field) do { \
385 if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
386 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
387 STAILQ_FIRST((head)) = (elm); \
388} while (0)
389
390#define STAILQ_INSERT_TAIL(head, elm, field) do { \
391 STAILQ_NEXT((elm), field) = NULL; \
392 *(head)->stqh_last = (elm); \
393 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
394} while (0)
395
396#define STAILQ_LAST(head, type, field) \
397__MISMATCH_TAGS_PUSH \
398__NULLABILITY_COMPLETENESS_PUSH \
399 (STAILQ_EMPTY((head)) ? \
400 NULL : \
401 ((struct type *)(void *) \
402 ((char *)((head)->stqh_last) - __offsetof(struct type, field))))\
403__NULLABILITY_COMPLETENESS_POP \
404__MISMATCH_TAGS_POP
405
406#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
407
408#define STAILQ_REMOVE(head, elm, type, field) \
409__MISMATCH_TAGS_PUSH \
410__NULLABILITY_COMPLETENESS_PUSH \
411do { \
412 if (STAILQ_FIRST((head)) == (elm)) { \
413 STAILQ_REMOVE_HEAD((head), field); \
414 } \
415 else { \
416 struct type *curelm = STAILQ_FIRST((head)); \
417 while (STAILQ_NEXT(curelm, field) != (elm)) \
418 curelm = STAILQ_NEXT(curelm, field); \
419 STAILQ_REMOVE_AFTER(head, curelm, field); \
420 } \
421 TRASHIT((elm)->field.stqe_next); \
422} while (0) \
423__NULLABILITY_COMPLETENESS_POP \
424__MISMATCH_TAGS_POP
425
426#define STAILQ_REMOVE_HEAD(head, field) do { \
427 if ((STAILQ_FIRST((head)) = \
428 STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
429 (head)->stqh_last = &STAILQ_FIRST((head)); \
430} while (0)
431
432#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
433 if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \
434 (head)->stqh_last = &STAILQ_FIRST((head)); \
435} while (0)
436
437#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
438 if ((STAILQ_NEXT(elm, field) = \
439 STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
440 (head)->stqh_last = &STAILQ_NEXT((elm), field); \
441} while (0)
442
443#define STAILQ_SWAP(head1, head2, type) \
444__MISMATCH_TAGS_PUSH \
445__NULLABILITY_COMPLETENESS_PUSH \
446do { \
447 struct type *swap_first = STAILQ_FIRST(head1); \
448 struct type **swap_last = (head1)->stqh_last; \
449 STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
450 (head1)->stqh_last = (head2)->stqh_last; \
451 STAILQ_FIRST(head2) = swap_first; \
452 (head2)->stqh_last = swap_last; \
453 if (STAILQ_EMPTY(head1)) \
454 (head1)->stqh_last = &STAILQ_FIRST(head1); \
455 if (STAILQ_EMPTY(head2)) \
456 (head2)->stqh_last = &STAILQ_FIRST(head2); \
457} while (0) \
458__NULLABILITY_COMPLETENESS_POP \
459__MISMATCH_TAGS_POP
460
461
462/*
463 * List declarations.
464 */
465#define LIST_HEAD(name, type) \
466__MISMATCH_TAGS_PUSH \
467__NULLABILITY_COMPLETENESS_PUSH \
468struct name { \
469 struct type *lh_first; /* first element */ \
470} \
471__NULLABILITY_COMPLETENESS_POP \
472__MISMATCH_TAGS_POP
473
474#define LIST_HEAD_INITIALIZER(head) \
475 { NULL }
476
477#define LIST_ENTRY(type) \
478__MISMATCH_TAGS_PUSH \
479__NULLABILITY_COMPLETENESS_PUSH \
480struct { \
481 struct type *le_next; /* next element */ \
482 struct type **le_prev; /* address of previous next element */ \
483} \
484__NULLABILITY_COMPLETENESS_POP \
485__MISMATCH_TAGS_POP
486
487/*
488 * List functions.
489 */
490
491#define LIST_CHECK_HEAD(head, field)
492#define LIST_CHECK_NEXT(elm, field)
493#define LIST_CHECK_PREV(elm, field)
494
495#define LIST_EMPTY(head) ((head)->lh_first == NULL)
496
497#define LIST_FIRST(head) ((head)->lh_first)
498
499#define LIST_FOREACH(var, head, field) \
500 for ((var) = LIST_FIRST((head)); \
501 (var); \
502 (var) = LIST_NEXT((var), field))
503
504#define LIST_FOREACH_SAFE(var, head, field, tvar) \
505 for ((var) = LIST_FIRST((head)); \
506 (var) && ((tvar) = LIST_NEXT((var), field), 1); \
507 (var) = (tvar))
508
509#define LIST_INIT(head) do { \
510 LIST_FIRST((head)) = NULL; \
511} while (0)
512
513#define LIST_INSERT_AFTER(listelm, elm, field) do { \
514 LIST_CHECK_NEXT(listelm, field); \
515 if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
516 LIST_NEXT((listelm), field)->field.le_prev = \
517 &LIST_NEXT((elm), field); \
518 LIST_NEXT((listelm), field) = (elm); \
519 (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
520} while (0)
521
522#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
523 LIST_CHECK_PREV(listelm, field); \
524 (elm)->field.le_prev = (listelm)->field.le_prev; \
525 LIST_NEXT((elm), field) = (listelm); \
526 *(listelm)->field.le_prev = (elm); \
527 (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
528} while (0)
529
530#define LIST_INSERT_HEAD(head, elm, field) do { \
531 LIST_CHECK_HEAD((head), field); \
532 if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
533 LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
534 LIST_FIRST((head)) = (elm); \
535 (elm)->field.le_prev = &LIST_FIRST((head)); \
536} while (0)
537
538#define LIST_NEXT(elm, field) ((elm)->field.le_next)
539
540#define LIST_REMOVE(elm, field) do { \
541 LIST_CHECK_NEXT(elm, field); \
542 LIST_CHECK_PREV(elm, field); \
543 if (LIST_NEXT((elm), field) != NULL) \
544 LIST_NEXT((elm), field)->field.le_prev = \
545 (elm)->field.le_prev; \
546 *(elm)->field.le_prev = LIST_NEXT((elm), field); \
547 TRASHIT((elm)->field.le_next); \
548 TRASHIT((elm)->field.le_prev); \
549} while (0)
550
551#define LIST_SWAP(head1, head2, type, field) \
552__MISMATCH_TAGS_PUSH \
553__NULLABILITY_COMPLETENESS_PUSH \
554do { \
555 struct type *swap_tmp = LIST_FIRST((head1)); \
556 LIST_FIRST((head1)) = LIST_FIRST((head2)); \
557 LIST_FIRST((head2)) = swap_tmp; \
558 if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
559 swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
560 if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
561 swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
562} while (0) \
563__NULLABILITY_COMPLETENESS_POP \
564__MISMATCH_TAGS_POP
565
566/*
567 * Tail queue declarations.
568 */
569#define TAILQ_HEAD(name, type) \
570__MISMATCH_TAGS_PUSH \
571__NULLABILITY_COMPLETENESS_PUSH \
572struct name { \
573 struct type *tqh_first; /* first element */ \
574 struct type **tqh_last; /* addr of last next element */ \
575 TRACEBUF \
576} \
577__NULLABILITY_COMPLETENESS_POP \
578__MISMATCH_TAGS_POP
579
580#define TAILQ_HEAD_INITIALIZER(head) \
581 { NULL, &(head).tqh_first }
582
583#define TAILQ_ENTRY(type) \
584__MISMATCH_TAGS_PUSH \
585__NULLABILITY_COMPLETENESS_PUSH \
586struct { \
587 struct type *tqe_next; /* next element */ \
588 struct type **tqe_prev; /* address of previous next element */ \
589 TRACEBUF \
590} \
591__NULLABILITY_COMPLETENESS_POP \
592__MISMATCH_TAGS_POP
593
594/*
595 * Tail queue functions.
596 */
597#define TAILQ_CHECK_HEAD(head, field)
598#define TAILQ_CHECK_NEXT(elm, field)
599#define TAILQ_CHECK_PREV(elm, field)
600
601#define TAILQ_CONCAT(head1, head2, field) do { \
602 if (!TAILQ_EMPTY(head2)) { \
603 *(head1)->tqh_last = (head2)->tqh_first; \
604 (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
605 (head1)->tqh_last = (head2)->tqh_last; \
606 TAILQ_INIT((head2)); \
607 QMD_TRACE_HEAD(head1); \
608 QMD_TRACE_HEAD(head2); \
609 } \
610} while (0)
611
612#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
613
614#define TAILQ_FIRST(head) ((head)->tqh_first)
615
616#define TAILQ_FOREACH(var, head, field) \
617 for ((var) = TAILQ_FIRST((head)); \
618 (var); \
619 (var) = TAILQ_NEXT((var), field))
620
621#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
622 for ((var) = TAILQ_FIRST((head)); \
623 (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
624 (var) = (tvar))
625
626#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
627 for ((var) = TAILQ_LAST((head), headname); \
628 (var); \
629 (var) = TAILQ_PREV((var), headname, field))
630
631#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
632 for ((var) = TAILQ_LAST((head), headname); \
633 (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
634 (var) = (tvar))
635
636
637#define TAILQ_INIT(head) do { \
638 TAILQ_FIRST((head)) = NULL; \
639 (head)->tqh_last = &TAILQ_FIRST((head)); \
640 QMD_TRACE_HEAD(head); \
641} while (0)
642
643
644#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
645 TAILQ_CHECK_NEXT(listelm, field); \
646 if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
647 TAILQ_NEXT((elm), field)->field.tqe_prev = \
648 &TAILQ_NEXT((elm), field); \
649 else { \
650 (head)->tqh_last = &TAILQ_NEXT((elm), field); \
651 QMD_TRACE_HEAD(head); \
652 } \
653 TAILQ_NEXT((listelm), field) = (elm); \
654 (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
655 QMD_TRACE_ELEM(&(elm)->field); \
656 QMD_TRACE_ELEM(&listelm->field); \
657} while (0)
658
659#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
660 TAILQ_CHECK_PREV(listelm, field); \
661 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
662 TAILQ_NEXT((elm), field) = (listelm); \
663 *(listelm)->field.tqe_prev = (elm); \
664 (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
665 QMD_TRACE_ELEM(&(elm)->field); \
666 QMD_TRACE_ELEM(&listelm->field); \
667} while (0)
668
669#define TAILQ_INSERT_HEAD(head, elm, field) do { \
670 TAILQ_CHECK_HEAD(head, field); \
671 if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
672 TAILQ_FIRST((head))->field.tqe_prev = \
673 &TAILQ_NEXT((elm), field); \
674 else \
675 (head)->tqh_last = &TAILQ_NEXT((elm), field); \
676 TAILQ_FIRST((head)) = (elm); \
677 (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
678 QMD_TRACE_HEAD(head); \
679 QMD_TRACE_ELEM(&(elm)->field); \
680} while (0)
681
682#define TAILQ_INSERT_TAIL(head, elm, field) do { \
683 TAILQ_NEXT((elm), field) = NULL; \
684 (elm)->field.tqe_prev = (head)->tqh_last; \
685 *(head)->tqh_last = (elm); \
686 (head)->tqh_last = &TAILQ_NEXT((elm), field); \
687 QMD_TRACE_HEAD(head); \
688 QMD_TRACE_ELEM(&(elm)->field); \
689} while (0)
690
691#define TAILQ_LAST(head, headname) \
692__MISMATCH_TAGS_PUSH \
693__NULLABILITY_COMPLETENESS_PUSH \
694 (*(((struct headname *)((head)->tqh_last))->tqh_last)) \
695__NULLABILITY_COMPLETENESS_POP \
696__MISMATCH_TAGS_POP
697
698#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
699
700#define TAILQ_PREV(elm, headname, field) \
701__MISMATCH_TAGS_PUSH \
702__NULLABILITY_COMPLETENESS_PUSH \
703 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) \
704__NULLABILITY_COMPLETENESS_POP \
705__MISMATCH_TAGS_POP
706
707#define TAILQ_REMOVE(head, elm, field) do { \
708 TAILQ_CHECK_NEXT(elm, field); \
709 TAILQ_CHECK_PREV(elm, field); \
710 if ((TAILQ_NEXT((elm), field)) != NULL) \
711 TAILQ_NEXT((elm), field)->field.tqe_prev = \
712 (elm)->field.tqe_prev; \
713 else { \
714 (head)->tqh_last = (elm)->field.tqe_prev; \
715 QMD_TRACE_HEAD(head); \
716 } \
717 *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
718 TRASHIT((elm)->field.tqe_next); \
719 TRASHIT((elm)->field.tqe_prev); \
720 QMD_TRACE_ELEM(&(elm)->field); \
721} while (0)
722
723/*
724 * Why did they switch to spaces for this one macro?
725 */
726#define TAILQ_SWAP(head1, head2, type, field) \
727__MISMATCH_TAGS_PUSH \
728__NULLABILITY_COMPLETENESS_PUSH \
729do { \
730 struct type *swap_first = (head1)->tqh_first; \
731 struct type **swap_last = (head1)->tqh_last; \
732 (head1)->tqh_first = (head2)->tqh_first; \
733 (head1)->tqh_last = (head2)->tqh_last; \
734 (head2)->tqh_first = swap_first; \
735 (head2)->tqh_last = swap_last; \
736 if ((swap_first = (head1)->tqh_first) != NULL) \
737 swap_first->field.tqe_prev = &(head1)->tqh_first; \
738 else \
739 (head1)->tqh_last = &(head1)->tqh_first; \
740 if ((swap_first = (head2)->tqh_first) != NULL) \
741 swap_first->field.tqe_prev = &(head2)->tqh_first; \
742 else \
743 (head2)->tqh_last = &(head2)->tqh_first; \
744} while (0) \
745__NULLABILITY_COMPLETENESS_POP \
746__MISMATCH_TAGS_POP
747
748/*
749 * Circular queue definitions.
750 */
751#define CIRCLEQ_HEAD(name, type) \
752__MISMATCH_TAGS_PUSH \
753__NULLABILITY_COMPLETENESS_PUSH \
754struct name { \
755 struct type *cqh_first; /* first element */ \
756 struct type *cqh_last; /* last element */ \
757} \
758__NULLABILITY_COMPLETENESS_POP \
759__MISMATCH_TAGS_POP
760
761#define CIRCLEQ_ENTRY(type) \
762__MISMATCH_TAGS_PUSH \
763__NULLABILITY_COMPLETENESS_PUSH \
764struct { \
765 struct type *cqe_next; /* next element */ \
766 struct type *cqe_prev; /* previous element */ \
767} \
768__NULLABILITY_COMPLETENESS_POP \
769__MISMATCH_TAGS_POP
770
771/*
772 * Circular queue functions.
773 */
774#define CIRCLEQ_CHECK_HEAD(head, field)
775#define CIRCLEQ_CHECK_NEXT(head, elm, field)
776#define CIRCLEQ_CHECK_PREV(head, elm, field)
777
778#define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
779
780#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
781
782#define CIRCLEQ_FOREACH(var, head, field) \
783 for((var) = (head)->cqh_first; \
784 (var) != (void *)(head); \
785 (var) = (var)->field.cqe_next)
786
787#define CIRCLEQ_INIT(head) do { \
788 (head)->cqh_first = (void *)(head); \
789 (head)->cqh_last = (void *)(head); \
790} while (0)
791
792#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
793 CIRCLEQ_CHECK_NEXT(head, listelm, field); \
794 (elm)->field.cqe_next = (listelm)->field.cqe_next; \
795 (elm)->field.cqe_prev = (listelm); \
796 if ((listelm)->field.cqe_next == (void *)(head)) \
797 (head)->cqh_last = (elm); \
798 else \
799 (listelm)->field.cqe_next->field.cqe_prev = (elm); \
800 (listelm)->field.cqe_next = (elm); \
801} while (0)
802
803#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
804 CIRCLEQ_CHECK_PREV(head, listelm, field); \
805 (elm)->field.cqe_next = (listelm); \
806 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
807 if ((listelm)->field.cqe_prev == (void *)(head)) \
808 (head)->cqh_first = (elm); \
809 else \
810 (listelm)->field.cqe_prev->field.cqe_next = (elm); \
811 (listelm)->field.cqe_prev = (elm); \
812} while (0)
813
814#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
815 CIRCLEQ_CHECK_HEAD(head, field); \
816 (elm)->field.cqe_next = (head)->cqh_first; \
817 (elm)->field.cqe_prev = (void *)(head); \
818 if ((head)->cqh_last == (void *)(head)) \
819 (head)->cqh_last = (elm); \
820 else \
821 (head)->cqh_first->field.cqe_prev = (elm); \
822 (head)->cqh_first = (elm); \
823} while (0)
824
825#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
826 (elm)->field.cqe_next = (void *)(head); \
827 (elm)->field.cqe_prev = (head)->cqh_last; \
828 if ((head)->cqh_first == (void *)(head)) \
829 (head)->cqh_first = (elm); \
830 else \
831 (head)->cqh_last->field.cqe_next = (elm); \
832 (head)->cqh_last = (elm); \
833} while (0)
834
835#define CIRCLEQ_LAST(head) ((head)->cqh_last)
836
837#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
838
839#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
840
841#define CIRCLEQ_REMOVE(head, elm, field) do { \
842 CIRCLEQ_CHECK_NEXT(head, elm, field); \
843 CIRCLEQ_CHECK_PREV(head, elm, field); \
844 if ((elm)->field.cqe_next == (void *)(head)) \
845 (head)->cqh_last = (elm)->field.cqe_prev; \
846 else \
847 (elm)->field.cqe_next->field.cqe_prev = \
848 (elm)->field.cqe_prev; \
849 if ((elm)->field.cqe_prev == (void *)(head)) \
850 (head)->cqh_first = (elm)->field.cqe_next; \
851 else \
852 (elm)->field.cqe_prev->field.cqe_next = \
853 (elm)->field.cqe_next; \
854} while (0)
855
856#ifdef _KERNEL
857
858#if NOTFB31
859
860/*
861 * XXX insque() and remque() are an old way of handling certain queues.
862 * They bogusly assumes that all queue heads look alike.
863 */
864
865struct quehead {
866 struct quehead *qh_link;
867 struct quehead *qh_rlink;
868};
869
870#ifdef __GNUC__
871#define chkquenext(a)
872#define chkqueprev(a)
873
874static __inline void
875insque(void *a, void *b)
876{
877 struct quehead *element = (struct quehead *)a,
878 *head = (struct quehead *)b;
879 chkquenext(head);
880
881 element->qh_link = head->qh_link;
882 element->qh_rlink = head;
883 head->qh_link = element;
884 element->qh_link->qh_rlink = element;
885}
886
887static __inline void
888remque(void *a)
889{
890 struct quehead *element = (struct quehead *)a;
891 chkquenext(element);
892 chkqueprev(element);
893
894 element->qh_link->qh_rlink = element->qh_rlink;
895 element->qh_rlink->qh_link = element->qh_link;
896 element->qh_rlink = 0;
897}
898
899#else /* !__GNUC__ */
900
901void insque(void *a, void *b);
902void remque(void *a);
903
904#endif /* __GNUC__ */
905
906#endif /* NOTFB31 */
907#endif /* _KERNEL */
908
909#endif /* !_SYS_QUEUE_H_ */