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