netwerk/sctp/src/user_queue.h

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rwxr-xr-x

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

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

mercurial