2 * Copyright (c) 2000 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 <kern/lock.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 /* Enqueue element to head of queue */
112 extern void enqueue_head(
116 /* Enqueue element to tail of queue */
117 extern void enqueue_tail(
121 /* Dequeue element from head of queue */
122 extern queue_entry_t
dequeue_head(
125 /* Dequeue element from tail of queue */
126 extern queue_entry_t
dequeue_tail(
129 /* Dequeue element */
130 extern void remqueue(
134 /* Enqueue element after a particular elem */
139 /* Dequeue element */
145 static __inline__
void
150 elt
->next
= que
->next
;
152 elt
->next
->prev
= elt
;
156 static __inline__
void
162 elt
->prev
= que
->prev
;
163 elt
->prev
->next
= elt
;
167 static __inline__ queue_entry_t
171 register queue_entry_t elt
= (queue_entry_t
) 0;
173 if (que
->next
!= que
) {
175 elt
->next
->prev
= que
;
176 que
->next
= elt
->next
;
182 static __inline__ queue_entry_t
186 register queue_entry_t elt
= (queue_entry_t
) 0;
188 if (que
->prev
!= que
) {
190 elt
->prev
->next
= que
;
191 que
->prev
= elt
->prev
;
197 static __inline__
void
202 elt
->next
->prev
= elt
->prev
;
203 elt
->prev
->next
= elt
->next
;
206 static __inline__
void
211 entry
->next
= pred
->next
;
213 (pred
->next
)->prev
= entry
;
217 static __inline__ integer_t
219 register queue_entry_t elt
)
221 (elt
->next
)->prev
= elt
->prev
;
222 (elt
->prev
)->next
= elt
->next
;
224 return((integer_t
)elt
);
227 #endif /* defined(__GNUC__) */
232 * Initialize the given queue.
235 * queue_t q; \* MODIFIED *\
237 #define queue_init(q) \
246 * Returns the first entry in the queue,
248 * queue_entry_t queue_first(q)
249 * queue_t q; \* IN *\
251 #define queue_first(q) ((q)->next)
256 * Returns the entry after an item in the queue.
258 * queue_entry_t queue_next(qc)
261 #define queue_next(qc) ((qc)->next)
266 * Returns the last entry in the queue.
268 * queue_entry_t queue_last(q)
269 * queue_t q; \* IN *\
271 #define queue_last(q) ((q)->prev)
276 * Returns the entry before an item in the queue.
278 * queue_entry_t queue_prev(qc)
281 #define queue_prev(qc) ((qc)->prev)
286 * Tests whether a new entry is really the end of
289 * boolean_t queue_end(q, qe)
293 #define queue_end(q, qe) ((q) == (qe))
298 * Tests whether a queue is empty.
300 * boolean_t queue_empty(q)
303 #define queue_empty(q) queue_end((q), queue_first(q))
306 /*----------------------------------------------------------------*/
308 * Macros that operate on generic structures. The queue
309 * chain may be at any location within the structure, and there
310 * may be more than one chain.
316 * Insert a new element at the tail of the queue.
318 * void queue_enter(q, elt, type, field)
321 * <type> is what's in our queue
322 * <field> is the chain field in (*<type>)
324 #define queue_enter(head, elt, type, field) \
326 register queue_entry_t prev; \
328 prev = (head)->prev; \
329 if ((head) == prev) { \
330 (head)->next = (queue_entry_t) (elt); \
333 ((type)prev)->field.next = (queue_entry_t)(elt);\
335 (elt)->field.prev = prev; \
336 (elt)->field.next = head; \
337 (head)->prev = (queue_entry_t) elt; \
341 * Macro: queue_enter_first
343 * Insert a new element at the head of the queue.
345 * void queue_enter_first(q, elt, type, field)
348 * <type> is what's in our queue
349 * <field> is the chain field in (*<type>)
351 #define queue_enter_first(head, elt, type, field) \
353 register queue_entry_t next; \
355 next = (head)->next; \
356 if ((head) == next) { \
357 (head)->prev = (queue_entry_t) (elt); \
360 ((type)next)->field.prev = (queue_entry_t)(elt);\
362 (elt)->field.next = next; \
363 (elt)->field.prev = head; \
364 (head)->next = (queue_entry_t) elt; \
368 * Macro: queue_insert_before
370 * Insert a new element before a given element.
372 * void queue_insert_before(q, elt, cur, type, field)
376 * <type> is what's in our queue
377 * <field> is the chain field in (*<type>)
379 #define queue_insert_before(head, elt, cur, type, field) \
381 register queue_entry_t prev; \
383 if ((head) == (queue_entry_t)(cur)) { \
384 (elt)->field.next = (head); \
385 if ((head)->next == (head)) { /* only element */ \
386 (elt)->field.prev = (head); \
387 (head)->next = (queue_entry_t)(elt); \
388 } else { /* last element */ \
389 prev = (elt)->field.prev = (head)->prev; \
390 ((type)prev)->field.next = (queue_entry_t)(elt);\
392 (head)->prev = (queue_entry_t)(elt); \
394 (elt)->field.next = (queue_entry_t)(cur); \
395 if ((head)->next == (queue_entry_t)(cur)) { \
396 /* first element */ \
397 (elt)->field.prev = (head); \
398 (head)->next = (queue_entry_t)(elt); \
399 } else { /* middle element */ \
400 prev = (elt)->field.prev = (cur)->field.prev; \
401 ((type)prev)->field.next = (queue_entry_t)(elt);\
403 (cur)->field.prev = (queue_entry_t)(elt); \
408 * Macro: queue_insert_after
410 * Insert a new element after a given element.
412 * void queue_insert_after(q, elt, cur, type, field)
416 * <type> is what's in our queue
417 * <field> is the chain field in (*<type>)
419 #define queue_insert_after(head, elt, cur, type, field) \
421 register queue_entry_t next; \
423 if ((head) == (queue_entry_t)(cur)) { \
424 (elt)->field.prev = (head); \
425 if ((head)->next == (head)) { /* only element */ \
426 (elt)->field.next = (head); \
427 (head)->prev = (queue_entry_t)(elt); \
428 } else { /* first element */ \
429 next = (elt)->field.next = (head)->next; \
430 ((type)next)->field.prev = (queue_entry_t)(elt);\
432 (head)->next = (queue_entry_t)(elt); \
434 (elt)->field.prev = (queue_entry_t)(cur); \
435 if ((head)->prev == (queue_entry_t)(cur)) { \
437 (elt)->field.next = (head); \
438 (head)->prev = (queue_entry_t)(elt); \
439 } else { /* middle element */ \
440 next = (elt)->field.next = (cur)->field.next; \
441 ((type)next)->field.prev = (queue_entry_t)(elt);\
443 (cur)->field.next = (queue_entry_t)(elt); \
448 * Macro: queue_field [internal use only]
450 * Find the queue_chain_t (or queue_t) for the
451 * given element (thing) in the given queue (head)
453 #define queue_field(head, thing, type, field) \
454 (((head) == (thing)) ? (head) : &((type)(thing))->field)
457 * Macro: queue_remove
459 * Remove an arbitrary item from the queue.
461 * void queue_remove(q, qe, type, field)
462 * arguments as in queue_enter
464 #define queue_remove(head, elt, type, field) \
466 register queue_entry_t next, prev; \
468 next = (elt)->field.next; \
469 prev = (elt)->field.prev; \
471 if ((head) == next) \
472 (head)->prev = prev; \
474 ((type)next)->field.prev = prev; \
476 if ((head) == prev) \
477 (head)->next = next; \
479 ((type)prev)->field.next = next; \
483 * Macro: queue_remove_first
485 * Remove and return the entry at the head of
488 * queue_remove_first(head, entry, type, field)
489 * entry is returned by reference
491 #define queue_remove_first(head, entry, type, field) \
493 register queue_entry_t next; \
495 (entry) = (type) ((head)->next); \
496 next = (entry)->field.next; \
498 if ((head) == next) \
499 (head)->prev = (head); \
501 ((type)(next))->field.prev = (head); \
502 (head)->next = next; \
506 * Macro: queue_remove_last
508 * Remove and return the entry at the tail of
511 * queue_remove_last(head, entry, type, field)
512 * entry is returned by reference
514 #define queue_remove_last(head, entry, type, field) \
516 register queue_entry_t prev; \
518 (entry) = (type) ((head)->prev); \
519 prev = (entry)->field.prev; \
521 if ((head) == prev) \
522 (head)->next = (head); \
524 ((type)(prev))->field.next = (head); \
525 (head)->prev = prev; \
529 * Macro: queue_assign
531 #define queue_assign(to, from, type, field) \
533 ((type)((from)->prev))->field.next = (to); \
534 ((type)((from)->next))->field.prev = (to); \
539 * Macro: queue_new_head
541 * rebase old queue to new queue head
543 * queue_new_head(old, new, type, field)
546 * <type> is what's in our queue
547 * <field> is the chain field in (*<type>)
549 #define queue_new_head(old, new, type, field) \
551 if (!queue_empty(new)) { \
553 ((type)((new)->next))->field.prev = (new); \
554 ((type)((new)->prev))->field.next = (new); \
561 * Macro: queue_iterate
563 * iterate over each item in the queue.
564 * Generates a 'for' loop, setting elt to
565 * each item in turn (by reference).
567 * queue_iterate(q, elt, type, field)
570 * <type> is what's in our queue
571 * <field> is the chain field in (*<type>)
573 #define queue_iterate(head, elt, type, field) \
574 for ((elt) = (type) queue_first(head); \
575 !queue_end((head), (queue_entry_t)(elt)); \
576 (elt) = (type) queue_next(&(elt)->field))
579 #ifdef MACH_KERNEL_PRIVATE
580 /*----------------------------------------------------------------*/
582 * Define macros for queues with locks.
584 struct mpqueue_head
{
585 struct queue_entry head
; /* header for queue */
586 decl_simple_lock_data(, lock
) /* lock for queue */
589 typedef struct mpqueue_head mpqueue_head_t
;
591 #define round_mpq(size) (size)
593 #define mpqueue_init(q) \
595 queue_init(&(q)->head); \
596 simple_lock_init(&(q)->lock, ETAP_MISC_Q); \
599 #define mpenqueue_tail(q, elt) \
601 simple_lock(&(q)->lock); \
602 enqueue_tail(&(q)->head, elt); \
603 simple_unlock(&(q)->lock); \
606 #define mpdequeue_head(q, elt) \
608 simple_lock(&(q)->lock); \
609 if (queue_empty(&(q)->head)) \
612 *(elt) = dequeue_head(&(q)->head); \
613 simple_unlock(&(q)->lock); \
616 #endif /* MACH_KERNEL_PRIVATE */
618 #endif /* _KERN_QUEUE_H_ */