2 * Copyright (c) 2000-2005 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
27 * Mach Operating System
28 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
29 * All Rights Reserved.
31 * Permission to use, copy, modify and distribute this software and its
32 * documentation is hereby granted, provided that both the copyright
33 * notice and this permission notice appear in all copies of the
34 * software, derivative works or modified versions, and any portions
35 * thereof, and that both notices appear in supporting documentation.
37 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
38 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
39 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
41 * Carnegie Mellon requests users of this software to return to
43 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
44 * School of Computer Science
45 * Carnegie Mellon University
46 * Pittsburgh PA 15213-3890
48 * any improvements or extensions that they make and grant Carnegie Mellon rights
49 * to redistribute these changes.
55 * Author: Avadis Tevanian, Jr.
58 * Type definitions for generic queues.
62 #ifndef _KERN_QUEUE_H_
63 #define _KERN_QUEUE_H_
65 #include <mach/mach_types.h>
66 #include <kern/macro_help.h>
69 * Queue of abstract objects. Queue is maintained
72 * Supports fast removal from within the queue.
74 * How to declare a queue of elements of type "foo_t":
75 * In the "*foo_t" type, you must have a field of
76 * type "queue_chain_t" to hold together this queue.
77 * There may be more than one chain through a
78 * "foo_t", for use by different queues.
80 * Declare the queue as a "queue_t" type.
82 * Elements of the queue (of type "foo_t", that is)
83 * are referred to by reference, and cast to type
84 * "queue_entry_t" within this module.
88 * A generic doubly-linked list (queue).
92 struct queue_entry
*next
; /* next element */
93 struct queue_entry
*prev
; /* previous element */
96 typedef struct queue_entry
*queue_t
;
97 typedef struct queue_entry queue_head_t
;
98 typedef struct queue_entry queue_chain_t
;
99 typedef struct queue_entry
*queue_entry_t
;
102 * enqueue puts "elt" on the "queue".
103 * dequeue returns the first element in the "queue".
104 * remqueue removes the specified "elt" from the specified "queue".
107 #define enqueue(queue,elt) enqueue_tail(queue, elt)
108 #define dequeue(queue) dequeue_head(queue)
110 #if !defined(__GNUC__)
112 #include <sys/cdefs.h>
115 /* Enqueue element to head of queue */
116 extern void enqueue_head(
120 /* Enqueue element to tail of queue */
121 extern void enqueue_tail(
125 /* Dequeue element from head of queue */
126 extern queue_entry_t
dequeue_head(
129 /* Dequeue element from tail of queue */
130 extern queue_entry_t
dequeue_tail(
133 /* Dequeue element */
134 extern void remqueue(
138 /* Enqueue element after a particular elem */
143 /* Dequeue element */
149 #else /* !__GNUC__ */
151 static __inline__
void
156 elt
->next
= que
->next
;
158 elt
->next
->prev
= elt
;
162 static __inline__
void
168 elt
->prev
= que
->prev
;
169 elt
->prev
->next
= elt
;
173 static __inline__ queue_entry_t
177 register queue_entry_t elt
= (queue_entry_t
) 0;
179 if (que
->next
!= que
) {
181 elt
->next
->prev
= que
;
182 que
->next
= elt
->next
;
188 static __inline__ queue_entry_t
192 register queue_entry_t elt
= (queue_entry_t
) 0;
194 if (que
->prev
!= que
) {
196 elt
->prev
->next
= que
;
197 que
->prev
= elt
->prev
;
203 static __inline__
void
205 __unused queue_t que
,
208 elt
->next
->prev
= elt
->prev
;
209 elt
->prev
->next
= elt
->next
;
212 static __inline__
void
217 entry
->next
= pred
->next
;
219 (pred
->next
)->prev
= entry
;
223 static __inline__ integer_t
225 register queue_entry_t elt
)
227 (elt
->next
)->prev
= elt
->prev
;
228 (elt
->prev
)->next
= elt
->next
;
230 return((integer_t
)elt
);
233 #endif /* !__GNUC__ */
238 * Initialize the given queue.
241 * queue_t q; \* MODIFIED *\
243 #define queue_init(q) \
252 * Returns the first entry in the queue,
254 * queue_entry_t queue_first(q)
255 * queue_t q; \* IN *\
257 #define queue_first(q) ((q)->next)
262 * Returns the entry after an item in the queue.
264 * queue_entry_t queue_next(qc)
267 #define queue_next(qc) ((qc)->next)
272 * Returns the last entry in the queue.
274 * queue_entry_t queue_last(q)
275 * queue_t q; \* IN *\
277 #define queue_last(q) ((q)->prev)
282 * Returns the entry before an item in the queue.
284 * queue_entry_t queue_prev(qc)
287 #define queue_prev(qc) ((qc)->prev)
292 * Tests whether a new entry is really the end of
295 * boolean_t queue_end(q, qe)
299 #define queue_end(q, qe) ((q) == (qe))
304 * Tests whether a queue is empty.
306 * boolean_t queue_empty(q)
309 #define queue_empty(q) queue_end((q), queue_first(q))
312 /*----------------------------------------------------------------*/
314 * Macros that operate on generic structures. The queue
315 * chain may be at any location within the structure, and there
316 * may be more than one chain.
322 * Insert a new element at the tail of the queue.
324 * void queue_enter(q, elt, type, field)
327 * <type> is what's in our queue
328 * <field> is the chain field in (*<type>)
330 #define queue_enter(head, elt, type, field) \
332 register queue_entry_t __prev; \
334 __prev = (head)->prev; \
335 if ((head) == __prev) { \
336 (head)->next = (queue_entry_t) (elt); \
339 ((type)__prev)->field.next = (queue_entry_t)(elt);\
341 (elt)->field.prev = __prev; \
342 (elt)->field.next = head; \
343 (head)->prev = (queue_entry_t) elt; \
347 * Macro: queue_enter_first
349 * Insert a new element at the head of the queue.
351 * void queue_enter_first(q, elt, type, field)
354 * <type> is what's in our queue
355 * <field> is the chain field in (*<type>)
357 #define queue_enter_first(head, elt, type, field) \
359 register queue_entry_t __next; \
361 __next = (head)->next; \
362 if ((head) == __next) { \
363 (head)->prev = (queue_entry_t) (elt); \
366 ((type)__next)->field.prev = (queue_entry_t)(elt);\
368 (elt)->field.next = __next; \
369 (elt)->field.prev = head; \
370 (head)->next = (queue_entry_t) elt; \
374 * Macro: queue_insert_before
376 * Insert a new element before a given element.
378 * void queue_insert_before(q, elt, cur, type, field)
382 * <type> is what's in our queue
383 * <field> is the chain field in (*<type>)
385 #define queue_insert_before(head, elt, cur, type, field) \
387 register queue_entry_t __prev; \
389 if ((head) == (queue_entry_t)(cur)) { \
390 (elt)->field.next = (head); \
391 if ((head)->next == (head)) { /* only element */ \
392 (elt)->field.prev = (head); \
393 (head)->next = (queue_entry_t)(elt); \
394 } else { /* last element */ \
395 __prev = (elt)->field.prev = (head)->prev; \
396 ((type)__prev)->field.next = (queue_entry_t)(elt);\
398 (head)->prev = (queue_entry_t)(elt); \
400 (elt)->field.next = (queue_entry_t)(cur); \
401 if ((head)->next == (queue_entry_t)(cur)) { \
402 /* first element */ \
403 (elt)->field.prev = (head); \
404 (head)->next = (queue_entry_t)(elt); \
405 } else { /* middle element */ \
406 __prev = (elt)->field.prev = (cur)->field.prev; \
407 ((type)__prev)->field.next = (queue_entry_t)(elt);\
409 (cur)->field.prev = (queue_entry_t)(elt); \
414 * Macro: queue_insert_after
416 * Insert a new element after a given element.
418 * void queue_insert_after(q, elt, cur, type, field)
422 * <type> is what's in our queue
423 * <field> is the chain field in (*<type>)
425 #define queue_insert_after(head, elt, cur, type, field) \
427 register queue_entry_t __next; \
429 if ((head) == (queue_entry_t)(cur)) { \
430 (elt)->field.prev = (head); \
431 if ((head)->next == (head)) { /* only element */ \
432 (elt)->field.next = (head); \
433 (head)->prev = (queue_entry_t)(elt); \
434 } else { /* first element */ \
435 __next = (elt)->field.next = (head)->next; \
436 ((type)__next)->field.prev = (queue_entry_t)(elt);\
438 (head)->next = (queue_entry_t)(elt); \
440 (elt)->field.prev = (queue_entry_t)(cur); \
441 if ((head)->prev == (queue_entry_t)(cur)) { \
443 (elt)->field.next = (head); \
444 (head)->prev = (queue_entry_t)(elt); \
445 } else { /* middle element */ \
446 __next = (elt)->field.next = (cur)->field.next; \
447 ((type)__next)->field.prev = (queue_entry_t)(elt);\
449 (cur)->field.next = (queue_entry_t)(elt); \
454 * Macro: queue_field [internal use only]
456 * Find the queue_chain_t (or queue_t) for the
457 * given element (thing) in the given queue (head)
459 #define queue_field(head, thing, type, field) \
460 (((head) == (thing)) ? (head) : &((type)(thing))->field)
463 * Macro: queue_remove
465 * Remove an arbitrary item from the queue.
467 * void queue_remove(q, qe, type, field)
468 * arguments as in queue_enter
470 #define queue_remove(head, elt, type, field) \
472 register queue_entry_t __next, __prev; \
474 __next = (elt)->field.next; \
475 __prev = (elt)->field.prev; \
477 if ((head) == __next) \
478 (head)->prev = __prev; \
480 ((type)__next)->field.prev = __prev; \
482 if ((head) == __prev) \
483 (head)->next = __next; \
485 ((type)__prev)->field.next = __next; \
489 * Macro: queue_remove_first
491 * Remove and return the entry at the head of
494 * queue_remove_first(head, entry, type, field)
495 * entry is returned by reference
497 #define queue_remove_first(head, entry, type, field) \
499 register queue_entry_t __next; \
501 (entry) = (type) ((head)->next); \
502 __next = (entry)->field.next; \
504 if ((head) == __next) \
505 (head)->prev = (head); \
507 ((type)(__next))->field.prev = (head); \
508 (head)->next = __next; \
512 * Macro: queue_remove_last
514 * Remove and return the entry at the tail of
517 * queue_remove_last(head, entry, type, field)
518 * entry is returned by reference
520 #define queue_remove_last(head, entry, type, field) \
522 register queue_entry_t __prev; \
524 (entry) = (type) ((head)->prev); \
525 __prev = (entry)->field.prev; \
527 if ((head) == __prev) \
528 (head)->next = (head); \
530 ((type)(__prev))->field.next = (head); \
531 (head)->prev = __prev; \
535 * Macro: queue_assign
537 #define queue_assign(to, from, type, field) \
539 ((type)((from)->prev))->field.next = (to); \
540 ((type)((from)->next))->field.prev = (to); \
545 * Macro: queue_new_head
547 * rebase old queue to new queue head
549 * queue_new_head(old, new, type, field)
552 * <type> is what's in our queue
553 * <field> is the chain field in (*<type>)
555 #define queue_new_head(old, new, type, field) \
557 if (!queue_empty(old)) { \
559 ((type)((new)->next))->field.prev = (new); \
560 ((type)((new)->prev))->field.next = (new); \
567 * Macro: queue_iterate
569 * iterate over each item in the queue.
570 * Generates a 'for' loop, setting elt to
571 * each item in turn (by reference).
573 * queue_iterate(q, elt, type, field)
576 * <type> is what's in our queue
577 * <field> is the chain field in (*<type>)
579 #define queue_iterate(head, elt, type, field) \
580 for ((elt) = (type) queue_first(head); \
581 !queue_end((head), (queue_entry_t)(elt)); \
582 (elt) = (type) queue_next(&(elt)->field))
584 #ifdef MACH_KERNEL_PRIVATE
586 #include <kern/lock.h>
588 /*----------------------------------------------------------------*/
590 * Define macros for queues with locks.
592 struct mpqueue_head
{
593 struct queue_entry head
; /* header for queue */
594 decl_simple_lock_data(, lock
) /* lock for queue */
597 typedef struct mpqueue_head mpqueue_head_t
;
599 #define round_mpq(size) (size)
601 #define mpqueue_init(q) \
603 queue_init(&(q)->head); \
604 simple_lock_init(&(q)->lock, 0); \
607 #define mpenqueue_tail(q, elt) \
609 simple_lock(&(q)->lock); \
610 enqueue_tail(&(q)->head, elt); \
611 simple_unlock(&(q)->lock); \
614 #define mpdequeue_head(q, elt) \
616 simple_lock(&(q)->lock); \
617 if (queue_empty(&(q)->head)) \
620 *(elt) = dequeue_head(&(q)->head); \
621 simple_unlock(&(q)->lock); \
624 #endif /* MACH_KERNEL_PRIVATE */
626 #endif /* _KERN_QUEUE_H_ */