1 /* BSDI $Id: queue.h,v 2.4 1996/07/02 13:22:11 bostic Exp $ */ 2 3 /* 4 * Copyright (c) 1991, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. All advertising materials mentioning features or use of this software 16 * must display the following acknowledgement: 17 * This product includes software developed by the University of 18 * California, Berkeley and its contributors. 19 * 4. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * @(#)queue.h 8.5 (Berkeley) 8/20/94 36 * %W% (Sun) %G% 37 */ 38 /* 39 * Copyright (c) 1998 by Sun Microsystems, Inc. 40 * All rights reserved. 41 */ 42 43 #ifndef _SYS_QUEUE_H_ 44 #define _SYS_QUEUE_H_ 45 46 /* 47 * This file defines three types of data structures: lists, tail queues, 48 * and circular queues. 49 * 50 * A list is headed by a single forward pointer (or an array of forward 51 * pointers for a hash table header). The elements are doubly linked 52 * so that an arbitrary element can be removed without a need to 53 * traverse the list. New elements can be added to the list before 54 * or after an existing element or at the head of the list. A list 55 * may only be traversed in the forward direction. 56 * 57 * A tail queue is headed by a pair of pointers, one to the head of the 58 * list and the other to the tail of the list. The elements are doubly 59 * linked so that an arbitrary element can be removed without a need to 60 * traverse the list. New elements can be added to the list before or 61 * after an existing element, at the head of the list, or at the end of 62 * the list. A tail queue may only be traversed in the forward direction. 63 * 64 * A circle queue is headed by a pair of pointers, one to the head of the 65 * list and the other to the tail of the list. The elements are doubly 66 * linked so that an arbitrary element can be removed without a need to 67 * traverse the list. New elements can be added to the list before or after 68 * an existing element, at the head of the list, or at the end of the list. 69 * A circle queue may be traversed in either direction, but has a more 70 * complex end of list detection. 71 * 72 * For details on the use of these macros, see the queue(3) manual page. 73 */ 74 75 /* 76 * List definitions. 77 */ 78 #define LIST_HEAD(name, type) \ 79 struct name { \ 80 struct type *lh_first; /* first element */ \ 81 } 82 83 #define LIST_ENTRY(type) \ 84 struct { \ 85 struct type *le_next; /* next element */ \ 86 struct type **le_prev; /* address of previous next element */ \ 87 } 88 89 #define LIST_FIRST(head) ((head)->lh_first) 90 #define LIST_NEXT(elm, field) ((elm)->field.le_next) 91 #define LIST_END(head) NULL 92 93 /* 94 * List functions. 95 */ 96 #define LIST_INIT(head) { \ 97 (head)->lh_first = NULL; \ 98 } 99 100 #define LIST_INSERT_AFTER(listelm, elm, field) do { \ 101 if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \ 102 (listelm)->field.le_next->field.le_prev = \ 103 &(elm)->field.le_next; \ 104 (listelm)->field.le_next = (elm); \ 105 (elm)->field.le_prev = &(listelm)->field.le_next; \ 106 } while (0) 107 108 #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ 109 (elm)->field.le_prev = (listelm)->field.le_prev; \ 110 (elm)->field.le_next = (listelm); \ 111 *(listelm)->field.le_prev = (elm); \ 112 (listelm)->field.le_prev = &(elm)->field.le_next; \ 113 } while (0) 114 115 #define LIST_INSERT_HEAD(head, elm, field) do { \ 116 if (((elm)->field.le_next = (head)->lh_first) != NULL) \ 117 (head)->lh_first->field.le_prev = &(elm)->field.le_next;\ 118 (head)->lh_first = (elm); \ 119 (elm)->field.le_prev = &(head)->lh_first; \ 120 } while (0) 121 122 #define LIST_REMOVE(elm, field) do { \ 123 if ((elm)->field.le_next != NULL) \ 124 (elm)->field.le_next->field.le_prev = \ 125 (elm)->field.le_prev; \ 126 *(elm)->field.le_prev = (elm)->field.le_next; \ 127 } while (0) 128 129 /* 130 * Tail queue definitions. 131 */ 132 #define TAILQ_HEAD(name, type) \ 133 struct name { \ 134 struct type *tqh_first; /* first element */ \ 135 struct type **tqh_last; /* addr of last next element */ \ 136 } 137 138 #define TAILQ_ENTRY(type) \ 139 struct { \ 140 struct type *tqe_next; /* next element */ \ 141 struct type **tqe_prev; /* address of previous next element */ \ 142 } 143 144 #define TAILQ_FIRST(head) ((head)->tqh_first) 145 #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) 146 #define TAILQ_END(head) NULL 147 148 /* 149 * Tail queue functions. 150 */ 151 #define TAILQ_INIT(head) do { \ 152 (head)->tqh_first = NULL; \ 153 (head)->tqh_last = &(head)->tqh_first; \ 154 } while (0) 155 156 #define TAILQ_INSERT_HEAD(head, elm, field) do { \ 157 if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \ 158 (head)->tqh_first->field.tqe_prev = \ 159 &(elm)->field.tqe_next; \ 160 else \ 161 (head)->tqh_last = &(elm)->field.tqe_next; \ 162 (head)->tqh_first = (elm); \ 163 (elm)->field.tqe_prev = &(head)->tqh_first; \ 164 } while (0) 165 166 #define TAILQ_INSERT_TAIL(head, elm, field) do { \ 167 (elm)->field.tqe_next = NULL; \ 168 (elm)->field.tqe_prev = (head)->tqh_last; \ 169 *(head)->tqh_last = (elm); \ 170 (head)->tqh_last = &(elm)->field.tqe_next; \ 171 } while (0) 172 173 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ 174 if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\ 175 (elm)->field.tqe_next->field.tqe_prev = \ 176 &(elm)->field.tqe_next; \ 177 else \ 178 (head)->tqh_last = &(elm)->field.tqe_next; \ 179 (listelm)->field.tqe_next = (elm); \ 180 (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \ 181 } while (0) 182 183 #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ 184 (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ 185 (elm)->field.tqe_next = (listelm); \ 186 *(listelm)->field.tqe_prev = (elm); \ 187 (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \ 188 } while (0) 189 190 #define TAILQ_REMOVE(head, elm, field) do { \ 191 if (((elm)->field.tqe_next) != NULL) \ 192 (elm)->field.tqe_next->field.tqe_prev = \ 193 (elm)->field.tqe_prev; \ 194 else \ 195 (head)->tqh_last = (elm)->field.tqe_prev; \ 196 *(elm)->field.tqe_prev = (elm)->field.tqe_next; \ 197 } while (0) 198 199 /* 200 * Circular queue definitions. 201 */ 202 #define CIRCLEQ_HEAD(name, type) \ 203 struct name { \ 204 struct type *cqh_first; /* first element */ \ 205 struct type *cqh_last; /* last element */ \ 206 } 207 208 #define CIRCLEQ_ENTRY(type) \ 209 struct { \ 210 struct type *cqe_next; /* next element */ \ 211 struct type *cqe_prev; /* previous element */ \ 212 } 213 214 #define CIRCLEQ_FIRST(head) ((head)->cqh_first) 215 #define CIRCLEQ_LAST(head) ((head)->cqh_last) 216 #define CIRCLEQ_END(head) ((void *)(head)) 217 #define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next) 218 #define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev) 219 220 /* 221 * Circular queue functions. 222 */ 223 #define CIRCLEQ_INIT(head) do { \ 224 (head)->cqh_first = (void *)(head); \ 225 (head)->cqh_last = (void *)(head); \ 226 } while (0) 227 228 #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \ 229 (elm)->field.cqe_next = (listelm)->field.cqe_next; \ 230 (elm)->field.cqe_prev = (listelm); \ 231 if ((listelm)->field.cqe_next == (void *)(head)) \ 232 (head)->cqh_last = (elm); \ 233 else \ 234 (listelm)->field.cqe_next->field.cqe_prev = (elm); \ 235 (listelm)->field.cqe_next = (elm); \ 236 } while (0) 237 238 #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \ 239 (elm)->field.cqe_next = (listelm); \ 240 (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \ 241 if ((listelm)->field.cqe_prev == (void *)(head)) \ 242 (head)->cqh_first = (elm); \ 243 else \ 244 (listelm)->field.cqe_prev->field.cqe_next = (elm); \ 245 (listelm)->field.cqe_prev = (elm); \ 246 } while (0) 247 248 #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \ 249 (elm)->field.cqe_next = (head)->cqh_first; \ 250 (elm)->field.cqe_prev = (void *)(head); \ 251 if ((head)->cqh_last == (void *)(head)) \ 252 (head)->cqh_last = (elm); \ 253 else \ 254 (head)->cqh_first->field.cqe_prev = (elm); \ 255 (head)->cqh_first = (elm); \ 256 } while (0) 257 258 #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \ 259 (elm)->field.cqe_next = (void *)(head); \ 260 (elm)->field.cqe_prev = (head)->cqh_last; \ 261 if ((head)->cqh_first == (void *)(head)) \ 262 (head)->cqh_first = (elm); \ 263 else \ 264 (head)->cqh_last->field.cqe_next = (elm); \ 265 (head)->cqh_last = (elm); \ 266 } while (0) 267 268 #define CIRCLEQ_REMOVE(head, elm, field) do { \ 269 if ((elm)->field.cqe_next == (void *)(head)) \ 270 (head)->cqh_last = (elm)->field.cqe_prev; \ 271 else \ 272 (elm)->field.cqe_next->field.cqe_prev = \ 273 (elm)->field.cqe_prev; \ 274 if ((elm)->field.cqe_prev == (void *)(head)) \ 275 (head)->cqh_first = (elm)->field.cqe_next; \ 276 else \ 277 (elm)->field.cqe_prev->field.cqe_next = \ 278 (elm)->field.cqe_next; \ 279 } while (0) 280 #endif /* !_SYS_QUEUE_H_ */ 281