12958Sdr146992 /* $NetBSD: queue.h,v 1.42 2005/07/13 15:08:24 wiz Exp $ */ 22958Sdr146992 32958Sdr146992 /* 42958Sdr146992 * Copyright (c) 1991, 1993 52958Sdr146992 * The Regents of the University of California. All rights reserved. 62958Sdr146992 * 72958Sdr146992 * Redistribution and use in source and binary forms, with or without 82958Sdr146992 * modification, are permitted provided that the following conditions 92958Sdr146992 * are met: 102958Sdr146992 * 1. Redistributions of source code must retain the above copyright 112958Sdr146992 * notice, this list of conditions and the following disclaimer. 122958Sdr146992 * 2. Redistributions in binary form must reproduce the above copyright 132958Sdr146992 * notice, this list of conditions and the following disclaimer in the 142958Sdr146992 * documentation and/or other materials provided with the distribution. 152958Sdr146992 * 3. Neither the name of the University nor the names of its contributors 162958Sdr146992 * may be used to endorse or promote products derived from this software 172958Sdr146992 * without specific prior written permission. 182958Sdr146992 * 192958Sdr146992 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 202958Sdr146992 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 212958Sdr146992 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 222958Sdr146992 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 232958Sdr146992 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 242958Sdr146992 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 252958Sdr146992 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 262958Sdr146992 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 272958Sdr146992 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 282958Sdr146992 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 292958Sdr146992 * SUCH DAMAGE. 302958Sdr146992 * 312958Sdr146992 * @(#)queue.h 8.5 (Berkeley) 8/20/94 322958Sdr146992 */ 332958Sdr146992 /* 3411387SSurya.Prakki@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 352958Sdr146992 * Use is subject to license terms. 362958Sdr146992 */ 372958Sdr146992 382958Sdr146992 #ifndef _SYS_QUEUE_H 392958Sdr146992 #define _SYS_QUEUE_H 402958Sdr146992 412958Sdr146992 #include <sys/note.h> 422958Sdr146992 432958Sdr146992 #ifdef __cplusplus 442958Sdr146992 extern "C" { 452958Sdr146992 #endif 462958Sdr146992 472958Sdr146992 /* 482958Sdr146992 * This file defines five types of data structures: singly-linked lists, 492958Sdr146992 * lists, simple queues, tail queues, and circular queues. 502958Sdr146992 * 512958Sdr146992 * A singly-linked list is headed by a single forward pointer. The 522958Sdr146992 * elements are singly linked for minimum space and pointer manipulation 532958Sdr146992 * overhead at the expense of O(n) removal for arbitrary elements. New 542958Sdr146992 * elements can be added to the list after an existing element or at the 552958Sdr146992 * head of the list. Elements being removed from the head of the list 562958Sdr146992 * should use the explicit macro for this purpose for optimum 572958Sdr146992 * efficiency. A singly-linked list may only be traversed in the forward 582958Sdr146992 * direction. Singly-linked lists are ideal for applications with large 592958Sdr146992 * datasets and few or no removals or for implementing a LIFO queue. 602958Sdr146992 * 612958Sdr146992 * A list is headed by a single forward pointer (or an array of forward 622958Sdr146992 * pointers for a hash table header). The elements are doubly linked 632958Sdr146992 * so that an arbitrary element can be removed without a need to 642958Sdr146992 * traverse the list. New elements can be added to the list before 652958Sdr146992 * or after an existing element or at the head of the list. A list 662958Sdr146992 * may only be traversed in the forward direction. 672958Sdr146992 * 682958Sdr146992 * A simple queue is headed by a pair of pointers, one the head of the 692958Sdr146992 * list and the other to the tail of the list. The elements are singly 702958Sdr146992 * linked to save space, so elements can only be removed from the 712958Sdr146992 * head of the list. New elements can be added to the list after 722958Sdr146992 * an existing element, at the head of the list, or at the end of the 732958Sdr146992 * list. A simple queue may only be traversed in the forward direction. 742958Sdr146992 * 752958Sdr146992 * A tail queue is headed by a pair of pointers, one to the head of the 762958Sdr146992 * list and the other to the tail of the list. The elements are doubly 772958Sdr146992 * linked so that an arbitrary element can be removed without a need to 782958Sdr146992 * traverse the list. New elements can be added to the list before or 792958Sdr146992 * after an existing element, at the head of the list, or at the end of 802958Sdr146992 * the list. A tail queue may be traversed in either direction. 812958Sdr146992 * 822958Sdr146992 * A circle queue is headed by a pair of pointers, one to the head of the 832958Sdr146992 * list and the other to the tail of the list. The elements are doubly 842958Sdr146992 * linked so that an arbitrary element can be removed without a need to 852958Sdr146992 * traverse the list. New elements can be added to the list before or after 862958Sdr146992 * an existing element, at the head of the list, or at the end of the list. 872958Sdr146992 * A circle queue may be traversed in either direction, but has a more 882958Sdr146992 * complex end of list detection. 892958Sdr146992 * 902958Sdr146992 * For details on the use of these macros, see the queue(3) manual page. 912958Sdr146992 */ 922958Sdr146992 932958Sdr146992 /* 942958Sdr146992 * List definitions. 952958Sdr146992 */ 962958Sdr146992 #define LIST_HEAD(name, type) \ 972958Sdr146992 struct name { \ 982958Sdr146992 struct type *lh_first; /* first element */ \ 992958Sdr146992 } 1002958Sdr146992 1012958Sdr146992 #define LIST_HEAD_INITIALIZER(head) \ 1022958Sdr146992 { NULL } 1032958Sdr146992 1042958Sdr146992 #define LIST_ENTRY(type) \ 1052958Sdr146992 struct { \ 1062958Sdr146992 struct type *le_next; /* next element */ \ 1072958Sdr146992 struct type **le_prev; /* address of previous next element */ \ 1082958Sdr146992 } 1092958Sdr146992 1102958Sdr146992 /* 1112958Sdr146992 * List functions. 1122958Sdr146992 */ 1132958Sdr146992 #if defined(_KERNEL) && defined(QUEUEDEBUG) 1142958Sdr146992 #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \ 1152958Sdr146992 if ((head)->lh_first && \ 1162958Sdr146992 (head)->lh_first->field.le_prev != &(head)->lh_first) \ 1172958Sdr146992 panic("LIST_INSERT_HEAD %p %s:%d", (head), __FILE__, __LINE__); 1182958Sdr146992 #define QUEUEDEBUG_LIST_OP(elm, field) \ 1192958Sdr146992 if ((elm)->field.le_next && \ 1202958Sdr146992 (elm)->field.le_next->field.le_prev != \ 1212958Sdr146992 &(elm)->field.le_next) \ 1222958Sdr146992 panic("LIST_* forw %p %s:%d", (elm), __FILE__, __LINE__);\ 1232958Sdr146992 if (*(elm)->field.le_prev != (elm)) \ 1242958Sdr146992 panic("LIST_* back %p %s:%d", (elm), __FILE__, __LINE__); 1252958Sdr146992 #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \ 1262958Sdr146992 (elm)->field.le_next = (void *)1L; \ 1272958Sdr146992 (elm)->field.le_prev = (void *)1L; 1282958Sdr146992 #else 1292958Sdr146992 #define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) 1302958Sdr146992 #define QUEUEDEBUG_LIST_OP(elm, field) 1312958Sdr146992 #define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) 1322958Sdr146992 #endif 1332958Sdr146992 1342958Sdr146992 #define LIST_INIT(head) do { \ 1352958Sdr146992 (head)->lh_first = NULL; \ 1362958Sdr146992 _NOTE(CONSTCOND) \ 1372958Sdr146992 } while (0) 1382958Sdr146992 1392958Sdr146992 #define LIST_INSERT_AFTER(listelm, elm, field) do { \ 1402958Sdr146992 QUEUEDEBUG_LIST_OP((listelm), field) \ 1412958Sdr146992 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ 1422958Sdr146992 (listelm)->field.le_next->field.le_prev = \ 1432958Sdr146992 &(elm)->field.le_next; \ 1442958Sdr146992 (listelm)->field.le_next = (elm); \ 1452958Sdr146992 (elm)->field.le_prev = &(listelm)->field.le_next; \ 1462958Sdr146992 _NOTE(CONSTCOND) \ 1472958Sdr146992 } while (0) 1482958Sdr146992 1492958Sdr146992 #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ 1502958Sdr146992 QUEUEDEBUG_LIST_OP((listelm), field) \ 1512958Sdr146992 (elm)->field.le_prev = (listelm)->field.le_prev; \ 1522958Sdr146992 (elm)->field.le_next = (listelm); \ 1532958Sdr146992 *(listelm)->field.le_prev = (elm); \ 1542958Sdr146992 (listelm)->field.le_prev = &(elm)->field.le_next; \ 1552958Sdr146992 _NOTE(CONSTCOND) \ 1562958Sdr146992 } while (0) 1572958Sdr146992 1582958Sdr146992 #define LIST_INSERT_HEAD(head, elm, field) do { \ 1592958Sdr146992 QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \ 1602958Sdr146992 if (((elm)->field.le_next = (head)->lh_first) != NULL) \ 1612958Sdr146992 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ 1622958Sdr146992 (head)->lh_first = (elm); \ 1632958Sdr146992 (elm)->field.le_prev = &(head)->lh_first; \ 1642958Sdr146992 _NOTE(CONSTCOND) \ 1652958Sdr146992 } while (0) 1662958Sdr146992 1672958Sdr146992 #define LIST_REMOVE(elm, field) do { \ 1682958Sdr146992 QUEUEDEBUG_LIST_OP((elm), field) \ 1692958Sdr146992 if ((elm)->field.le_next != NULL) \ 1702958Sdr146992 (elm)->field.le_next->field.le_prev = \ 1712958Sdr146992 (elm)->field.le_prev; \ 1722958Sdr146992 *(elm)->field.le_prev = (elm)->field.le_next; \ 1732958Sdr146992 QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \ 1742958Sdr146992 _NOTE(CONSTCOND) \ 1752958Sdr146992 } while (0) 1762958Sdr146992 1772958Sdr146992 #define LIST_FOREACH(var, head, field) \ 1782958Sdr146992 for ((var) = ((head)->lh_first); \ 1792958Sdr146992 (var); \ 1802958Sdr146992 (var) = ((var)->field.le_next)) 1812958Sdr146992 1822958Sdr146992 /* 1832958Sdr146992 * List access methods. 1842958Sdr146992 */ 1852958Sdr146992 #define LIST_EMPTY(head) ((head)->lh_first == NULL) 1862958Sdr146992 #define LIST_FIRST(head) ((head)->lh_first) 1872958Sdr146992 #define LIST_NEXT(elm, field) ((elm)->field.le_next) 1882958Sdr146992 1892958Sdr146992 1902958Sdr146992 /* 1912958Sdr146992 * Singly-linked List definitions. 1922958Sdr146992 */ 1932958Sdr146992 #define SLIST_HEAD(name, type) \ 1942958Sdr146992 struct name { \ 1952958Sdr146992 struct type *slh_first; /* first element */ \ 1962958Sdr146992 } 1972958Sdr146992 1982958Sdr146992 #define SLIST_HEAD_INITIALIZER(head) \ 1992958Sdr146992 { NULL } 2002958Sdr146992 2012958Sdr146992 #define SLIST_ENTRY(type) \ 2022958Sdr146992 struct { \ 2032958Sdr146992 struct type *sle_next; /* next element */ \ 2042958Sdr146992 } 2052958Sdr146992 2062958Sdr146992 /* 2072958Sdr146992 * Singly-linked List functions. 2082958Sdr146992 */ 2092958Sdr146992 #define SLIST_INIT(head) do { \ 2102958Sdr146992 (head)->slh_first = NULL; \ 2112958Sdr146992 _NOTE(CONSTCOND) \ 2122958Sdr146992 } while (0) 2132958Sdr146992 2142958Sdr146992 #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ 2152958Sdr146992 (elm)->field.sle_next = (slistelm)->field.sle_next; \ 2162958Sdr146992 (slistelm)->field.sle_next = (elm); \ 2172958Sdr146992 _NOTE(CONSTCOND) \ 2182958Sdr146992 } while (0) 2192958Sdr146992 2202958Sdr146992 #define SLIST_INSERT_HEAD(head, elm, field) do { \ 2212958Sdr146992 (elm)->field.sle_next = (head)->slh_first; \ 2222958Sdr146992 (head)->slh_first = (elm); \ 2232958Sdr146992 _NOTE(CONSTCOND) \ 2242958Sdr146992 } while (0) 2252958Sdr146992 2262958Sdr146992 #define SLIST_REMOVE_HEAD(head, field) do { \ 2272958Sdr146992 (head)->slh_first = (head)->slh_first->field.sle_next; \ 2282958Sdr146992 _NOTE(CONSTCOND) \ 2292958Sdr146992 } while (0) 2302958Sdr146992 2312958Sdr146992 #define SLIST_REMOVE(head, elm, type, field) do { \ 2322958Sdr146992 if ((head)->slh_first == (elm)) { \ 2332958Sdr146992 SLIST_REMOVE_HEAD((head), field); \ 2342958Sdr146992 } \ 2352958Sdr146992 else { \ 2362958Sdr146992 struct type *curelm = (head)->slh_first; \ 2372958Sdr146992 while (curelm->field.sle_next != (elm)) \ 2382958Sdr146992 curelm = curelm->field.sle_next; \ 2392958Sdr146992 curelm->field.sle_next = \ 2402958Sdr146992 curelm->field.sle_next->field.sle_next; \ 2412958Sdr146992 } \ 2422958Sdr146992 _NOTE(CONSTCOND) \ 2432958Sdr146992 } while (0) 2442958Sdr146992 2452958Sdr146992 #define SLIST_FOREACH(var, head, field) \ 2462958Sdr146992 for ((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next) 2472958Sdr146992 2482958Sdr146992 /* 2492958Sdr146992 * Singly-linked List access methods. 2502958Sdr146992 */ 2512958Sdr146992 #define SLIST_EMPTY(head) ((head)->slh_first == NULL) 2522958Sdr146992 #define SLIST_FIRST(head) ((head)->slh_first) 2532958Sdr146992 #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) 2542958Sdr146992 2552958Sdr146992 2562958Sdr146992 /* 2572958Sdr146992 * Singly-linked Tail queue declarations. 2582958Sdr146992 */ 2592958Sdr146992 #define STAILQ_HEAD(name, type) \ 2602958Sdr146992 struct name { \ 2612958Sdr146992 struct type *stqh_first; /* first element */ \ 2622958Sdr146992 struct type **stqh_last; /* addr of last next element */ \ 2632958Sdr146992 } 2642958Sdr146992 2652958Sdr146992 #define STAILQ_HEAD_INITIALIZER(head) \ 2662958Sdr146992 { NULL, &(head).stqh_first } 2672958Sdr146992 2682958Sdr146992 #define STAILQ_ENTRY(type) \ 2692958Sdr146992 struct { \ 2702958Sdr146992 struct type *stqe_next; /* next element */ \ 2712958Sdr146992 } 2722958Sdr146992 2732958Sdr146992 /* 2742958Sdr146992 * Singly-linked Tail queue functions. 2752958Sdr146992 */ 2762958Sdr146992 #define STAILQ_INIT(head) do { \ 2772958Sdr146992 (head)->stqh_first = NULL; \ 2782958Sdr146992 (head)->stqh_last = &(head)->stqh_first; \ 2792958Sdr146992 _NOTE(CONSTCOND) \ 2802958Sdr146992 } while (0) 2812958Sdr146992 2822958Sdr146992 #define STAILQ_INSERT_HEAD(head, elm, field) do { \ 2832958Sdr146992 if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \ 2842958Sdr146992 (head)->stqh_last = &(elm)->field.stqe_next; \ 2852958Sdr146992 (head)->stqh_first = (elm); \ 2862958Sdr146992 _NOTE(CONSTCOND) \ 2872958Sdr146992 } while (0) 2882958Sdr146992 2892958Sdr146992 #define STAILQ_INSERT_TAIL(head, elm, field) do { \ 2902958Sdr146992 (elm)->field.stqe_next = NULL; \ 2912958Sdr146992 *(head)->stqh_last = (elm); \ 2922958Sdr146992 (head)->stqh_last = &(elm)->field.stqe_next; \ 2932958Sdr146992 _NOTE(CONSTCOND) \ 2942958Sdr146992 } while (0) 2952958Sdr146992 2962958Sdr146992 #define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 2972958Sdr146992 if (((elm)->field.stqe_next = (listelm)->field.stqe_next) \ 2982958Sdr146992 == NULL) \ 2992958Sdr146992 (head)->stqh_last = &(elm)->field.stqe_next; \ 3002958Sdr146992 (listelm)->field.stqe_next = (elm); \ 3012958Sdr146992 _NOTE(CONSTCOND) \ 3022958Sdr146992 } while (0) 3032958Sdr146992 3042958Sdr146992 #define STAILQ_REMOVE_HEAD(head, field) do { \ 3052958Sdr146992 if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) \ 3062958Sdr146992 == NULL) \ 3072958Sdr146992 (head)->stqh_last = &(head)->stqh_first; \ 3082958Sdr146992 _NOTE(CONSTCOND) \ 3092958Sdr146992 } while (0) 3102958Sdr146992 3112958Sdr146992 #define STAILQ_REMOVE(head, elm, type, field) do { \ 3122958Sdr146992 if ((head)->stqh_first == (elm)) { \ 3132958Sdr146992 STAILQ_REMOVE_HEAD((head), field); \ 3142958Sdr146992 } else { \ 3152958Sdr146992 struct type *curelm = (head)->stqh_first; \ 3162958Sdr146992 while (curelm->field.stqe_next != (elm)) \ 3172958Sdr146992 curelm = curelm->field.stqe_next; \ 3182958Sdr146992 if ((curelm->field.stqe_next = \ 3192958Sdr146992 curelm->field.stqe_next->field.stqe_next) == NULL) \ 3202958Sdr146992 (head)->stqh_last = &(curelm)->field.stqe_next; \ 3212958Sdr146992 } \ 3222958Sdr146992 _NOTE(CONSTCOND) \ 3232958Sdr146992 } while (0) 3242958Sdr146992 3252958Sdr146992 #define STAILQ_FOREACH(var, head, field) \ 3262958Sdr146992 for ((var) = ((head)->stqh_first); \ 3272958Sdr146992 (var); \ 3282958Sdr146992 (var) = ((var)->field.stqe_next)) 3292958Sdr146992 3302958Sdr146992 /* 3312958Sdr146992 * Singly-linked Tail queue access methods. 3322958Sdr146992 */ 3332958Sdr146992 #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) 3342958Sdr146992 #define STAILQ_FIRST(head) ((head)->stqh_first) 3352958Sdr146992 #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) 3362958Sdr146992 3372958Sdr146992 3382958Sdr146992 /* 3392958Sdr146992 * Simple queue definitions. 3402958Sdr146992 */ 3412958Sdr146992 #define SIMPLEQ_HEAD(name, type) \ 3422958Sdr146992 struct name { \ 3432958Sdr146992 struct type *sqh_first; /* first element */ \ 3442958Sdr146992 struct type **sqh_last; /* addr of last next element */ \ 3452958Sdr146992 } 3462958Sdr146992 3472958Sdr146992 #define SIMPLEQ_HEAD_INITIALIZER(head) \ 3482958Sdr146992 { NULL, &(head).sqh_first } 3492958Sdr146992 3502958Sdr146992 #define SIMPLEQ_ENTRY(type) \ 3512958Sdr146992 struct { \ 3522958Sdr146992 struct type *sqe_next; /* next element */ \ 3532958Sdr146992 } 3542958Sdr146992 3552958Sdr146992 /* 3562958Sdr146992 * Simple queue functions. 3572958Sdr146992 */ 3582958Sdr146992 #define SIMPLEQ_INIT(head) do { \ 3592958Sdr146992 (head)->sqh_first = NULL; \ 3602958Sdr146992 (head)->sqh_last = &(head)->sqh_first; \ 3612958Sdr146992 _NOTE(CONSTCOND) \ 3622958Sdr146992 } while (0) 3632958Sdr146992 3642958Sdr146992 #define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \ 3652958Sdr146992 if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \ 3662958Sdr146992 (head)->sqh_last = &(elm)->field.sqe_next; \ 3672958Sdr146992 (head)->sqh_first = (elm); \ 3682958Sdr146992 _NOTE(CONSTCOND) \ 3692958Sdr146992 } while (0) 3702958Sdr146992 3712958Sdr146992 #define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \ 3722958Sdr146992 (elm)->field.sqe_next = NULL; \ 3732958Sdr146992 *(head)->sqh_last = (elm); \ 3742958Sdr146992 (head)->sqh_last = &(elm)->field.sqe_next; \ 3752958Sdr146992 _NOTE(CONSTCOND) \ 3762958Sdr146992 } while (0) 3772958Sdr146992 3782958Sdr146992 #define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 3792958Sdr146992 if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\ 3802958Sdr146992 (head)->sqh_last = &(elm)->field.sqe_next; \ 3812958Sdr146992 (listelm)->field.sqe_next = (elm); \ 3822958Sdr146992 _NOTE(CONSTCOND) \ 3832958Sdr146992 } while (0) 3842958Sdr146992 3852958Sdr146992 #define SIMPLEQ_REMOVE_HEAD(head, field) do { \ 3862958Sdr146992 if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \ 3872958Sdr146992 (head)->sqh_last = &(head)->sqh_first; \ 3882958Sdr146992 _NOTE(CONSTCOND) \ 3892958Sdr146992 } while (0) 3902958Sdr146992 3912958Sdr146992 #define SIMPLEQ_REMOVE(head, elm, type, field) do { \ 3922958Sdr146992 if ((head)->sqh_first == (elm)) { \ 3932958Sdr146992 SIMPLEQ_REMOVE_HEAD((head), field); \ 3942958Sdr146992 } else { \ 3952958Sdr146992 struct type *curelm = (head)->sqh_first; \ 3962958Sdr146992 while (curelm->field.sqe_next != (elm)) \ 3972958Sdr146992 curelm = curelm->field.sqe_next; \ 3982958Sdr146992 if ((curelm->field.sqe_next = \ 3992958Sdr146992 curelm->field.sqe_next->field.sqe_next) == NULL) \ 4002958Sdr146992 (head)->sqh_last = &(curelm)->field.sqe_next; \ 4012958Sdr146992 } \ 4022958Sdr146992 _NOTE(CONSTCOND) \ 4032958Sdr146992 } while (0) 4042958Sdr146992 4052958Sdr146992 #define SIMPLEQ_FOREACH(var, head, field) \ 4062958Sdr146992 for ((var) = ((head)->sqh_first); \ 4072958Sdr146992 (var); \ 4082958Sdr146992 (var) = ((var)->field.sqe_next)) 4092958Sdr146992 4102958Sdr146992 /* 4112958Sdr146992 * Simple queue access methods. 4122958Sdr146992 */ 4132958Sdr146992 #define SIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL) 4142958Sdr146992 #define SIMPLEQ_FIRST(head) ((head)->sqh_first) 4152958Sdr146992 #define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next) 4162958Sdr146992 4172958Sdr146992 4182958Sdr146992 /* 4192958Sdr146992 * Tail queue definitions. 4202958Sdr146992 */ 4212958Sdr146992 #define _TAILQ_HEAD(name, type) \ 4222958Sdr146992 struct name { \ 4232958Sdr146992 type *tqh_first; /* first element */ \ 4242958Sdr146992 type **tqh_last; /* addr of last next element */ \ 4252958Sdr146992 } 4262958Sdr146992 #define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type) 4272958Sdr146992 4282958Sdr146992 #define TAILQ_HEAD_INITIALIZER(head) \ 4292958Sdr146992 { NULL, &(head).tqh_first } 4302958Sdr146992 4312958Sdr146992 #define _TAILQ_ENTRY(type) \ 4322958Sdr146992 struct { \ 4332958Sdr146992 type *tqe_next; /* next element */ \ 4342958Sdr146992 type **tqe_prev; /* address of previous next element */\ 4352958Sdr146992 } 4362958Sdr146992 #define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type) 4372958Sdr146992 4382958Sdr146992 /* 4392958Sdr146992 * Tail queue functions. 4402958Sdr146992 */ 4412958Sdr146992 #if defined(_KERNEL) && defined(QUEUEDEBUG) 4422958Sdr146992 #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \ 4432958Sdr146992 if ((head)->tqh_first && \ 4442958Sdr146992 (head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \ 44511387SSurya.Prakki@Sun.COM panic("TAILQ_INSERT_HEAD %p %s:%d", (void *)(head), \ 44611387SSurya.Prakki@Sun.COM __FILE__, __LINE__); 4472958Sdr146992 #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \ 4482958Sdr146992 if (*(head)->tqh_last != NULL) \ 44911387SSurya.Prakki@Sun.COM panic("TAILQ_INSERT_TAIL %p %s:%d", (void *)(head), \ 45011387SSurya.Prakki@Sun.COM __FILE__, __LINE__); 4512958Sdr146992 #define QUEUEDEBUG_TAILQ_OP(elm, field) \ 4522958Sdr146992 if ((elm)->field.tqe_next && \ 4532958Sdr146992 (elm)->field.tqe_next->field.tqe_prev != \ 4542958Sdr146992 &(elm)->field.tqe_next) \ 45511387SSurya.Prakki@Sun.COM panic("TAILQ_* forw %p %s:%d", (void *)(elm), \ 45611387SSurya.Prakki@Sun.COM __FILE__, __LINE__);\ 4572958Sdr146992 if (*(elm)->field.tqe_prev != (elm)) \ 45811387SSurya.Prakki@Sun.COM panic("TAILQ_* back %p %s:%d", (void *)(elm), \ 45911387SSurya.Prakki@Sun.COM __FILE__, __LINE__); 4602958Sdr146992 #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \ 4612958Sdr146992 if ((elm)->field.tqe_next == NULL && \ 4622958Sdr146992 (head)->tqh_last != &(elm)->field.tqe_next) \ 4632958Sdr146992 panic("TAILQ_PREREMOVE head %p elm %p %s:%d", \ 46411387SSurya.Prakki@Sun.COM (void *)(head), (void *)(elm), __FILE__, __LINE__); 4652958Sdr146992 #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \ 4662958Sdr146992 (elm)->field.tqe_next = (void *)1L; \ 4672958Sdr146992 (elm)->field.tqe_prev = (void *)1L; 4682958Sdr146992 #else 4692958Sdr146992 #define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) 4702958Sdr146992 #define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) 4712958Sdr146992 #define QUEUEDEBUG_TAILQ_OP(elm, field) 4722958Sdr146992 #define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) 4732958Sdr146992 #define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) 4742958Sdr146992 #endif 4752958Sdr146992 4762958Sdr146992 #define TAILQ_INIT(head) do { \ 4772958Sdr146992 (head)->tqh_first = NULL; \ 4782958Sdr146992 (head)->tqh_last = &(head)->tqh_first; \ 4792958Sdr146992 _NOTE(CONSTCOND) \ 4802958Sdr146992 } while (0) 4812958Sdr146992 4822958Sdr146992 #define TAILQ_INSERT_HEAD(head, elm, field) do { \ 4832958Sdr146992 QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \ 4842958Sdr146992 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ 4852958Sdr146992 (head)->tqh_first->field.tqe_prev = \ 4862958Sdr146992 &(elm)->field.tqe_next; \ 4872958Sdr146992 else \ 4882958Sdr146992 (head)->tqh_last = &(elm)->field.tqe_next; \ 4892958Sdr146992 (head)->tqh_first = (elm); \ 4902958Sdr146992 (elm)->field.tqe_prev = &(head)->tqh_first; \ 4912958Sdr146992 _NOTE(CONSTCOND) \ 4922958Sdr146992 } while (0) 4932958Sdr146992 4942958Sdr146992 #define TAILQ_INSERT_TAIL(head, elm, field) do { \ 4952958Sdr146992 QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \ 4962958Sdr146992 (elm)->field.tqe_next = NULL; \ 4972958Sdr146992 (elm)->field.tqe_prev = (head)->tqh_last; \ 4982958Sdr146992 *(head)->tqh_last = (elm); \ 4992958Sdr146992 (head)->tqh_last = &(elm)->field.tqe_next; \ 5002958Sdr146992 _NOTE(CONSTCOND) \ 5012958Sdr146992 } while (0) 5022958Sdr146992 5032958Sdr146992 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 5042958Sdr146992 QUEUEDEBUG_TAILQ_OP((listelm), field) \ 5052958Sdr146992 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ 5062958Sdr146992 (elm)->field.tqe_next->field.tqe_prev = \ 5072958Sdr146992 &(elm)->field.tqe_next; \ 5082958Sdr146992 else \ 5092958Sdr146992 (head)->tqh_last = &(elm)->field.tqe_next; \ 5102958Sdr146992 (listelm)->field.tqe_next = (elm); \ 5112958Sdr146992 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ 5122958Sdr146992 _NOTE(CONSTCOND) \ 5132958Sdr146992 } while (0) 5142958Sdr146992 5152958Sdr146992 #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 5162958Sdr146992 QUEUEDEBUG_TAILQ_OP((listelm), field) \ 5172958Sdr146992 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 5182958Sdr146992 (elm)->field.tqe_next = (listelm); \ 5192958Sdr146992 *(listelm)->field.tqe_prev = (elm); \ 5202958Sdr146992 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ 5212958Sdr146992 _NOTE(CONSTCOND) \ 5222958Sdr146992 } while (0) 5232958Sdr146992 5242958Sdr146992 #define TAILQ_REMOVE(head, elm, field) do { \ 5252958Sdr146992 QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \ 5262958Sdr146992 QUEUEDEBUG_TAILQ_OP((elm), field) \ 5272958Sdr146992 if (((elm)->field.tqe_next) != NULL) \ 5282958Sdr146992 (elm)->field.tqe_next->field.tqe_prev = \ 5292958Sdr146992 (elm)->field.tqe_prev; \ 5302958Sdr146992 else \ 5312958Sdr146992 (head)->tqh_last = (elm)->field.tqe_prev; \ 5322958Sdr146992 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ 5332958Sdr146992 QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \ 5342958Sdr146992 _NOTE(CONSTCOND) \ 5352958Sdr146992 } while (0) 5362958Sdr146992 5372958Sdr146992 #define TAILQ_FOREACH(var, head, field) \ 5382958Sdr146992 for ((var) = ((head)->tqh_first); \ 5392958Sdr146992 (var); \ 5402958Sdr146992 (var) = ((var)->field.tqe_next)) 5412958Sdr146992 5422958Sdr146992 #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ 5432958Sdr146992 for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last));\ 5442958Sdr146992 (var); \ 5452958Sdr146992 (var) = \ 5462958Sdr146992 (*(((struct headname *)((var)->field.tqe_prev))->tqh_last))) 5472958Sdr146992 5482958Sdr146992 /* 5492958Sdr146992 * Tail queue access methods. 5502958Sdr146992 */ 5512958Sdr146992 #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) 5522958Sdr146992 #define TAILQ_FIRST(head) ((head)->tqh_first) 5532958Sdr146992 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 5542958Sdr146992 5552958Sdr146992 #define TAILQ_LAST(head, headname) \ 5562958Sdr146992 (*(((struct headname *)((head)->tqh_last))->tqh_last)) 5572958Sdr146992 #define TAILQ_PREV(elm, headname, field) \ 5582958Sdr146992 (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) 5592958Sdr146992 5602958Sdr146992 5612958Sdr146992 /* 5622958Sdr146992 * Circular queue definitions. 5632958Sdr146992 */ 5642958Sdr146992 #define CIRCLEQ_HEAD(name, type) \ 5652958Sdr146992 struct name { \ 5662958Sdr146992 struct type *cqh_first; /* first element */ \ 5672958Sdr146992 struct type *cqh_last; /* last element */ \ 5682958Sdr146992 } 5692958Sdr146992 5702958Sdr146992 #define CIRCLEQ_HEAD_INITIALIZER(head) \ 5712958Sdr146992 { (void *)&head, (void *)&head } 5722958Sdr146992 5732958Sdr146992 #define CIRCLEQ_ENTRY(type) \ 5742958Sdr146992 struct { \ 5752958Sdr146992 struct type *cqe_next; /* next element */ \ 5762958Sdr146992 struct type *cqe_prev; /* previous element */ \ 5772958Sdr146992 } 5782958Sdr146992 5792958Sdr146992 /* 5802958Sdr146992 * Circular queue functions. 5812958Sdr146992 */ 5822958Sdr146992 #define CIRCLEQ_INIT(head) do { \ 5832958Sdr146992 (head)->cqh_first = (void *)(head); \ 5842958Sdr146992 (head)->cqh_last = (void *)(head); \ 5852958Sdr146992 _NOTE(CONSTCOND) \ 5862958Sdr146992 } while (0) 5872958Sdr146992 5882958Sdr146992 #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 5892958Sdr146992 (elm)->field.cqe_next = (listelm)->field.cqe_next; \ 5902958Sdr146992 (elm)->field.cqe_prev = (listelm); \ 5912958Sdr146992 if ((listelm)->field.cqe_next == (void *)(head)) \ 5922958Sdr146992 (head)->cqh_last = (elm); \ 5932958Sdr146992 else \ 5942958Sdr146992 (listelm)->field.cqe_next->field.cqe_prev = (elm); \ 5952958Sdr146992 (listelm)->field.cqe_next = (elm); \ 5962958Sdr146992 _NOTE(CONSTCOND) \ 5972958Sdr146992 } while (0) 5982958Sdr146992 5992958Sdr146992 #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ 6002958Sdr146992 (elm)->field.cqe_next = (listelm); \ 6012958Sdr146992 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ 6022958Sdr146992 if ((listelm)->field.cqe_prev == (void *)(head)) \ 6032958Sdr146992 (head)->cqh_first = (elm); \ 6042958Sdr146992 else \ 6052958Sdr146992 (listelm)->field.cqe_prev->field.cqe_next = (elm); \ 6062958Sdr146992 (listelm)->field.cqe_prev = (elm); \ 6072958Sdr146992 _NOTE(CONSTCOND) \ 6082958Sdr146992 } while (0) 6092958Sdr146992 6102958Sdr146992 #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ 6112958Sdr146992 (elm)->field.cqe_next = (head)->cqh_first; \ 6122958Sdr146992 (elm)->field.cqe_prev = (void *)(head); \ 6132958Sdr146992 if ((head)->cqh_last == (void *)(head)) \ 6142958Sdr146992 (head)->cqh_last = (elm); \ 6152958Sdr146992 else \ 6162958Sdr146992 (head)->cqh_first->field.cqe_prev = (elm); \ 6172958Sdr146992 (head)->cqh_first = (elm); \ 6182958Sdr146992 _NOTE(CONSTCOND) \ 6192958Sdr146992 } while (0) 6202958Sdr146992 6212958Sdr146992 #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ 6222958Sdr146992 (elm)->field.cqe_next = (void *)(head); \ 6232958Sdr146992 (elm)->field.cqe_prev = (head)->cqh_last; \ 6242958Sdr146992 if ((head)->cqh_first == (void *)(head)) \ 6252958Sdr146992 (head)->cqh_first = (elm); \ 6262958Sdr146992 else \ 6272958Sdr146992 (head)->cqh_last->field.cqe_next = (elm); \ 6282958Sdr146992 (head)->cqh_last = (elm); \ 6292958Sdr146992 _NOTE(CONSTCOND) \ 6302958Sdr146992 } while (0) 6312958Sdr146992 6322958Sdr146992 #define CIRCLEQ_REMOVE(head, elm, field) do { \ 6332958Sdr146992 if ((elm)->field.cqe_next == (void *)(head)) \ 6342958Sdr146992 (head)->cqh_last = (elm)->field.cqe_prev; \ 6352958Sdr146992 else \ 6362958Sdr146992 (elm)->field.cqe_next->field.cqe_prev = \ 6372958Sdr146992 (elm)->field.cqe_prev; \ 6382958Sdr146992 if ((elm)->field.cqe_prev == (void *)(head)) \ 6392958Sdr146992 (head)->cqh_first = (elm)->field.cqe_next; \ 6402958Sdr146992 else \ 6412958Sdr146992 (elm)->field.cqe_prev->field.cqe_next = \ 6422958Sdr146992 (elm)->field.cqe_next; \ 6432958Sdr146992 _NOTE(CONSTCOND) \ 6442958Sdr146992 } while (0) 6452958Sdr146992 6462958Sdr146992 #define CIRCLEQ_FOREACH(var, head, field) \ 6472958Sdr146992 for ((var) = ((head)->cqh_first); \ 6482958Sdr146992 (var) != (void *)(head); \ 6492958Sdr146992 (var) = ((var)->field.cqe_next)) 6502958Sdr146992 6512958Sdr146992 #define CIRCLEQ_FOREACH_REVERSE(var, head, field) \ 6522958Sdr146992 for ((var) = ((head)->cqh_last); \ 6532958Sdr146992 (var) != (void *)(head); \ 6542958Sdr146992 (var) = ((var)->field.cqe_prev)) 6552958Sdr146992 6562958Sdr146992 /* 6572958Sdr146992 * Circular queue access methods. 6582958Sdr146992 */ 6592958Sdr146992 #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head)) 6602958Sdr146992 #define CIRCLEQ_FIRST(head) ((head)->cqh_first) 6612958Sdr146992 #define CIRCLEQ_LAST(head) ((head)->cqh_last) 6622958Sdr146992 #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) 6632958Sdr146992 #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) 6642958Sdr146992 665*12459SDarren.Reed@Sun.COM #define CIRCLEQ_LOOP_NEXT(head, elm, field) \ 666*12459SDarren.Reed@Sun.COM (((elm)->field.cqe_next == (void *)(head)) \ 667*12459SDarren.Reed@Sun.COM ? ((head)->cqh_first) \ 668*12459SDarren.Reed@Sun.COM : (elm->field.cqe_next)) 669*12459SDarren.Reed@Sun.COM #define CIRCLEQ_LOOP_PREV(head, elm, field) \ 670*12459SDarren.Reed@Sun.COM (((elm)->field.cqe_prev == (void *)(head)) \ 671*12459SDarren.Reed@Sun.COM ? ((head)->cqh_last) \ 672*12459SDarren.Reed@Sun.COM : (elm->field.cqe_prev)) 673*12459SDarren.Reed@Sun.COM 6742958Sdr146992 #ifdef __cplusplus 6752958Sdr146992 } 6762958Sdr146992 #endif 6772958Sdr146992 6782958Sdr146992 #endif /* !_SYS_QUEUE_H */ 679