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