2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
29 * Mach Operating System
30 * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
31 * All Rights Reserved.
33 * Permission to use, copy, modify and distribute this software and its
34 * documentation is hereby granted, provided that both the copyright
35 * notice and this permission notice appear in all copies of the
36 * software, derivative works or modified versions, and any portions
37 * thereof, and that both notices appear in supporting documentation.
39 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
40 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
41 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
43 * Carnegie Mellon requests users of this software to return to
45 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
46 * School of Computer Science
47 * Carnegie Mellon University
48 * Pittsburgh PA 15213-3890
50 * any improvements or extensions that they make and grant Carnegie Mellon rights
51 * to redistribute these changes.
57 * Author: Avadis Tevanian, Jr.
60 * Type definitions for generic queues.
64 #ifndef _KERN_QUEUE_H_
65 #define _KERN_QUEUE_H_
67 #include <kern/lock.h>
68 #include <kern/macro_help.h>
71 * Queue of abstract objects. Queue is maintained
74 * Supports fast removal from within the queue.
76 * How to declare a queue of elements of type "foo_t":
77 * In the "*foo_t" type, you must have a field of
78 * type "queue_chain_t" to hold together this queue.
79 * There may be more than one chain through a
80 * "foo_t", for use by different queues.
82 * Declare the queue as a "queue_t" type.
84 * Elements of the queue (of type "foo_t", that is)
85 * are referred to by reference, and cast to type
86 * "queue_entry_t" within this module.
90 * A generic doubly-linked list (queue).
94 struct queue_entry
*next
; /* next element */
95 struct queue_entry
*prev
; /* previous element */
98 typedef struct queue_entry
*queue_t
;
99 typedef struct queue_entry queue_head_t
;
100 typedef struct queue_entry queue_chain_t
;
101 typedef struct queue_entry
*queue_entry_t
;
104 * enqueue puts "elt" on the "queue".
105 * dequeue returns the first element in the "queue".
106 * remqueue removes the specified "elt" from the specified "queue".
109 #define enqueue(queue,elt) enqueue_tail(queue, elt)
110 #define dequeue(queue) dequeue_head(queue)
112 #if !defined(__GNUC__)
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 static __inline__
void
153 elt
->next
= que
->next
;
155 elt
->next
->prev
= elt
;
159 static __inline__
void
165 elt
->prev
= que
->prev
;
166 elt
->prev
->next
= elt
;
170 static __inline__ queue_entry_t
174 register queue_entry_t elt
= (queue_entry_t
) 0;
176 if (que
->next
!= que
) {
178 elt
->next
->prev
= que
;
179 que
->next
= elt
->next
;
185 static __inline__ queue_entry_t
189 register queue_entry_t elt
= (queue_entry_t
) 0;
191 if (que
->prev
!= que
) {
193 elt
->prev
->next
= que
;
194 que
->prev
= elt
->prev
;
200 static __inline__
void
205 elt
->next
->prev
= elt
->prev
;
206 elt
->prev
->next
= elt
->next
;
209 static __inline__
void
214 entry
->next
= pred
->next
;
216 (pred
->next
)->prev
= entry
;
220 static __inline__ integer_t
222 register queue_entry_t elt
)
224 (elt
->next
)->prev
= elt
->prev
;
225 (elt
->prev
)->next
= elt
->next
;
227 return((integer_t
)elt
);
230 #endif /* defined(__GNUC__) */
235 * Initialize the given queue.
238 * queue_t q; \* MODIFIED *\
240 #define queue_init(q) \
249 * Returns the first entry in the queue,
251 * queue_entry_t queue_first(q)
252 * queue_t q; \* IN *\
254 #define queue_first(q) ((q)->next)
259 * Returns the entry after an item in the queue.
261 * queue_entry_t queue_next(qc)
264 #define queue_next(qc) ((qc)->next)
269 * Returns the last entry in the queue.
271 * queue_entry_t queue_last(q)
272 * queue_t q; \* IN *\
274 #define queue_last(q) ((q)->prev)
279 * Returns the entry before an item in the queue.
281 * queue_entry_t queue_prev(qc)
284 #define queue_prev(qc) ((qc)->prev)
289 * Tests whether a new entry is really the end of
292 * boolean_t queue_end(q, qe)
296 #define queue_end(q, qe) ((q) == (qe))
301 * Tests whether a queue is empty.
303 * boolean_t queue_empty(q)
306 #define queue_empty(q) queue_end((q), queue_first(q))
309 /*----------------------------------------------------------------*/
311 * Macros that operate on generic structures. The queue
312 * chain may be at any location within the structure, and there
313 * may be more than one chain.
319 * Insert a new element at the tail of the queue.
321 * void queue_enter(q, elt, type, field)
324 * <type> is what's in our queue
325 * <field> is the chain field in (*<type>)
327 #define queue_enter(head, elt, type, field) \
329 register queue_entry_t prev; \
331 prev = (head)->prev; \
332 if ((head) == prev) { \
333 (head)->next = (queue_entry_t) (elt); \
336 ((type)prev)->field.next = (queue_entry_t)(elt);\
338 (elt)->field.prev = prev; \
339 (elt)->field.next = head; \
340 (head)->prev = (queue_entry_t) elt; \
344 * Macro: queue_enter_first
346 * Insert a new element at the head of the queue.
348 * void queue_enter_first(q, elt, type, field)
351 * <type> is what's in our queue
352 * <field> is the chain field in (*<type>)
354 #define queue_enter_first(head, elt, type, field) \
356 register queue_entry_t next; \
358 next = (head)->next; \
359 if ((head) == next) { \
360 (head)->prev = (queue_entry_t) (elt); \
363 ((type)next)->field.prev = (queue_entry_t)(elt);\
365 (elt)->field.next = next; \
366 (elt)->field.prev = head; \
367 (head)->next = (queue_entry_t) elt; \
371 * Macro: queue_insert_before
373 * Insert a new element before a given element.
375 * void queue_insert_before(q, elt, cur, type, field)
379 * <type> is what's in our queue
380 * <field> is the chain field in (*<type>)
382 #define queue_insert_before(head, elt, cur, type, field) \
384 register queue_entry_t prev; \
386 if ((head) == (queue_entry_t)(cur)) { \
387 (elt)->field.next = (head); \
388 if ((head)->next == (head)) { /* only element */ \
389 (elt)->field.prev = (head); \
390 (head)->next = (queue_entry_t)(elt); \
391 } else { /* last element */ \
392 prev = (elt)->field.prev = (head)->prev; \
393 ((type)prev)->field.next = (queue_entry_t)(elt);\
395 (head)->prev = (queue_entry_t)(elt); \
397 (elt)->field.next = (queue_entry_t)(cur); \
398 if ((head)->next == (queue_entry_t)(cur)) { \
399 /* first element */ \
400 (elt)->field.prev = (head); \
401 (head)->next = (queue_entry_t)(elt); \
402 } else { /* middle element */ \
403 prev = (elt)->field.prev = (cur)->field.prev; \
404 ((type)prev)->field.next = (queue_entry_t)(elt);\
406 (cur)->field.prev = (queue_entry_t)(elt); \
411 * Macro: queue_insert_after
413 * Insert a new element after a given element.
415 * void queue_insert_after(q, elt, cur, type, field)
419 * <type> is what's in our queue
420 * <field> is the chain field in (*<type>)
422 #define queue_insert_after(head, elt, cur, type, field) \
424 register queue_entry_t next; \
426 if ((head) == (queue_entry_t)(cur)) { \
427 (elt)->field.prev = (head); \
428 if ((head)->next == (head)) { /* only element */ \
429 (elt)->field.next = (head); \
430 (head)->prev = (queue_entry_t)(elt); \
431 } else { /* first element */ \
432 next = (elt)->field.next = (head)->next; \
433 ((type)next)->field.prev = (queue_entry_t)(elt);\
435 (head)->next = (queue_entry_t)(elt); \
437 (elt)->field.prev = (queue_entry_t)(cur); \
438 if ((head)->prev == (queue_entry_t)(cur)) { \
440 (elt)->field.next = (head); \
441 (head)->prev = (queue_entry_t)(elt); \
442 } else { /* middle element */ \
443 next = (elt)->field.next = (cur)->field.next; \
444 ((type)next)->field.prev = (queue_entry_t)(elt);\
446 (cur)->field.next = (queue_entry_t)(elt); \
451 * Macro: queue_field [internal use only]
453 * Find the queue_chain_t (or queue_t) for the
454 * given element (thing) in the given queue (head)
456 #define queue_field(head, thing, type, field) \
457 (((head) == (thing)) ? (head) : &((type)(thing))->field)
460 * Macro: queue_remove
462 * Remove an arbitrary item from the queue.
464 * void queue_remove(q, qe, type, field)
465 * arguments as in queue_enter
467 #define queue_remove(head, elt, type, field) \
469 register queue_entry_t next, prev; \
471 next = (elt)->field.next; \
472 prev = (elt)->field.prev; \
474 if ((head) == next) \
475 (head)->prev = prev; \
477 ((type)next)->field.prev = prev; \
479 if ((head) == prev) \
480 (head)->next = next; \
482 ((type)prev)->field.next = next; \
486 * Macro: queue_remove_first
488 * Remove and return the entry at the head of
491 * queue_remove_first(head, entry, type, field)
492 * entry is returned by reference
494 #define queue_remove_first(head, entry, type, field) \
496 register queue_entry_t next; \
498 (entry) = (type) ((head)->next); \
499 next = (entry)->field.next; \
501 if ((head) == next) \
502 (head)->prev = (head); \
504 ((type)(next))->field.prev = (head); \
505 (head)->next = next; \
509 * Macro: queue_remove_last
511 * Remove and return the entry at the tail of
514 * queue_remove_last(head, entry, type, field)
515 * entry is returned by reference
517 #define queue_remove_last(head, entry, type, field) \
519 register queue_entry_t prev; \
521 (entry) = (type) ((head)->prev); \
522 prev = (entry)->field.prev; \
524 if ((head) == prev) \
525 (head)->next = (head); \
527 ((type)(prev))->field.next = (head); \
528 (head)->prev = prev; \
532 * Macro: queue_assign
534 #define queue_assign(to, from, type, field) \
536 ((type)((from)->prev))->field.next = (to); \
537 ((type)((from)->next))->field.prev = (to); \
542 * Macro: queue_new_head
544 * rebase old queue to new queue head
546 * queue_new_head(old, new, type, field)
549 * <type> is what's in our queue
550 * <field> is the chain field in (*<type>)
552 #define queue_new_head(old, new, type, field) \
554 if (!queue_empty(new)) { \
556 ((type)((new)->next))->field.prev = (new); \
557 ((type)((new)->prev))->field.next = (new); \
564 * Macro: queue_iterate
566 * iterate over each item in the queue.
567 * Generates a 'for' loop, setting elt to
568 * each item in turn (by reference).
570 * queue_iterate(q, elt, type, field)
573 * <type> is what's in our queue
574 * <field> is the chain field in (*<type>)
576 #define queue_iterate(head, elt, type, field) \
577 for ((elt) = (type) queue_first(head); \
578 !queue_end((head), (queue_entry_t)(elt)); \
579 (elt) = (type) queue_next(&(elt)->field))
581 #include <sys/appleapiopts.h>
583 #ifdef __APPLE_API_PRIVATE
585 #ifdef MACH_KERNEL_PRIVATE
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, ETAP_MISC_Q); \
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 /* __APPLE_API_PRIVATE */
627 #endif /* _KERN_QUEUE_H_ */