2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
28 * All Rights Reserved.
30 * Permission to use, copy, modify and distribute this software and its
31 * documentation is hereby granted, provided that both the copyright
32 * notice and this permission notice appear in all copies of the
33 * software, derivative works or modified versions, and any portions
34 * thereof, and that both notices appear in supporting documentation.
36 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
37 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
38 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
40 * Carnegie Mellon requests users of this software to return to
42 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
43 * School of Computer Science
44 * Carnegie Mellon University
45 * Pittsburgh PA 15213-3890
47 * any improvements or extensions that they make and grant Carnegie Mellon rights
48 * to redistribute these changes.
54 * Author: Avadis Tevanian, Jr.
57 * Type definitions for generic queues.
61 #ifndef _KERN_QUEUE_H_
62 #define _KERN_QUEUE_H_
64 #include <mach/mach_types.h>
65 #include <kern/macro_help.h>
68 * Queue of abstract objects. Queue is maintained
71 * Supports fast removal from within the queue.
73 * How to declare a queue of elements of type "foo_t":
74 * In the "*foo_t" type, you must have a field of
75 * type "queue_chain_t" to hold together this queue.
76 * There may be more than one chain through a
77 * "foo_t", for use by different queues.
79 * Declare the queue as a "queue_t" type.
81 * Elements of the queue (of type "foo_t", that is)
82 * are referred to by reference, and cast to type
83 * "queue_entry_t" within this module.
87 * A generic doubly-linked list (queue).
91 struct queue_entry
*next
; /* next element */
92 struct queue_entry
*prev
; /* previous element */
95 typedef struct queue_entry
*queue_t
;
96 typedef struct queue_entry queue_head_t
;
97 typedef struct queue_entry queue_chain_t
;
98 typedef struct queue_entry
*queue_entry_t
;
101 * enqueue puts "elt" on the "queue".
102 * dequeue returns the first element in the "queue".
103 * remqueue removes the specified "elt" from the specified "queue".
106 #define enqueue(queue,elt) enqueue_tail(queue, elt)
107 #define dequeue(queue) dequeue_head(queue)
109 #if !defined(__GNUC__)
111 #include <sys/cdefs.h>
114 /* Enqueue element to head of queue */
115 extern void enqueue_head(
119 /* Enqueue element to tail of queue */
120 extern void enqueue_tail(
124 /* Dequeue element from head of queue */
125 extern queue_entry_t
dequeue_head(
128 /* Dequeue element from tail of queue */
129 extern queue_entry_t
dequeue_tail(
132 /* Dequeue element */
133 extern void remqueue(
137 /* Enqueue element after a particular elem */
142 /* Dequeue element */
148 #else /* !__GNUC__ */
150 static __inline__
void
155 elt
->next
= que
->next
;
157 elt
->next
->prev
= elt
;
161 static __inline__
void
167 elt
->prev
= que
->prev
;
168 elt
->prev
->next
= elt
;
172 static __inline__ queue_entry_t
176 register queue_entry_t elt
= (queue_entry_t
) 0;
178 if (que
->next
!= que
) {
180 elt
->next
->prev
= que
;
181 que
->next
= elt
->next
;
187 static __inline__ queue_entry_t
191 register queue_entry_t elt
= (queue_entry_t
) 0;
193 if (que
->prev
!= que
) {
195 elt
->prev
->next
= que
;
196 que
->prev
= elt
->prev
;
202 static __inline__
void
204 __unused queue_t que
,
207 elt
->next
->prev
= elt
->prev
;
208 elt
->prev
->next
= elt
->next
;
211 static __inline__
void
216 entry
->next
= pred
->next
;
218 (pred
->next
)->prev
= entry
;
222 static __inline__ integer_t
224 register queue_entry_t elt
)
226 (elt
->next
)->prev
= elt
->prev
;
227 (elt
->prev
)->next
= elt
->next
;
229 return((integer_t
)elt
);
232 #endif /* !__GNUC__ */
237 * Initialize the given queue.
240 * queue_t q; \* MODIFIED *\
242 #define queue_init(q) \
251 * Returns the first entry in the queue,
253 * queue_entry_t queue_first(q)
254 * queue_t q; \* IN *\
256 #define queue_first(q) ((q)->next)
261 * Returns the entry after an item in the queue.
263 * queue_entry_t queue_next(qc)
266 #define queue_next(qc) ((qc)->next)
271 * Returns the last entry in the queue.
273 * queue_entry_t queue_last(q)
274 * queue_t q; \* IN *\
276 #define queue_last(q) ((q)->prev)
281 * Returns the entry before an item in the queue.
283 * queue_entry_t queue_prev(qc)
286 #define queue_prev(qc) ((qc)->prev)
291 * Tests whether a new entry is really the end of
294 * boolean_t queue_end(q, qe)
298 #define queue_end(q, qe) ((q) == (qe))
303 * Tests whether a queue is empty.
305 * boolean_t queue_empty(q)
308 #define queue_empty(q) queue_end((q), queue_first(q))
311 /*----------------------------------------------------------------*/
313 * Macros that operate on generic structures. The queue
314 * chain may be at any location within the structure, and there
315 * may be more than one chain.
321 * Insert a new element at the tail of the queue.
323 * void queue_enter(q, elt, type, field)
326 * <type> is what's in our queue
327 * <field> is the chain field in (*<type>)
329 #define queue_enter(head, elt, type, field) \
331 register queue_entry_t __prev; \
333 __prev = (head)->prev; \
334 if ((head) == __prev) { \
335 (head)->next = (queue_entry_t) (elt); \
338 ((type)__prev)->field.next = (queue_entry_t)(elt);\
340 (elt)->field.prev = __prev; \
341 (elt)->field.next = head; \
342 (head)->prev = (queue_entry_t) elt; \
346 * Macro: queue_enter_first
348 * Insert a new element at the head of the queue.
350 * void queue_enter_first(q, elt, type, field)
353 * <type> is what's in our queue
354 * <field> is the chain field in (*<type>)
356 #define queue_enter_first(head, elt, type, field) \
358 register queue_entry_t __next; \
360 __next = (head)->next; \
361 if ((head) == __next) { \
362 (head)->prev = (queue_entry_t) (elt); \
365 ((type)__next)->field.prev = (queue_entry_t)(elt);\
367 (elt)->field.next = __next; \
368 (elt)->field.prev = head; \
369 (head)->next = (queue_entry_t) elt; \
373 * Macro: queue_insert_before
375 * Insert a new element before a given element.
377 * void queue_insert_before(q, elt, cur, type, field)
381 * <type> is what's in our queue
382 * <field> is the chain field in (*<type>)
384 #define queue_insert_before(head, elt, cur, type, field) \
386 register queue_entry_t __prev; \
388 if ((head) == (queue_entry_t)(cur)) { \
389 (elt)->field.next = (head); \
390 if ((head)->next == (head)) { /* only element */ \
391 (elt)->field.prev = (head); \
392 (head)->next = (queue_entry_t)(elt); \
393 } else { /* last element */ \
394 __prev = (elt)->field.prev = (head)->prev; \
395 ((type)__prev)->field.next = (queue_entry_t)(elt);\
397 (head)->prev = (queue_entry_t)(elt); \
399 (elt)->field.next = (queue_entry_t)(cur); \
400 if ((head)->next == (queue_entry_t)(cur)) { \
401 /* first element */ \
402 (elt)->field.prev = (head); \
403 (head)->next = (queue_entry_t)(elt); \
404 } else { /* middle element */ \
405 __prev = (elt)->field.prev = (cur)->field.prev; \
406 ((type)__prev)->field.next = (queue_entry_t)(elt);\
408 (cur)->field.prev = (queue_entry_t)(elt); \
413 * Macro: queue_insert_after
415 * Insert a new element after a given element.
417 * void queue_insert_after(q, elt, cur, type, field)
421 * <type> is what's in our queue
422 * <field> is the chain field in (*<type>)
424 #define queue_insert_after(head, elt, cur, type, field) \
426 register queue_entry_t __next; \
428 if ((head) == (queue_entry_t)(cur)) { \
429 (elt)->field.prev = (head); \
430 if ((head)->next == (head)) { /* only element */ \
431 (elt)->field.next = (head); \
432 (head)->prev = (queue_entry_t)(elt); \
433 } else { /* first element */ \
434 __next = (elt)->field.next = (head)->next; \
435 ((type)__next)->field.prev = (queue_entry_t)(elt);\
437 (head)->next = (queue_entry_t)(elt); \
439 (elt)->field.prev = (queue_entry_t)(cur); \
440 if ((head)->prev == (queue_entry_t)(cur)) { \
442 (elt)->field.next = (head); \
443 (head)->prev = (queue_entry_t)(elt); \
444 } else { /* middle element */ \
445 __next = (elt)->field.next = (cur)->field.next; \
446 ((type)__next)->field.prev = (queue_entry_t)(elt);\
448 (cur)->field.next = (queue_entry_t)(elt); \
453 * Macro: queue_field [internal use only]
455 * Find the queue_chain_t (or queue_t) for the
456 * given element (thing) in the given queue (head)
458 #define queue_field(head, thing, type, field) \
459 (((head) == (thing)) ? (head) : &((type)(thing))->field)
462 * Macro: queue_remove
464 * Remove an arbitrary item from the queue.
466 * void queue_remove(q, qe, type, field)
467 * arguments as in queue_enter
469 #define queue_remove(head, elt, type, field) \
471 register queue_entry_t __next, __prev; \
473 __next = (elt)->field.next; \
474 __prev = (elt)->field.prev; \
476 if ((head) == __next) \
477 (head)->prev = __prev; \
479 ((type)__next)->field.prev = __prev; \
481 if ((head) == __prev) \
482 (head)->next = __next; \
484 ((type)__prev)->field.next = __next; \
488 * Macro: queue_remove_first
490 * Remove and return the entry at the head of
493 * queue_remove_first(head, entry, type, field)
494 * entry is returned by reference
496 #define queue_remove_first(head, entry, type, field) \
498 register queue_entry_t __next; \
500 (entry) = (type) ((head)->next); \
501 __next = (entry)->field.next; \
503 if ((head) == __next) \
504 (head)->prev = (head); \
506 ((type)(__next))->field.prev = (head); \
507 (head)->next = __next; \
511 * Macro: queue_remove_last
513 * Remove and return the entry at the tail of
516 * queue_remove_last(head, entry, type, field)
517 * entry is returned by reference
519 #define queue_remove_last(head, entry, type, field) \
521 register queue_entry_t __prev; \
523 (entry) = (type) ((head)->prev); \
524 __prev = (entry)->field.prev; \
526 if ((head) == __prev) \
527 (head)->next = (head); \
529 ((type)(__prev))->field.next = (head); \
530 (head)->prev = __prev; \
534 * Macro: queue_assign
536 #define queue_assign(to, from, type, field) \
538 ((type)((from)->prev))->field.next = (to); \
539 ((type)((from)->next))->field.prev = (to); \
544 * Macro: queue_new_head
546 * rebase old queue to new queue head
548 * queue_new_head(old, new, type, field)
551 * <type> is what's in our queue
552 * <field> is the chain field in (*<type>)
554 #define queue_new_head(old, new, type, field) \
556 if (!queue_empty(old)) { \
558 ((type)((new)->next))->field.prev = (new); \
559 ((type)((new)->prev))->field.next = (new); \
566 * Macro: queue_iterate
568 * iterate over each item in the queue.
569 * Generates a 'for' loop, setting elt to
570 * each item in turn (by reference).
572 * queue_iterate(q, elt, type, field)
575 * <type> is what's in our queue
576 * <field> is the chain field in (*<type>)
578 #define queue_iterate(head, elt, type, field) \
579 for ((elt) = (type) queue_first(head); \
580 !queue_end((head), (queue_entry_t)(elt)); \
581 (elt) = (type) queue_next(&(elt)->field))
583 #ifdef MACH_KERNEL_PRIVATE
585 #include <kern/lock.h>
587 /*----------------------------------------------------------------*/
589 * Define macros for queues with locks.
591 struct mpqueue_head
{
592 struct queue_entry head
; /* header for queue */
593 decl_simple_lock_data(, lock
) /* lock for queue */
596 typedef struct mpqueue_head mpqueue_head_t
;
598 #define round_mpq(size) (size)
600 #define mpqueue_init(q) \
602 queue_init(&(q)->head); \
603 simple_lock_init(&(q)->lock, 0); \
606 #define mpenqueue_tail(q, elt) \
608 simple_lock(&(q)->lock); \
609 enqueue_tail(&(q)->head, elt); \
610 simple_unlock(&(q)->lock); \
613 #define mpdequeue_head(q, elt) \
615 simple_lock(&(q)->lock); \
616 if (queue_empty(&(q)->head)) \
619 *(elt) = dequeue_head(&(q)->head); \
620 simple_unlock(&(q)->lock); \
623 #endif /* MACH_KERNEL_PRIVATE */
625 #endif /* _KERN_QUEUE_H_ */