|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * Copyright (c) 1991, 1993
24: * The Regents of the University of California. All rights reserved.
25: *
26: * Redistribution and use in source and binary forms, with or without
27: * modification, are permitted provided that the following conditions
28: * are met:
29: * 1. Redistributions of source code must retain the above copyright
30: * notice, this list of conditions and the following disclaimer.
31: * 2. Redistributions in binary form must reproduce the above copyright
32: * notice, this list of conditions and the following disclaimer in the
33: * documentation and/or other materials provided with the distribution.
34: * 3. All advertising materials mentioning features or use of this software
35: * must display the following acknowledgement:
36: * This product includes software developed by the University of
37: * California, Berkeley and its contributors.
38: * 4. Neither the name of the University nor the names of its contributors
39: * may be used to endorse or promote products derived from this software
40: * without specific prior written permission.
41: *
42: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
43: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
44: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
45: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
46: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
47: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
48: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
49: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
50: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
51: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52: * SUCH DAMAGE.
53: *
54: * @(#)queue.h 8.5 (Berkeley) 8/20/94
55: */
56:
57: #ifndef _SYS_QUEUE_H_
58: #define _SYS_QUEUE_H_
59:
60: /*
61: * This file defines five types of data structures: singly-linked lists,
62: * slingly-linked tail queues, lists, tail queues, and circular queues.
63: *
64: * A singly-linked list is headed by a single forward pointer. The elements
65: * are singly linked for minimum space and pointer manipulation overhead at
66: * the expense of O(n) removal for arbitrary elements. New elements can be
67: * added to the list after an existing element or at the head of the list.
68: * Elements being removed from the head of the list should use the explicit
69: * macro for this purpose for optimum efficiency. A singly-linked list may
70: * only be traversed in the forward direction. Singly-linked lists are ideal
71: * for applications with large datasets and few or no removals or for
72: * implementing a LIFO queue.
73: *
74: * A singly-linked tail queue is headed by a pair of pointers, one to the
75: * head of the list and the other to the tail of the list. The elements are
76: * singly linked for minimum space and pointer manipulation overhead at the
77: * expense of O(n) removal for arbitrary elements. New elements can be added
78: * to the list after an existing element, at the head of the list, or at the
79: * end of the list. Elements being removed from the head of the tail queue
80: * should use the explicit macro for this purpose for optimum efficiency.
81: * A singly-linked tail queue may only be traversed in the forward direction.
82: * Singly-linked tail queues are ideal for applications with large datasets
83: * and few or no removals or for implementing a FIFO queue.
84: *
85: * A list is headed by a single forward pointer (or an array of forward
86: * pointers for a hash table header). The elements are doubly linked
87: * so that an arbitrary element can be removed without a need to
88: * traverse the list. New elements can be added to the list before
89: * or after an existing element or at the head of the list. A list
90: * may only be traversed in the forward direction.
91: *
92: * A tail queue is headed by a pair of pointers, one to the head of the
93: * list and the other to the tail of the list. The elements are doubly
94: * linked so that an arbitrary element can be removed without a need to
95: * traverse the list. New elements can be added to the list before or
96: * after an existing element, at the head of the list, or at the end of
97: * the list. A tail queue may only be traversed in the forward direction.
98: *
99: * A circle queue is headed by a pair of pointers, one to the head of the
100: * list and the other to the tail of the list. The elements are doubly
101: * linked so that an arbitrary element can be removed without a need to
102: * traverse the list. New elements can be added to the list before or after
103: * an existing element, at the head of the list, or at the end of the list.
104: * A circle queue may be traversed in either direction, but has a more
105: * complex end of list detection.
106: *
107: * For details on the use of these macros, see the queue(3) manual page.
108: *
109: *
110: * SLIST LIST STAILQ TAILQ CIRCLEQ
111: * _HEAD + + + + +
112: * _ENTRY + + + + +
113: * _INIT + + + + +
114: * _EMPTY + + + + +
115: * _FIRST + + + + +
116: * _NEXT + + + + +
117: * _PREV - - - + +
118: * _LAST - - + + +
119: * _FOREACH + + - + +
120: * _INSERT_HEAD + + + + +
121: * _INSERT_BEFORE - + - + +
122: * _INSERT_AFTER + + + + +
123: * _INSERT_TAIL - - + + +
124: * _REMOVE_HEAD + - + - -
125: * _REMOVE + + + + +
126: *
127: */
128:
129: /*
130: * Singly-linked List definitions.
131: */
132: #define SLIST_HEAD(name, type) \
133: struct name { \
134: struct type *slh_first; /* first element */ \
135: }
136:
137: #define SLIST_ENTRY(type) \
138: struct { \
139: struct type *sle_next; /* next element */ \
140: }
141:
142: /*
143: * Singly-linked List functions.
144: */
145: #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
146:
147: #define SLIST_FIRST(head) ((head)->slh_first)
148:
149: #define SLIST_FOREACH(var, head, field) \
150: for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
151:
152: #define SLIST_INIT(head) { \
153: (head)->slh_first = NULL; \
154: }
155:
156: #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
157: (elm)->field.sle_next = (slistelm)->field.sle_next; \
158: (slistelm)->field.sle_next = (elm); \
159: } while (0)
160:
161: #define SLIST_INSERT_HEAD(head, elm, field) do { \
162: (elm)->field.sle_next = (head)->slh_first; \
163: (head)->slh_first = (elm); \
164: } while (0)
165:
166: #define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
167:
168: #define SLIST_REMOVE_HEAD(head, field) do { \
169: (head)->slh_first = (head)->slh_first->field.sle_next; \
170: } while (0)
171:
172: #define SLIST_REMOVE(head, elm, type, field) do { \
173: if ((head)->slh_first == (elm)) { \
174: SLIST_REMOVE_HEAD((head), field); \
175: } \
176: else { \
177: struct type *curelm = (head)->slh_first; \
178: while( curelm->field.sle_next != (elm) ) \
179: curelm = curelm->field.sle_next; \
180: curelm->field.sle_next = \
181: curelm->field.sle_next->field.sle_next; \
182: } \
183: } while (0)
184:
185: /*
186: * Singly-linked Tail queue definitions.
187: */
188: #define STAILQ_HEAD(name, type) \
189: struct name { \
190: struct type *stqh_first;/* first element */ \
191: struct type **stqh_last;/* addr of last next element */ \
192: }
193:
194: #define STAILQ_HEAD_INITIALIZER(head) \
195: { NULL, &(head).stqh_first }
196:
197: #define STAILQ_ENTRY(type) \
198: struct { \
199: struct type *stqe_next; /* next element */ \
200: }
201:
202: /*
203: * Singly-linked Tail queue functions.
204: */
205: #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
206:
207: #define STAILQ_INIT(head) do { \
208: (head)->stqh_first = NULL; \
209: (head)->stqh_last = &(head)->stqh_first; \
210: } while (0)
211:
212: #define STAILQ_FIRST(head) ((head)->stqh_first)
213: #define STAILQ_LAST(head) (*(head)->stqh_last)
214:
215: #define STAILQ_INSERT_HEAD(head, elm, field) do { \
216: if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
217: (head)->stqh_last = &(elm)->field.stqe_next; \
218: (head)->stqh_first = (elm); \
219: } while (0)
220:
221: #define STAILQ_INSERT_TAIL(head, elm, field) do { \
222: (elm)->field.stqe_next = NULL; \
223: *(head)->stqh_last = (elm); \
224: (head)->stqh_last = &(elm)->field.stqe_next; \
225: } while (0)
226:
227: #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
228: if (((elm)->field.stqe_next = (tqelm)->field.stqe_next) == NULL)\
229: (head)->stqh_last = &(elm)->field.stqe_next; \
230: (tqelm)->field.stqe_next = (elm); \
231: } while (0)
232:
233: #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
234:
235: #define STAILQ_REMOVE_HEAD(head, field) do { \
236: if (((head)->stqh_first = \
237: (head)->stqh_first->field.stqe_next) == NULL) \
238: (head)->stqh_last = &(head)->stqh_first; \
239: } while (0)
240:
241: #define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \
242: if (((head)->stqh_first = (elm)->field.stqe_next) == NULL) \
243: (head)->stqh_last = &(head)->stqh_first; \
244: } while (0)
245:
246:
247: #define STAILQ_REMOVE(head, elm, type, field) do { \
248: if ((head)->stqh_first == (elm)) { \
249: STAILQ_REMOVE_HEAD(head, field); \
250: } \
251: else { \
252: struct type *curelm = (head)->stqh_first; \
253: while( curelm->field.stqe_next != (elm) ) \
254: curelm = curelm->field.stqe_next; \
255: if((curelm->field.stqe_next = \
256: curelm->field.stqe_next->field.stqe_next) == NULL) \
257: (head)->stqh_last = &(curelm)->field.stqe_next; \
258: } \
259: } while (0)
260:
261: /*
262: * List definitions.
263: */
264: #define LIST_HEAD(name, type) \
265: struct name { \
266: struct type *lh_first; /* first element */ \
267: }
268:
269: #define LIST_HEAD_INITIALIZER(head) \
270: { NULL }
271:
272: #define LIST_ENTRY(type) \
273: struct { \
274: struct type *le_next; /* next element */ \
275: struct type **le_prev; /* address of previous next element */ \
276: }
277:
278: /*
279: * List functions.
280: */
281:
282: #define LIST_EMPTY(head) ((head)->lh_first == NULL)
283:
284: #define LIST_FIRST(head) ((head)->lh_first)
285:
286: #define LIST_FOREACH(var, head, field) \
287: for((var) = (head)->lh_first; (var); (var) = (var)->field.le_next)
288:
289: #define LIST_INIT(head) do { \
290: (head)->lh_first = NULL; \
291: } while (0)
292:
293: #define LIST_INSERT_AFTER(listelm, elm, field) do { \
294: if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
295: (listelm)->field.le_next->field.le_prev = \
296: &(elm)->field.le_next; \
297: (listelm)->field.le_next = (elm); \
298: (elm)->field.le_prev = &(listelm)->field.le_next; \
299: } while (0)
300:
301: #define LIST_INSERT_BEFORE(listelm, elm, field) do { \
302: (elm)->field.le_prev = (listelm)->field.le_prev; \
303: (elm)->field.le_next = (listelm); \
304: *(listelm)->field.le_prev = (elm); \
305: (listelm)->field.le_prev = &(elm)->field.le_next; \
306: } while (0)
307:
308: #define LIST_INSERT_HEAD(head, elm, field) do { \
309: if (((elm)->field.le_next = (head)->lh_first) != NULL) \
310: (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
311: (head)->lh_first = (elm); \
312: (elm)->field.le_prev = &(head)->lh_first; \
313: } while (0)
314:
315: #define LIST_NEXT(elm, field) ((elm)->field.le_next)
316:
317: #define LIST_REMOVE(elm, field) do { \
318: if ((elm)->field.le_next != NULL) \
319: (elm)->field.le_next->field.le_prev = \
320: (elm)->field.le_prev; \
321: *(elm)->field.le_prev = (elm)->field.le_next; \
322: } while (0)
323:
324: /*
325: * Tail queue definitions.
326: */
327: #define TAILQ_HEAD(name, type) \
328: struct name { \
329: struct type *tqh_first; /* first element */ \
330: struct type **tqh_last; /* addr of last next element */ \
331: }
332:
333: #define TAILQ_HEAD_INITIALIZER(head) \
334: { NULL, &(head).tqh_first }
335:
336: #define TAILQ_ENTRY(type) \
337: struct { \
338: struct type *tqe_next; /* next element */ \
339: struct type **tqe_prev; /* address of previous next element */ \
340: }
341:
342: /*
343: * Tail queue functions.
344: */
345: #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
346:
347: #define TAILQ_FOREACH(var, head, field) \
348: for (var = TAILQ_FIRST(head); var; var = TAILQ_NEXT(var, field))
349:
350: #define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
351: for (var = TAILQ_LAST(head, headname); \
352: var; var = TAILQ_PREV(var, headname, field))
353:
354: #define TAILQ_FIRST(head) ((head)->tqh_first)
355:
356: #define TAILQ_LAST(head, headname) \
357: (*(((struct headname *)((head)->tqh_last))->tqh_last))
358:
359: #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
360:
361: #define TAILQ_PREV(elm, headname, field) \
362: (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
363:
364: #define TAILQ_INIT(head) do { \
365: (head)->tqh_first = NULL; \
366: (head)->tqh_last = &(head)->tqh_first; \
367: } while (0)
368:
369: #define TAILQ_INSERT_HEAD(head, elm, field) do { \
370: if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
371: (head)->tqh_first->field.tqe_prev = \
372: &(elm)->field.tqe_next; \
373: else \
374: (head)->tqh_last = &(elm)->field.tqe_next; \
375: (head)->tqh_first = (elm); \
376: (elm)->field.tqe_prev = &(head)->tqh_first; \
377: } while (0)
378:
379: #define TAILQ_INSERT_TAIL(head, elm, field) do { \
380: (elm)->field.tqe_next = NULL; \
381: (elm)->field.tqe_prev = (head)->tqh_last; \
382: *(head)->tqh_last = (elm); \
383: (head)->tqh_last = &(elm)->field.tqe_next; \
384: } while (0)
385:
386: #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
387: if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
388: (elm)->field.tqe_next->field.tqe_prev = \
389: &(elm)->field.tqe_next; \
390: else \
391: (head)->tqh_last = &(elm)->field.tqe_next; \
392: (listelm)->field.tqe_next = (elm); \
393: (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
394: } while (0)
395:
396: #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
397: (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
398: (elm)->field.tqe_next = (listelm); \
399: *(listelm)->field.tqe_prev = (elm); \
400: (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
401: } while (0)
402:
403: #define TAILQ_REMOVE(head, elm, field) do { \
404: if (((elm)->field.tqe_next) != NULL) \
405: (elm)->field.tqe_next->field.tqe_prev = \
406: (elm)->field.tqe_prev; \
407: else \
408: (head)->tqh_last = (elm)->field.tqe_prev; \
409: *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
410: } while (0)
411:
412: /*
413: * Circular queue definitions.
414: */
415: #define CIRCLEQ_HEAD(name, type) \
416: struct name { \
417: struct type *cqh_first; /* first element */ \
418: struct type *cqh_last; /* last element */ \
419: }
420:
421: #define CIRCLEQ_ENTRY(type) \
422: struct { \
423: struct type *cqe_next; /* next element */ \
424: struct type *cqe_prev; /* previous element */ \
425: }
426:
427: /*
428: * Circular queue functions.
429: */
430: #define CIRCLEQ_EMPTY(head) ((head)->cqh_first == (void *)(head))
431:
432: #define CIRCLEQ_FIRST(head) ((head)->cqh_first)
433:
434: #define CIRCLEQ_FOREACH(var, head, field) \
435: for((var) = (head)->cqh_first; \
436: (var) != (void *)(head); \
437: (var) = (var)->field.cqe_next)
438:
439: #define CIRCLEQ_INIT(head) do { \
440: (head)->cqh_first = (void *)(head); \
441: (head)->cqh_last = (void *)(head); \
442: } while (0)
443:
444: #define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
445: (elm)->field.cqe_next = (listelm)->field.cqe_next; \
446: (elm)->field.cqe_prev = (listelm); \
447: if ((listelm)->field.cqe_next == (void *)(head)) \
448: (head)->cqh_last = (elm); \
449: else \
450: (listelm)->field.cqe_next->field.cqe_prev = (elm); \
451: (listelm)->field.cqe_next = (elm); \
452: } while (0)
453:
454: #define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
455: (elm)->field.cqe_next = (listelm); \
456: (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
457: if ((listelm)->field.cqe_prev == (void *)(head)) \
458: (head)->cqh_first = (elm); \
459: else \
460: (listelm)->field.cqe_prev->field.cqe_next = (elm); \
461: (listelm)->field.cqe_prev = (elm); \
462: } while (0)
463:
464: #define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
465: (elm)->field.cqe_next = (head)->cqh_first; \
466: (elm)->field.cqe_prev = (void *)(head); \
467: if ((head)->cqh_last == (void *)(head)) \
468: (head)->cqh_last = (elm); \
469: else \
470: (head)->cqh_first->field.cqe_prev = (elm); \
471: (head)->cqh_first = (elm); \
472: } while (0)
473:
474: #define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
475: (elm)->field.cqe_next = (void *)(head); \
476: (elm)->field.cqe_prev = (head)->cqh_last; \
477: if ((head)->cqh_first == (void *)(head)) \
478: (head)->cqh_first = (elm); \
479: else \
480: (head)->cqh_last->field.cqe_next = (elm); \
481: (head)->cqh_last = (elm); \
482: } while (0)
483:
484: #define CIRCLEQ_LAST(head) ((head)->cqh_last)
485:
486: #define CIRCLEQ_NEXT(elm,field) ((elm)->field.cqe_next)
487:
488: #define CIRCLEQ_PREV(elm,field) ((elm)->field.cqe_prev)
489:
490: #define CIRCLEQ_REMOVE(head, elm, field) do { \
491: if ((elm)->field.cqe_next == (void *)(head)) \
492: (head)->cqh_last = (elm)->field.cqe_prev; \
493: else \
494: (elm)->field.cqe_next->field.cqe_prev = \
495: (elm)->field.cqe_prev; \
496: if ((elm)->field.cqe_prev == (void *)(head)) \
497: (head)->cqh_first = (elm)->field.cqe_next; \
498: else \
499: (elm)->field.cqe_prev->field.cqe_next = \
500: (elm)->field.cqe_next; \
501: } while (0)
502:
503: #ifdef KERNEL
504:
505: #if NOTFB31
506:
507: /*
508: * XXX insque() and remque() are an old way of handling certain queues.
509: * They bogusly assumes that all queue heads look alike.
510: */
511:
512: struct quehead {
513: struct quehead *qh_link;
514: struct quehead *qh_rlink;
515: };
516:
517: #ifdef __GNUC__
518:
519: static __inline void
520: insque(void *a, void *b)
521: {
522: struct quehead *element = a, *head = b;
523:
524: element->qh_link = head->qh_link;
525: element->qh_rlink = head;
526: head->qh_link = element;
527: element->qh_link->qh_rlink = element;
528: }
529:
530: static __inline void
531: remque(void *a)
532: {
533: struct quehead *element = a;
534:
535: element->qh_link->qh_rlink = element->qh_rlink;
536: element->qh_rlink->qh_link = element->qh_link;
537: element->qh_rlink = 0;
538: }
539:
540: #else /* !__GNUC__ */
541:
542: void insque __P((void *a, void *b));
543: void remque __P((void *a));
544:
545: #endif /* __GNUC__ */
546:
547: #endif
548: #endif /* KERNEL */
549:
550: #endif /* !_SYS_QUEUE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.