1*4a5d661aSToomas Soome /*- 2*4a5d661aSToomas Soome * Copyright (c) 1991, 1993 3*4a5d661aSToomas Soome * The Regents of the University of California. All rights reserved. 4*4a5d661aSToomas Soome * 5*4a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 6*4a5d661aSToomas Soome * modification, are permitted provided that the following conditions 7*4a5d661aSToomas Soome * are met: 8*4a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 9*4a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 10*4a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 11*4a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 12*4a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 13*4a5d661aSToomas Soome * 4. Neither the name of the University nor the names of its contributors 14*4a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 15*4a5d661aSToomas Soome * without specific prior written permission. 16*4a5d661aSToomas Soome * 17*4a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18*4a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*4a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*4a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21*4a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*4a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*4a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*4a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*4a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*4a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*4a5d661aSToomas Soome * SUCH DAMAGE. 28*4a5d661aSToomas Soome * 29*4a5d661aSToomas Soome * @(#)queue.h 8.5 (Berkeley) 8/20/94 30*4a5d661aSToomas Soome * $FreeBSD$ 31*4a5d661aSToomas Soome */ 32*4a5d661aSToomas Soome 33*4a5d661aSToomas Soome #ifndef _SYS_QUEUE_H_ 34*4a5d661aSToomas Soome #define _SYS_QUEUE_H_ 35*4a5d661aSToomas Soome 36*4a5d661aSToomas Soome #include <sys/cdefs.h> 37*4a5d661aSToomas Soome 38*4a5d661aSToomas Soome /* 39*4a5d661aSToomas Soome * This file defines four types of data structures: singly-linked lists, 40*4a5d661aSToomas Soome * singly-linked tail queues, lists and tail queues. 41*4a5d661aSToomas Soome * 42*4a5d661aSToomas Soome * A singly-linked list is headed by a single forward pointer. The elements 43*4a5d661aSToomas Soome * are singly linked for minimum space and pointer manipulation overhead at 44*4a5d661aSToomas Soome * the expense of O(n) removal for arbitrary elements. New elements can be 45*4a5d661aSToomas Soome * added to the list after an existing element or at the head of the list. 46*4a5d661aSToomas Soome * Elements being removed from the head of the list should use the explicit 47*4a5d661aSToomas Soome * macro for this purpose for optimum efficiency. A singly-linked list may 48*4a5d661aSToomas Soome * only be traversed in the forward direction. Singly-linked lists are ideal 49*4a5d661aSToomas Soome * for applications with large datasets and few or no removals or for 50*4a5d661aSToomas Soome * implementing a LIFO queue. 51*4a5d661aSToomas Soome * 52*4a5d661aSToomas Soome * A singly-linked tail queue is headed by a pair of pointers, one to the 53*4a5d661aSToomas Soome * head of the list and the other to the tail of the list. The elements are 54*4a5d661aSToomas Soome * singly linked for minimum space and pointer manipulation overhead at the 55*4a5d661aSToomas Soome * expense of O(n) removal for arbitrary elements. New elements can be added 56*4a5d661aSToomas Soome * to the list after an existing element, at the head of the list, or at the 57*4a5d661aSToomas Soome * end of the list. Elements being removed from the head of the tail queue 58*4a5d661aSToomas Soome * should use the explicit macro for this purpose for optimum efficiency. 59*4a5d661aSToomas Soome * A singly-linked tail queue may only be traversed in the forward direction. 60*4a5d661aSToomas Soome * Singly-linked tail queues are ideal for applications with large datasets 61*4a5d661aSToomas Soome * and few or no removals or for implementing a FIFO queue. 62*4a5d661aSToomas Soome * 63*4a5d661aSToomas Soome * A list is headed by a single forward pointer (or an array of forward 64*4a5d661aSToomas Soome * pointers for a hash table header). The elements are doubly linked 65*4a5d661aSToomas Soome * so that an arbitrary element can be removed without a need to 66*4a5d661aSToomas Soome * traverse the list. New elements can be added to the list before 67*4a5d661aSToomas Soome * or after an existing element or at the head of the list. A list 68*4a5d661aSToomas Soome * may be traversed in either direction. 69*4a5d661aSToomas Soome * 70*4a5d661aSToomas Soome * A tail queue is headed by a pair of pointers, one to the head of the 71*4a5d661aSToomas Soome * list and the other to the tail of the list. The elements are doubly 72*4a5d661aSToomas Soome * linked so that an arbitrary element can be removed without a need to 73*4a5d661aSToomas Soome * traverse the list. New elements can be added to the list before or 74*4a5d661aSToomas Soome * after an existing element, at the head of the list, or at the end of 75*4a5d661aSToomas Soome * the list. A tail queue may be traversed in either direction. 76*4a5d661aSToomas Soome * 77*4a5d661aSToomas Soome * For details on the use of these macros, see the queue(3) manual page. 78*4a5d661aSToomas Soome * 79*4a5d661aSToomas Soome * 80*4a5d661aSToomas Soome * SLIST LIST STAILQ TAILQ 81*4a5d661aSToomas Soome * _HEAD + + + + 82*4a5d661aSToomas Soome * _CLASS_HEAD + + + + 83*4a5d661aSToomas Soome * _HEAD_INITIALIZER + + + + 84*4a5d661aSToomas Soome * _ENTRY + + + + 85*4a5d661aSToomas Soome * _CLASS_ENTRY + + + + 86*4a5d661aSToomas Soome * _INIT + + + + 87*4a5d661aSToomas Soome * _EMPTY + + + + 88*4a5d661aSToomas Soome * _FIRST + + + + 89*4a5d661aSToomas Soome * _NEXT + + + + 90*4a5d661aSToomas Soome * _PREV - + - + 91*4a5d661aSToomas Soome * _LAST - - + + 92*4a5d661aSToomas Soome * _FOREACH + + + + 93*4a5d661aSToomas Soome * _FOREACH_FROM + + + + 94*4a5d661aSToomas Soome * _FOREACH_SAFE + + + + 95*4a5d661aSToomas Soome * _FOREACH_FROM_SAFE + + + + 96*4a5d661aSToomas Soome * _FOREACH_REVERSE - - - + 97*4a5d661aSToomas Soome * _FOREACH_REVERSE_FROM - - - + 98*4a5d661aSToomas Soome * _FOREACH_REVERSE_SAFE - - - + 99*4a5d661aSToomas Soome * _FOREACH_REVERSE_FROM_SAFE - - - + 100*4a5d661aSToomas Soome * _INSERT_HEAD + + + + 101*4a5d661aSToomas Soome * _INSERT_BEFORE - + - + 102*4a5d661aSToomas Soome * _INSERT_AFTER + + + + 103*4a5d661aSToomas Soome * _INSERT_TAIL - - + + 104*4a5d661aSToomas Soome * _CONCAT - - + + 105*4a5d661aSToomas Soome * _REMOVE_AFTER + - + - 106*4a5d661aSToomas Soome * _REMOVE_HEAD + - + - 107*4a5d661aSToomas Soome * _REMOVE + + + + 108*4a5d661aSToomas Soome * _SWAP + + + + 109*4a5d661aSToomas Soome * 110*4a5d661aSToomas Soome */ 111*4a5d661aSToomas Soome #ifdef QUEUE_MACRO_DEBUG 112*4a5d661aSToomas Soome /* Store the last 2 places the queue element or head was altered */ 113*4a5d661aSToomas Soome struct qm_trace { 114*4a5d661aSToomas Soome unsigned long lastline; 115*4a5d661aSToomas Soome unsigned long prevline; 116*4a5d661aSToomas Soome const char *lastfile; 117*4a5d661aSToomas Soome const char *prevfile; 118*4a5d661aSToomas Soome }; 119*4a5d661aSToomas Soome 120*4a5d661aSToomas Soome #define TRACEBUF struct qm_trace trace; 121*4a5d661aSToomas Soome #define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } , 122*4a5d661aSToomas Soome #define TRASHIT(x) do {(x) = (void *)-1;} while (0) 123*4a5d661aSToomas Soome #define QMD_SAVELINK(name, link) void **name = (void *)&(link) 124*4a5d661aSToomas Soome 125*4a5d661aSToomas Soome #define QMD_TRACE_HEAD(head) do { \ 126*4a5d661aSToomas Soome (head)->trace.prevline = (head)->trace.lastline; \ 127*4a5d661aSToomas Soome (head)->trace.prevfile = (head)->trace.lastfile; \ 128*4a5d661aSToomas Soome (head)->trace.lastline = __LINE__; \ 129*4a5d661aSToomas Soome (head)->trace.lastfile = __FILE__; \ 130*4a5d661aSToomas Soome } while (0) 131*4a5d661aSToomas Soome 132*4a5d661aSToomas Soome #define QMD_TRACE_ELEM(elem) do { \ 133*4a5d661aSToomas Soome (elem)->trace.prevline = (elem)->trace.lastline; \ 134*4a5d661aSToomas Soome (elem)->trace.prevfile = (elem)->trace.lastfile; \ 135*4a5d661aSToomas Soome (elem)->trace.lastline = __LINE__; \ 136*4a5d661aSToomas Soome (elem)->trace.lastfile = __FILE__; \ 137*4a5d661aSToomas Soome } while (0) 138*4a5d661aSToomas Soome 139*4a5d661aSToomas Soome #else 140*4a5d661aSToomas Soome #define QMD_TRACE_ELEM(elem) 141*4a5d661aSToomas Soome #define QMD_TRACE_HEAD(head) 142*4a5d661aSToomas Soome #define QMD_SAVELINK(name, link) 143*4a5d661aSToomas Soome #define TRACEBUF 144*4a5d661aSToomas Soome #define TRACEBUF_INITIALIZER 145*4a5d661aSToomas Soome #define TRASHIT(x) 146*4a5d661aSToomas Soome #endif /* QUEUE_MACRO_DEBUG */ 147*4a5d661aSToomas Soome 148*4a5d661aSToomas Soome #ifdef __cplusplus 149*4a5d661aSToomas Soome /* 150*4a5d661aSToomas Soome * In C++ there can be structure lists and class lists: 151*4a5d661aSToomas Soome */ 152*4a5d661aSToomas Soome #define QUEUE_TYPEOF(type) type 153*4a5d661aSToomas Soome #else 154*4a5d661aSToomas Soome #define QUEUE_TYPEOF(type) struct type 155*4a5d661aSToomas Soome #endif 156*4a5d661aSToomas Soome 157*4a5d661aSToomas Soome /* 158*4a5d661aSToomas Soome * Singly-linked List declarations. 159*4a5d661aSToomas Soome */ 160*4a5d661aSToomas Soome #define SLIST_HEAD(name, type) \ 161*4a5d661aSToomas Soome struct name { \ 162*4a5d661aSToomas Soome struct type *slh_first; /* first element */ \ 163*4a5d661aSToomas Soome } 164*4a5d661aSToomas Soome 165*4a5d661aSToomas Soome #define SLIST_CLASS_HEAD(name, type) \ 166*4a5d661aSToomas Soome struct name { \ 167*4a5d661aSToomas Soome class type *slh_first; /* first element */ \ 168*4a5d661aSToomas Soome } 169*4a5d661aSToomas Soome 170*4a5d661aSToomas Soome #define SLIST_HEAD_INITIALIZER(head) \ 171*4a5d661aSToomas Soome { NULL } 172*4a5d661aSToomas Soome 173*4a5d661aSToomas Soome #define SLIST_ENTRY(type) \ 174*4a5d661aSToomas Soome struct { \ 175*4a5d661aSToomas Soome struct type *sle_next; /* next element */ \ 176*4a5d661aSToomas Soome } 177*4a5d661aSToomas Soome 178*4a5d661aSToomas Soome #define SLIST_CLASS_ENTRY(type) \ 179*4a5d661aSToomas Soome struct { \ 180*4a5d661aSToomas Soome class type *sle_next; /* next element */ \ 181*4a5d661aSToomas Soome } 182*4a5d661aSToomas Soome 183*4a5d661aSToomas Soome /* 184*4a5d661aSToomas Soome * Singly-linked List functions. 185*4a5d661aSToomas Soome */ 186*4a5d661aSToomas Soome #define SLIST_EMPTY(head) ((head)->slh_first == NULL) 187*4a5d661aSToomas Soome 188*4a5d661aSToomas Soome #define SLIST_FIRST(head) ((head)->slh_first) 189*4a5d661aSToomas Soome 190*4a5d661aSToomas Soome #define SLIST_FOREACH(var, head, field) \ 191*4a5d661aSToomas Soome for ((var) = SLIST_FIRST((head)); \ 192*4a5d661aSToomas Soome (var); \ 193*4a5d661aSToomas Soome (var) = SLIST_NEXT((var), field)) 194*4a5d661aSToomas Soome 195*4a5d661aSToomas Soome #define SLIST_FOREACH_FROM(var, head, field) \ 196*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ 197*4a5d661aSToomas Soome (var); \ 198*4a5d661aSToomas Soome (var) = SLIST_NEXT((var), field)) 199*4a5d661aSToomas Soome 200*4a5d661aSToomas Soome #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ 201*4a5d661aSToomas Soome for ((var) = SLIST_FIRST((head)); \ 202*4a5d661aSToomas Soome (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ 203*4a5d661aSToomas Soome (var) = (tvar)) 204*4a5d661aSToomas Soome 205*4a5d661aSToomas Soome #define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ 206*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \ 207*4a5d661aSToomas Soome (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ 208*4a5d661aSToomas Soome (var) = (tvar)) 209*4a5d661aSToomas Soome 210*4a5d661aSToomas Soome #define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ 211*4a5d661aSToomas Soome for ((varp) = &SLIST_FIRST((head)); \ 212*4a5d661aSToomas Soome ((var) = *(varp)) != NULL; \ 213*4a5d661aSToomas Soome (varp) = &SLIST_NEXT((var), field)) 214*4a5d661aSToomas Soome 215*4a5d661aSToomas Soome #define SLIST_INIT(head) do { \ 216*4a5d661aSToomas Soome SLIST_FIRST((head)) = NULL; \ 217*4a5d661aSToomas Soome } while (0) 218*4a5d661aSToomas Soome 219*4a5d661aSToomas Soome #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ 220*4a5d661aSToomas Soome SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ 221*4a5d661aSToomas Soome SLIST_NEXT((slistelm), field) = (elm); \ 222*4a5d661aSToomas Soome } while (0) 223*4a5d661aSToomas Soome 224*4a5d661aSToomas Soome #define SLIST_INSERT_HEAD(head, elm, field) do { \ 225*4a5d661aSToomas Soome SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ 226*4a5d661aSToomas Soome SLIST_FIRST((head)) = (elm); \ 227*4a5d661aSToomas Soome } while (0) 228*4a5d661aSToomas Soome 229*4a5d661aSToomas Soome #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) 230*4a5d661aSToomas Soome 231*4a5d661aSToomas Soome #define SLIST_REMOVE(head, elm, type, field) do { \ 232*4a5d661aSToomas Soome QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ 233*4a5d661aSToomas Soome if (SLIST_FIRST((head)) == (elm)) { \ 234*4a5d661aSToomas Soome SLIST_REMOVE_HEAD((head), field); \ 235*4a5d661aSToomas Soome } \ 236*4a5d661aSToomas Soome else { \ 237*4a5d661aSToomas Soome QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ 238*4a5d661aSToomas Soome while (SLIST_NEXT(curelm, field) != (elm)) \ 239*4a5d661aSToomas Soome curelm = SLIST_NEXT(curelm, field); \ 240*4a5d661aSToomas Soome SLIST_REMOVE_AFTER(curelm, field); \ 241*4a5d661aSToomas Soome } \ 242*4a5d661aSToomas Soome TRASHIT(*oldnext); \ 243*4a5d661aSToomas Soome } while (0) 244*4a5d661aSToomas Soome 245*4a5d661aSToomas Soome #define SLIST_REMOVE_AFTER(elm, field) do { \ 246*4a5d661aSToomas Soome SLIST_NEXT(elm, field) = \ 247*4a5d661aSToomas Soome SLIST_NEXT(SLIST_NEXT(elm, field), field); \ 248*4a5d661aSToomas Soome } while (0) 249*4a5d661aSToomas Soome 250*4a5d661aSToomas Soome #define SLIST_REMOVE_HEAD(head, field) do { \ 251*4a5d661aSToomas Soome SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ 252*4a5d661aSToomas Soome } while (0) 253*4a5d661aSToomas Soome 254*4a5d661aSToomas Soome #define SLIST_SWAP(head1, head2, type) do { \ 255*4a5d661aSToomas Soome QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ 256*4a5d661aSToomas Soome SLIST_FIRST(head1) = SLIST_FIRST(head2); \ 257*4a5d661aSToomas Soome SLIST_FIRST(head2) = swap_first; \ 258*4a5d661aSToomas Soome } while (0) 259*4a5d661aSToomas Soome 260*4a5d661aSToomas Soome /* 261*4a5d661aSToomas Soome * Singly-linked Tail queue declarations. 262*4a5d661aSToomas Soome */ 263*4a5d661aSToomas Soome #define STAILQ_HEAD(name, type) \ 264*4a5d661aSToomas Soome struct name { \ 265*4a5d661aSToomas Soome struct type *stqh_first;/* first element */ \ 266*4a5d661aSToomas Soome struct type **stqh_last;/* addr of last next element */ \ 267*4a5d661aSToomas Soome } 268*4a5d661aSToomas Soome 269*4a5d661aSToomas Soome #define STAILQ_CLASS_HEAD(name, type) \ 270*4a5d661aSToomas Soome struct name { \ 271*4a5d661aSToomas Soome class type *stqh_first; /* first element */ \ 272*4a5d661aSToomas Soome class type **stqh_last; /* addr of last next element */ \ 273*4a5d661aSToomas Soome } 274*4a5d661aSToomas Soome 275*4a5d661aSToomas Soome #define STAILQ_HEAD_INITIALIZER(head) \ 276*4a5d661aSToomas Soome { NULL, &(head).stqh_first } 277*4a5d661aSToomas Soome 278*4a5d661aSToomas Soome #define STAILQ_ENTRY(type) \ 279*4a5d661aSToomas Soome struct { \ 280*4a5d661aSToomas Soome struct type *stqe_next; /* next element */ \ 281*4a5d661aSToomas Soome } 282*4a5d661aSToomas Soome 283*4a5d661aSToomas Soome #define STAILQ_CLASS_ENTRY(type) \ 284*4a5d661aSToomas Soome struct { \ 285*4a5d661aSToomas Soome class type *stqe_next; /* next element */ \ 286*4a5d661aSToomas Soome } 287*4a5d661aSToomas Soome 288*4a5d661aSToomas Soome /* 289*4a5d661aSToomas Soome * Singly-linked Tail queue functions. 290*4a5d661aSToomas Soome */ 291*4a5d661aSToomas Soome #define STAILQ_CONCAT(head1, head2) do { \ 292*4a5d661aSToomas Soome if (!STAILQ_EMPTY((head2))) { \ 293*4a5d661aSToomas Soome *(head1)->stqh_last = (head2)->stqh_first; \ 294*4a5d661aSToomas Soome (head1)->stqh_last = (head2)->stqh_last; \ 295*4a5d661aSToomas Soome STAILQ_INIT((head2)); \ 296*4a5d661aSToomas Soome } \ 297*4a5d661aSToomas Soome } while (0) 298*4a5d661aSToomas Soome 299*4a5d661aSToomas Soome #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) 300*4a5d661aSToomas Soome 301*4a5d661aSToomas Soome #define STAILQ_FIRST(head) ((head)->stqh_first) 302*4a5d661aSToomas Soome 303*4a5d661aSToomas Soome #define STAILQ_FOREACH(var, head, field) \ 304*4a5d661aSToomas Soome for((var) = STAILQ_FIRST((head)); \ 305*4a5d661aSToomas Soome (var); \ 306*4a5d661aSToomas Soome (var) = STAILQ_NEXT((var), field)) 307*4a5d661aSToomas Soome 308*4a5d661aSToomas Soome #define STAILQ_FOREACH_FROM(var, head, field) \ 309*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ 310*4a5d661aSToomas Soome (var); \ 311*4a5d661aSToomas Soome (var) = STAILQ_NEXT((var), field)) 312*4a5d661aSToomas Soome 313*4a5d661aSToomas Soome #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ 314*4a5d661aSToomas Soome for ((var) = STAILQ_FIRST((head)); \ 315*4a5d661aSToomas Soome (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ 316*4a5d661aSToomas Soome (var) = (tvar)) 317*4a5d661aSToomas Soome 318*4a5d661aSToomas Soome #define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ 319*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \ 320*4a5d661aSToomas Soome (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ 321*4a5d661aSToomas Soome (var) = (tvar)) 322*4a5d661aSToomas Soome 323*4a5d661aSToomas Soome #define STAILQ_INIT(head) do { \ 324*4a5d661aSToomas Soome STAILQ_FIRST((head)) = NULL; \ 325*4a5d661aSToomas Soome (head)->stqh_last = &STAILQ_FIRST((head)); \ 326*4a5d661aSToomas Soome } while (0) 327*4a5d661aSToomas Soome 328*4a5d661aSToomas Soome #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ 329*4a5d661aSToomas Soome if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ 330*4a5d661aSToomas Soome (head)->stqh_last = &STAILQ_NEXT((elm), field); \ 331*4a5d661aSToomas Soome STAILQ_NEXT((tqelm), field) = (elm); \ 332*4a5d661aSToomas Soome } while (0) 333*4a5d661aSToomas Soome 334*4a5d661aSToomas Soome #define STAILQ_INSERT_HEAD(head, elm, field) do { \ 335*4a5d661aSToomas Soome if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ 336*4a5d661aSToomas Soome (head)->stqh_last = &STAILQ_NEXT((elm), field); \ 337*4a5d661aSToomas Soome STAILQ_FIRST((head)) = (elm); \ 338*4a5d661aSToomas Soome } while (0) 339*4a5d661aSToomas Soome 340*4a5d661aSToomas Soome #define STAILQ_INSERT_TAIL(head, elm, field) do { \ 341*4a5d661aSToomas Soome STAILQ_NEXT((elm), field) = NULL; \ 342*4a5d661aSToomas Soome *(head)->stqh_last = (elm); \ 343*4a5d661aSToomas Soome (head)->stqh_last = &STAILQ_NEXT((elm), field); \ 344*4a5d661aSToomas Soome } while (0) 345*4a5d661aSToomas Soome 346*4a5d661aSToomas Soome #define STAILQ_LAST(head, type, field) \ 347*4a5d661aSToomas Soome (STAILQ_EMPTY((head)) ? NULL : \ 348*4a5d661aSToomas Soome __containerof((head)->stqh_last, \ 349*4a5d661aSToomas Soome QUEUE_TYPEOF(type), field.stqe_next)) 350*4a5d661aSToomas Soome 351*4a5d661aSToomas Soome #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) 352*4a5d661aSToomas Soome 353*4a5d661aSToomas Soome #define STAILQ_REMOVE(head, elm, type, field) do { \ 354*4a5d661aSToomas Soome QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ 355*4a5d661aSToomas Soome if (STAILQ_FIRST((head)) == (elm)) { \ 356*4a5d661aSToomas Soome STAILQ_REMOVE_HEAD((head), field); \ 357*4a5d661aSToomas Soome } \ 358*4a5d661aSToomas Soome else { \ 359*4a5d661aSToomas Soome QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ 360*4a5d661aSToomas Soome while (STAILQ_NEXT(curelm, field) != (elm)) \ 361*4a5d661aSToomas Soome curelm = STAILQ_NEXT(curelm, field); \ 362*4a5d661aSToomas Soome STAILQ_REMOVE_AFTER(head, curelm, field); \ 363*4a5d661aSToomas Soome } \ 364*4a5d661aSToomas Soome TRASHIT(*oldnext); \ 365*4a5d661aSToomas Soome } while (0) 366*4a5d661aSToomas Soome 367*4a5d661aSToomas Soome #define STAILQ_REMOVE_AFTER(head, elm, field) do { \ 368*4a5d661aSToomas Soome if ((STAILQ_NEXT(elm, field) = \ 369*4a5d661aSToomas Soome STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ 370*4a5d661aSToomas Soome (head)->stqh_last = &STAILQ_NEXT((elm), field); \ 371*4a5d661aSToomas Soome } while (0) 372*4a5d661aSToomas Soome 373*4a5d661aSToomas Soome #define STAILQ_REMOVE_HEAD(head, field) do { \ 374*4a5d661aSToomas Soome if ((STAILQ_FIRST((head)) = \ 375*4a5d661aSToomas Soome STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ 376*4a5d661aSToomas Soome (head)->stqh_last = &STAILQ_FIRST((head)); \ 377*4a5d661aSToomas Soome } while (0) 378*4a5d661aSToomas Soome 379*4a5d661aSToomas Soome #define STAILQ_SWAP(head1, head2, type) do { \ 380*4a5d661aSToomas Soome QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ 381*4a5d661aSToomas Soome QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ 382*4a5d661aSToomas Soome STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ 383*4a5d661aSToomas Soome (head1)->stqh_last = (head2)->stqh_last; \ 384*4a5d661aSToomas Soome STAILQ_FIRST(head2) = swap_first; \ 385*4a5d661aSToomas Soome (head2)->stqh_last = swap_last; \ 386*4a5d661aSToomas Soome if (STAILQ_EMPTY(head1)) \ 387*4a5d661aSToomas Soome (head1)->stqh_last = &STAILQ_FIRST(head1); \ 388*4a5d661aSToomas Soome if (STAILQ_EMPTY(head2)) \ 389*4a5d661aSToomas Soome (head2)->stqh_last = &STAILQ_FIRST(head2); \ 390*4a5d661aSToomas Soome } while (0) 391*4a5d661aSToomas Soome 392*4a5d661aSToomas Soome 393*4a5d661aSToomas Soome /* 394*4a5d661aSToomas Soome * List declarations. 395*4a5d661aSToomas Soome */ 396*4a5d661aSToomas Soome #define LIST_HEAD(name, type) \ 397*4a5d661aSToomas Soome struct name { \ 398*4a5d661aSToomas Soome struct type *lh_first; /* first element */ \ 399*4a5d661aSToomas Soome } 400*4a5d661aSToomas Soome 401*4a5d661aSToomas Soome #define LIST_CLASS_HEAD(name, type) \ 402*4a5d661aSToomas Soome struct name { \ 403*4a5d661aSToomas Soome class type *lh_first; /* first element */ \ 404*4a5d661aSToomas Soome } 405*4a5d661aSToomas Soome 406*4a5d661aSToomas Soome #define LIST_HEAD_INITIALIZER(head) \ 407*4a5d661aSToomas Soome { NULL } 408*4a5d661aSToomas Soome 409*4a5d661aSToomas Soome #define LIST_ENTRY(type) \ 410*4a5d661aSToomas Soome struct { \ 411*4a5d661aSToomas Soome struct type *le_next; /* next element */ \ 412*4a5d661aSToomas Soome struct type **le_prev; /* address of previous next element */ \ 413*4a5d661aSToomas Soome } 414*4a5d661aSToomas Soome 415*4a5d661aSToomas Soome #define LIST_CLASS_ENTRY(type) \ 416*4a5d661aSToomas Soome struct { \ 417*4a5d661aSToomas Soome class type *le_next; /* next element */ \ 418*4a5d661aSToomas Soome class type **le_prev; /* address of previous next element */ \ 419*4a5d661aSToomas Soome } 420*4a5d661aSToomas Soome 421*4a5d661aSToomas Soome /* 422*4a5d661aSToomas Soome * List functions. 423*4a5d661aSToomas Soome */ 424*4a5d661aSToomas Soome 425*4a5d661aSToomas Soome #if (defined(_KERNEL) && defined(INVARIANTS)) 426*4a5d661aSToomas Soome #define QMD_LIST_CHECK_HEAD(head, field) do { \ 427*4a5d661aSToomas Soome if (LIST_FIRST((head)) != NULL && \ 428*4a5d661aSToomas Soome LIST_FIRST((head))->field.le_prev != \ 429*4a5d661aSToomas Soome &LIST_FIRST((head))) \ 430*4a5d661aSToomas Soome panic("Bad list head %p first->prev != head", (head)); \ 431*4a5d661aSToomas Soome } while (0) 432*4a5d661aSToomas Soome 433*4a5d661aSToomas Soome #define QMD_LIST_CHECK_NEXT(elm, field) do { \ 434*4a5d661aSToomas Soome if (LIST_NEXT((elm), field) != NULL && \ 435*4a5d661aSToomas Soome LIST_NEXT((elm), field)->field.le_prev != \ 436*4a5d661aSToomas Soome &((elm)->field.le_next)) \ 437*4a5d661aSToomas Soome panic("Bad link elm %p next->prev != elm", (elm)); \ 438*4a5d661aSToomas Soome } while (0) 439*4a5d661aSToomas Soome 440*4a5d661aSToomas Soome #define QMD_LIST_CHECK_PREV(elm, field) do { \ 441*4a5d661aSToomas Soome if (*(elm)->field.le_prev != (elm)) \ 442*4a5d661aSToomas Soome panic("Bad link elm %p prev->next != elm", (elm)); \ 443*4a5d661aSToomas Soome } while (0) 444*4a5d661aSToomas Soome #else 445*4a5d661aSToomas Soome #define QMD_LIST_CHECK_HEAD(head, field) 446*4a5d661aSToomas Soome #define QMD_LIST_CHECK_NEXT(elm, field) 447*4a5d661aSToomas Soome #define QMD_LIST_CHECK_PREV(elm, field) 448*4a5d661aSToomas Soome #endif /* (_KERNEL && INVARIANTS) */ 449*4a5d661aSToomas Soome 450*4a5d661aSToomas Soome #define LIST_EMPTY(head) ((head)->lh_first == NULL) 451*4a5d661aSToomas Soome 452*4a5d661aSToomas Soome #define LIST_FIRST(head) ((head)->lh_first) 453*4a5d661aSToomas Soome 454*4a5d661aSToomas Soome #define LIST_FOREACH(var, head, field) \ 455*4a5d661aSToomas Soome for ((var) = LIST_FIRST((head)); \ 456*4a5d661aSToomas Soome (var); \ 457*4a5d661aSToomas Soome (var) = LIST_NEXT((var), field)) 458*4a5d661aSToomas Soome 459*4a5d661aSToomas Soome #define LIST_FOREACH_FROM(var, head, field) \ 460*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ 461*4a5d661aSToomas Soome (var); \ 462*4a5d661aSToomas Soome (var) = LIST_NEXT((var), field)) 463*4a5d661aSToomas Soome 464*4a5d661aSToomas Soome #define LIST_FOREACH_SAFE(var, head, field, tvar) \ 465*4a5d661aSToomas Soome for ((var) = LIST_FIRST((head)); \ 466*4a5d661aSToomas Soome (var) && ((tvar) = LIST_NEXT((var), field), 1); \ 467*4a5d661aSToomas Soome (var) = (tvar)) 468*4a5d661aSToomas Soome 469*4a5d661aSToomas Soome #define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \ 470*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : LIST_FIRST((head))); \ 471*4a5d661aSToomas Soome (var) && ((tvar) = LIST_NEXT((var), field), 1); \ 472*4a5d661aSToomas Soome (var) = (tvar)) 473*4a5d661aSToomas Soome 474*4a5d661aSToomas Soome #define LIST_INIT(head) do { \ 475*4a5d661aSToomas Soome LIST_FIRST((head)) = NULL; \ 476*4a5d661aSToomas Soome } while (0) 477*4a5d661aSToomas Soome 478*4a5d661aSToomas Soome #define LIST_INSERT_AFTER(listelm, elm, field) do { \ 479*4a5d661aSToomas Soome QMD_LIST_CHECK_NEXT(listelm, field); \ 480*4a5d661aSToomas Soome if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ 481*4a5d661aSToomas Soome LIST_NEXT((listelm), field)->field.le_prev = \ 482*4a5d661aSToomas Soome &LIST_NEXT((elm), field); \ 483*4a5d661aSToomas Soome LIST_NEXT((listelm), field) = (elm); \ 484*4a5d661aSToomas Soome (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ 485*4a5d661aSToomas Soome } while (0) 486*4a5d661aSToomas Soome 487*4a5d661aSToomas Soome #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ 488*4a5d661aSToomas Soome QMD_LIST_CHECK_PREV(listelm, field); \ 489*4a5d661aSToomas Soome (elm)->field.le_prev = (listelm)->field.le_prev; \ 490*4a5d661aSToomas Soome LIST_NEXT((elm), field) = (listelm); \ 491*4a5d661aSToomas Soome *(listelm)->field.le_prev = (elm); \ 492*4a5d661aSToomas Soome (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ 493*4a5d661aSToomas Soome } while (0) 494*4a5d661aSToomas Soome 495*4a5d661aSToomas Soome #define LIST_INSERT_HEAD(head, elm, field) do { \ 496*4a5d661aSToomas Soome QMD_LIST_CHECK_HEAD((head), field); \ 497*4a5d661aSToomas Soome if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ 498*4a5d661aSToomas Soome LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ 499*4a5d661aSToomas Soome LIST_FIRST((head)) = (elm); \ 500*4a5d661aSToomas Soome (elm)->field.le_prev = &LIST_FIRST((head)); \ 501*4a5d661aSToomas Soome } while (0) 502*4a5d661aSToomas Soome 503*4a5d661aSToomas Soome #define LIST_NEXT(elm, field) ((elm)->field.le_next) 504*4a5d661aSToomas Soome 505*4a5d661aSToomas Soome #define LIST_PREV(elm, head, type, field) \ 506*4a5d661aSToomas Soome ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ 507*4a5d661aSToomas Soome __containerof((elm)->field.le_prev, \ 508*4a5d661aSToomas Soome QUEUE_TYPEOF(type), field.le_next)) 509*4a5d661aSToomas Soome 510*4a5d661aSToomas Soome #define LIST_REMOVE(elm, field) do { \ 511*4a5d661aSToomas Soome QMD_SAVELINK(oldnext, (elm)->field.le_next); \ 512*4a5d661aSToomas Soome QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ 513*4a5d661aSToomas Soome QMD_LIST_CHECK_NEXT(elm, field); \ 514*4a5d661aSToomas Soome QMD_LIST_CHECK_PREV(elm, field); \ 515*4a5d661aSToomas Soome if (LIST_NEXT((elm), field) != NULL) \ 516*4a5d661aSToomas Soome LIST_NEXT((elm), field)->field.le_prev = \ 517*4a5d661aSToomas Soome (elm)->field.le_prev; \ 518*4a5d661aSToomas Soome *(elm)->field.le_prev = LIST_NEXT((elm), field); \ 519*4a5d661aSToomas Soome TRASHIT(*oldnext); \ 520*4a5d661aSToomas Soome TRASHIT(*oldprev); \ 521*4a5d661aSToomas Soome } while (0) 522*4a5d661aSToomas Soome 523*4a5d661aSToomas Soome #define LIST_SWAP(head1, head2, type, field) do { \ 524*4a5d661aSToomas Soome QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ 525*4a5d661aSToomas Soome LIST_FIRST((head1)) = LIST_FIRST((head2)); \ 526*4a5d661aSToomas Soome LIST_FIRST((head2)) = swap_tmp; \ 527*4a5d661aSToomas Soome if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ 528*4a5d661aSToomas Soome swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ 529*4a5d661aSToomas Soome if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ 530*4a5d661aSToomas Soome swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ 531*4a5d661aSToomas Soome } while (0) 532*4a5d661aSToomas Soome 533*4a5d661aSToomas Soome /* 534*4a5d661aSToomas Soome * Tail queue declarations. 535*4a5d661aSToomas Soome */ 536*4a5d661aSToomas Soome #define TAILQ_HEAD(name, type) \ 537*4a5d661aSToomas Soome struct name { \ 538*4a5d661aSToomas Soome struct type *tqh_first; /* first element */ \ 539*4a5d661aSToomas Soome struct type **tqh_last; /* addr of last next element */ \ 540*4a5d661aSToomas Soome TRACEBUF \ 541*4a5d661aSToomas Soome } 542*4a5d661aSToomas Soome 543*4a5d661aSToomas Soome #define TAILQ_CLASS_HEAD(name, type) \ 544*4a5d661aSToomas Soome struct name { \ 545*4a5d661aSToomas Soome class type *tqh_first; /* first element */ \ 546*4a5d661aSToomas Soome class type **tqh_last; /* addr of last next element */ \ 547*4a5d661aSToomas Soome TRACEBUF \ 548*4a5d661aSToomas Soome } 549*4a5d661aSToomas Soome 550*4a5d661aSToomas Soome #define TAILQ_HEAD_INITIALIZER(head) \ 551*4a5d661aSToomas Soome { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } 552*4a5d661aSToomas Soome 553*4a5d661aSToomas Soome #define TAILQ_ENTRY(type) \ 554*4a5d661aSToomas Soome struct { \ 555*4a5d661aSToomas Soome struct type *tqe_next; /* next element */ \ 556*4a5d661aSToomas Soome struct type **tqe_prev; /* address of previous next element */ \ 557*4a5d661aSToomas Soome TRACEBUF \ 558*4a5d661aSToomas Soome } 559*4a5d661aSToomas Soome 560*4a5d661aSToomas Soome #define TAILQ_CLASS_ENTRY(type) \ 561*4a5d661aSToomas Soome struct { \ 562*4a5d661aSToomas Soome class type *tqe_next; /* next element */ \ 563*4a5d661aSToomas Soome class type **tqe_prev; /* address of previous next element */ \ 564*4a5d661aSToomas Soome TRACEBUF \ 565*4a5d661aSToomas Soome } 566*4a5d661aSToomas Soome 567*4a5d661aSToomas Soome /* 568*4a5d661aSToomas Soome * Tail queue functions. 569*4a5d661aSToomas Soome */ 570*4a5d661aSToomas Soome #if (defined(_KERNEL) && defined(INVARIANTS)) 571*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_HEAD(head, field) do { \ 572*4a5d661aSToomas Soome if (!TAILQ_EMPTY(head) && \ 573*4a5d661aSToomas Soome TAILQ_FIRST((head))->field.tqe_prev != \ 574*4a5d661aSToomas Soome &TAILQ_FIRST((head))) \ 575*4a5d661aSToomas Soome panic("Bad tailq head %p first->prev != head", (head)); \ 576*4a5d661aSToomas Soome } while (0) 577*4a5d661aSToomas Soome 578*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_TAIL(head, field) do { \ 579*4a5d661aSToomas Soome if (*(head)->tqh_last != NULL) \ 580*4a5d661aSToomas Soome panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ 581*4a5d661aSToomas Soome } while (0) 582*4a5d661aSToomas Soome 583*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ 584*4a5d661aSToomas Soome if (TAILQ_NEXT((elm), field) != NULL && \ 585*4a5d661aSToomas Soome TAILQ_NEXT((elm), field)->field.tqe_prev != \ 586*4a5d661aSToomas Soome &((elm)->field.tqe_next)) \ 587*4a5d661aSToomas Soome panic("Bad link elm %p next->prev != elm", (elm)); \ 588*4a5d661aSToomas Soome } while (0) 589*4a5d661aSToomas Soome 590*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_PREV(elm, field) do { \ 591*4a5d661aSToomas Soome if (*(elm)->field.tqe_prev != (elm)) \ 592*4a5d661aSToomas Soome panic("Bad link elm %p prev->next != elm", (elm)); \ 593*4a5d661aSToomas Soome } while (0) 594*4a5d661aSToomas Soome #else 595*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_HEAD(head, field) 596*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_TAIL(head, headname) 597*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_NEXT(elm, field) 598*4a5d661aSToomas Soome #define QMD_TAILQ_CHECK_PREV(elm, field) 599*4a5d661aSToomas Soome #endif /* (_KERNEL && INVARIANTS) */ 600*4a5d661aSToomas Soome 601*4a5d661aSToomas Soome #define TAILQ_CONCAT(head1, head2, field) do { \ 602*4a5d661aSToomas Soome if (!TAILQ_EMPTY(head2)) { \ 603*4a5d661aSToomas Soome *(head1)->tqh_last = (head2)->tqh_first; \ 604*4a5d661aSToomas Soome (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ 605*4a5d661aSToomas Soome (head1)->tqh_last = (head2)->tqh_last; \ 606*4a5d661aSToomas Soome TAILQ_INIT((head2)); \ 607*4a5d661aSToomas Soome QMD_TRACE_HEAD(head1); \ 608*4a5d661aSToomas Soome QMD_TRACE_HEAD(head2); \ 609*4a5d661aSToomas Soome } \ 610*4a5d661aSToomas Soome } while (0) 611*4a5d661aSToomas Soome 612*4a5d661aSToomas Soome #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) 613*4a5d661aSToomas Soome 614*4a5d661aSToomas Soome #define TAILQ_FIRST(head) ((head)->tqh_first) 615*4a5d661aSToomas Soome 616*4a5d661aSToomas Soome #define TAILQ_FOREACH(var, head, field) \ 617*4a5d661aSToomas Soome for ((var) = TAILQ_FIRST((head)); \ 618*4a5d661aSToomas Soome (var); \ 619*4a5d661aSToomas Soome (var) = TAILQ_NEXT((var), field)) 620*4a5d661aSToomas Soome 621*4a5d661aSToomas Soome #define TAILQ_FOREACH_FROM(var, head, field) \ 622*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ 623*4a5d661aSToomas Soome (var); \ 624*4a5d661aSToomas Soome (var) = TAILQ_NEXT((var), field)) 625*4a5d661aSToomas Soome 626*4a5d661aSToomas Soome #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ 627*4a5d661aSToomas Soome for ((var) = TAILQ_FIRST((head)); \ 628*4a5d661aSToomas Soome (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ 629*4a5d661aSToomas Soome (var) = (tvar)) 630*4a5d661aSToomas Soome 631*4a5d661aSToomas Soome #define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ 632*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \ 633*4a5d661aSToomas Soome (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ 634*4a5d661aSToomas Soome (var) = (tvar)) 635*4a5d661aSToomas Soome 636*4a5d661aSToomas Soome #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ 637*4a5d661aSToomas Soome for ((var) = TAILQ_LAST((head), headname); \ 638*4a5d661aSToomas Soome (var); \ 639*4a5d661aSToomas Soome (var) = TAILQ_PREV((var), headname, field)) 640*4a5d661aSToomas Soome 641*4a5d661aSToomas Soome #define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \ 642*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ 643*4a5d661aSToomas Soome (var); \ 644*4a5d661aSToomas Soome (var) = TAILQ_PREV((var), headname, field)) 645*4a5d661aSToomas Soome 646*4a5d661aSToomas Soome #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ 647*4a5d661aSToomas Soome for ((var) = TAILQ_LAST((head), headname); \ 648*4a5d661aSToomas Soome (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ 649*4a5d661aSToomas Soome (var) = (tvar)) 650*4a5d661aSToomas Soome 651*4a5d661aSToomas Soome #define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \ 652*4a5d661aSToomas Soome for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \ 653*4a5d661aSToomas Soome (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ 654*4a5d661aSToomas Soome (var) = (tvar)) 655*4a5d661aSToomas Soome 656*4a5d661aSToomas Soome #define TAILQ_INIT(head) do { \ 657*4a5d661aSToomas Soome TAILQ_FIRST((head)) = NULL; \ 658*4a5d661aSToomas Soome (head)->tqh_last = &TAILQ_FIRST((head)); \ 659*4a5d661aSToomas Soome QMD_TRACE_HEAD(head); \ 660*4a5d661aSToomas Soome } while (0) 661*4a5d661aSToomas Soome 662*4a5d661aSToomas Soome #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 663*4a5d661aSToomas Soome QMD_TAILQ_CHECK_NEXT(listelm, field); \ 664*4a5d661aSToomas Soome if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ 665*4a5d661aSToomas Soome TAILQ_NEXT((elm), field)->field.tqe_prev = \ 666*4a5d661aSToomas Soome &TAILQ_NEXT((elm), field); \ 667*4a5d661aSToomas Soome else { \ 668*4a5d661aSToomas Soome (head)->tqh_last = &TAILQ_NEXT((elm), field); \ 669*4a5d661aSToomas Soome QMD_TRACE_HEAD(head); \ 670*4a5d661aSToomas Soome } \ 671*4a5d661aSToomas Soome TAILQ_NEXT((listelm), field) = (elm); \ 672*4a5d661aSToomas Soome (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ 673*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(elm)->field); \ 674*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(listelm)->field); \ 675*4a5d661aSToomas Soome } while (0) 676*4a5d661aSToomas Soome 677*4a5d661aSToomas Soome #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 678*4a5d661aSToomas Soome QMD_TAILQ_CHECK_PREV(listelm, field); \ 679*4a5d661aSToomas Soome (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 680*4a5d661aSToomas Soome TAILQ_NEXT((elm), field) = (listelm); \ 681*4a5d661aSToomas Soome *(listelm)->field.tqe_prev = (elm); \ 682*4a5d661aSToomas Soome (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ 683*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(elm)->field); \ 684*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(listelm)->field); \ 685*4a5d661aSToomas Soome } while (0) 686*4a5d661aSToomas Soome 687*4a5d661aSToomas Soome #define TAILQ_INSERT_HEAD(head, elm, field) do { \ 688*4a5d661aSToomas Soome QMD_TAILQ_CHECK_HEAD(head, field); \ 689*4a5d661aSToomas Soome if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ 690*4a5d661aSToomas Soome TAILQ_FIRST((head))->field.tqe_prev = \ 691*4a5d661aSToomas Soome &TAILQ_NEXT((elm), field); \ 692*4a5d661aSToomas Soome else \ 693*4a5d661aSToomas Soome (head)->tqh_last = &TAILQ_NEXT((elm), field); \ 694*4a5d661aSToomas Soome TAILQ_FIRST((head)) = (elm); \ 695*4a5d661aSToomas Soome (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ 696*4a5d661aSToomas Soome QMD_TRACE_HEAD(head); \ 697*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(elm)->field); \ 698*4a5d661aSToomas Soome } while (0) 699*4a5d661aSToomas Soome 700*4a5d661aSToomas Soome #define TAILQ_INSERT_TAIL(head, elm, field) do { \ 701*4a5d661aSToomas Soome QMD_TAILQ_CHECK_TAIL(head, field); \ 702*4a5d661aSToomas Soome TAILQ_NEXT((elm), field) = NULL; \ 703*4a5d661aSToomas Soome (elm)->field.tqe_prev = (head)->tqh_last; \ 704*4a5d661aSToomas Soome *(head)->tqh_last = (elm); \ 705*4a5d661aSToomas Soome (head)->tqh_last = &TAILQ_NEXT((elm), field); \ 706*4a5d661aSToomas Soome QMD_TRACE_HEAD(head); \ 707*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(elm)->field); \ 708*4a5d661aSToomas Soome } while (0) 709*4a5d661aSToomas Soome 710*4a5d661aSToomas Soome #define TAILQ_LAST(head, headname) \ 711*4a5d661aSToomas Soome (*(((struct headname *)((head)->tqh_last))->tqh_last)) 712*4a5d661aSToomas Soome 713*4a5d661aSToomas Soome #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 714*4a5d661aSToomas Soome 715*4a5d661aSToomas Soome #define TAILQ_PREV(elm, headname, field) \ 716*4a5d661aSToomas Soome (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) 717*4a5d661aSToomas Soome 718*4a5d661aSToomas Soome #define TAILQ_REMOVE(head, elm, field) do { \ 719*4a5d661aSToomas Soome QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ 720*4a5d661aSToomas Soome QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ 721*4a5d661aSToomas Soome QMD_TAILQ_CHECK_NEXT(elm, field); \ 722*4a5d661aSToomas Soome QMD_TAILQ_CHECK_PREV(elm, field); \ 723*4a5d661aSToomas Soome if ((TAILQ_NEXT((elm), field)) != NULL) \ 724*4a5d661aSToomas Soome TAILQ_NEXT((elm), field)->field.tqe_prev = \ 725*4a5d661aSToomas Soome (elm)->field.tqe_prev; \ 726*4a5d661aSToomas Soome else { \ 727*4a5d661aSToomas Soome (head)->tqh_last = (elm)->field.tqe_prev; \ 728*4a5d661aSToomas Soome QMD_TRACE_HEAD(head); \ 729*4a5d661aSToomas Soome } \ 730*4a5d661aSToomas Soome *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ 731*4a5d661aSToomas Soome TRASHIT(*oldnext); \ 732*4a5d661aSToomas Soome TRASHIT(*oldprev); \ 733*4a5d661aSToomas Soome QMD_TRACE_ELEM(&(elm)->field); \ 734*4a5d661aSToomas Soome } while (0) 735*4a5d661aSToomas Soome 736*4a5d661aSToomas Soome #define TAILQ_SWAP(head1, head2, type, field) do { \ 737*4a5d661aSToomas Soome QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ 738*4a5d661aSToomas Soome QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \ 739*4a5d661aSToomas Soome (head1)->tqh_first = (head2)->tqh_first; \ 740*4a5d661aSToomas Soome (head1)->tqh_last = (head2)->tqh_last; \ 741*4a5d661aSToomas Soome (head2)->tqh_first = swap_first; \ 742*4a5d661aSToomas Soome (head2)->tqh_last = swap_last; \ 743*4a5d661aSToomas Soome if ((swap_first = (head1)->tqh_first) != NULL) \ 744*4a5d661aSToomas Soome swap_first->field.tqe_prev = &(head1)->tqh_first; \ 745*4a5d661aSToomas Soome else \ 746*4a5d661aSToomas Soome (head1)->tqh_last = &(head1)->tqh_first; \ 747*4a5d661aSToomas Soome if ((swap_first = (head2)->tqh_first) != NULL) \ 748*4a5d661aSToomas Soome swap_first->field.tqe_prev = &(head2)->tqh_first; \ 749*4a5d661aSToomas Soome else \ 750*4a5d661aSToomas Soome (head2)->tqh_last = &(head2)->tqh_first; \ 751*4a5d661aSToomas Soome } while (0) 752*4a5d661aSToomas Soome 753*4a5d661aSToomas Soome #endif /* !_SYS_QUEUE_H_ */ 754