Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
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_ */ |