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