home *** CD-ROM | disk | FTP | other *** search
- /*
- * Mach Operating System
- * Copyright (c) 1989 Carnegie-Mellon University
- * Copyright (c) 1988 Carnegie-Mellon University
- * Copyright (c) 1987 Carnegie-Mellon University
- * All rights reserved. The CMU software License Agreement specifies
- * the terms and conditions for use and redistribution.
- */
- /*
- * HISTORY
- * $Log: queue.h,v $
- * 21-May-89 Avadis Tevanian, Jr. (avie) at NeXT, Inc.
- * Use inline expansion if compiling with the GNU compiler.
- *
- * Revision 2.7 89/03/09 20:15:03 rpd
- * More cleanup.
- *
- * Revision 2.6 89/02/25 18:07:48 gm0w
- * Kernel code cleanup.
- * Put all the macros under #ifdef KERNEL
- * [89/02/15 mrt]
- *
- * Revision 2.5 89/02/07 01:03:50 mwyoung
- * Relocated from sys/queue.h
- *
- * Revision 2.4 88/12/19 02:51:30 mwyoung
- * Eliminate round_queue.
- * [88/11/22 01:22:22 mwyoung]
- *
- * Add queue_remove_last.
- * [88/11/18 mwyoung]
- *
- * Revision 2.3 88/08/24 02:40:43 mwyoung
- * Adjusted include file references.
- * [88/08/17 02:20:58 mwyoung]
- *
- *
- * 17-Jan-88 Daniel Julin (dpj) at Carnegie-Mellon University
- * Added queue_enter_first, queue_last and queue_prev for use by
- * the TCP netport code.
- *
- * 17-Mar-87 David Golub (dbg) at Carnegie-Mellon University
- * Made queue package return queue_entry_t instead of vm_offset_t.
- *
- * 27-Feb-87 David Golub (dbg) at Carnegie-Mellon University
- * Made remqueue a real routine on all machines. Defined old
- * Queue routines as macros that invoke new queue routines.
- *
- * 25-Feb-87 Avadis Tevanian (avie) at Carnegie-Mellon University
- * Fixed non-KERNEL compilation.
- *
- * 24-Feb-87 David L. Black (dlb) at Carnegie-Mellon University
- * MULTIMAX: remqueue is now a real routine, removed define.
- * This is done to mask a compiler buT*
- * 12-Jun-85 Avadis Tevanian (avie) at Carnegie-Mellon University
- * Created.
- */
- /*
- * File: queue.h
- *
- * Type definitions for generic queues.
- */
-
- #ifndef _KERN_INTERNAL_QUEUE_H_
- #define _KERN_INTERNAL_QUEUE_H_
-
- #import <mach/machine/vm_types.h>
- #import <kernserv/lock.h>
- #import <kernserv/macro_help.h>
-
- /*
- * Queue of abstract objects. Queue is maintained
- * within that object.
- *
- * Supports fast removal from within the queue.
- *
- * How to declare a queue of elements of type "foo_t":
- * In the "*foo_t" type, you must have a field of
- * type "queue_chain_t" to hold together this queue.
- * There may be more than one chain through a
- * "foo_t", for use by different queues.
- *
- * Declare the queue as a "queue_t" type.
- *
- * Elements of the queue (of type "foo_t", that is)
- * are referred to by reference, and cast to type
- * "queue_entry_t" within this module.
- */
-
- /*
- * A generic doubly-linked list (queue).
- */
-
- struct queue_entry {
- struct queue_entry *next; /* next element */
- struct queue_entry *prev; /* previous element */
- };
-
- typedef struct queue_entry *queue_t;
- typedef struct queue_entry queue_head_t;
- typedef struct queue_entry queue_chain_t;
- typedef struct queue_entry *queue_entry_t;
-
- /*
- * enqueue puts "elt" on the "queue".
- * dequeue returns the first element in the "queue".
- * remqueue removes the specified "elt" from the specified "queue".
- */
-
- #define enqueue(queue,elt) enqueue_tail(queue, elt)
- #define dequeue(queue) dequeue_head(queue)
-
- #if defined(__GNU__) && defined(KERNEL_BUILD)
- #define COMPILE_QUEUE /* flag that queue.c should compile now */
- #import <kern/queue.c>
- #else defined(__GNU__) && defined(KERNEL_BUILD)
- extern void enqueue_head();
- extern void enqueue_tail();
- extern queue_entry_t dequeue_head();
- extern queue_entry_t dequeue_tail();
- extern void remqueue();
- #endif defined(__GNU__) && defined(KERNEL_BUILD)
-
-
- /*
- * Macro: queue_init
- * Function:
- * Initialize the given queue.
- * Header:
- * void queue_init(q)
- * queue_t q; \* MODIFIED *\
- */
- #define queue_init(q) ((q)->next = (q)->prev = q)
-
- /*
- * Macro: queue_first
- * Function:
- * Returns the first entry in the queue,
- * Header:
- * queue_entry_t queue_first(q)
- * queue_t q; \* IN *\
- */
- #define queue_first(q) ((q)->next)
-
- /*
- * Macro: queue_next
- * Header:
- * queue_entry_t queue_next(qc)
- * queue_t qc;
- U#define queue_next(qc) ((qc)->next)
-
- /*
- * Macro: queue_end
- * Header:
- * boolean_t queue_end(q, qe)
- * queue_t q;
- * queue_entry_t qe;
- */
- #define queue_end(q, qe) ((q) == (qe))
-
- #define queue_empty(q) queue_end((q), queue_first(q))
-
- /*
- * Macro: queue_enter
- * Header:
- * void queue_enter(q, elt, type, field)
- * queue_t q;
- * <type> elt;
- * <type> is what's in our queue
- * <field> is the chain field in (*<type>)
- */
- #define queue_enter(head, elt, type, field) \
- MACRO_BEGIN \
- if (queue_empty((head))) { \
- (head)->next = (queue_entry_t) elt; \
- (head)->prev = (queue_entry_t) elt; \
- (elt)->field.next = head; \
- (elt)->field.prev = head; \
- } \
- else { \
- register queue_entry_t prev; \
- \
- prev = (head)->prev; \
- (elt)->field.prev = prev; \
- (elt)->field.next = head; \
- (head)->prev = (queue_entry_t)(elt); \
- ((type)prev)->field.next = (queue_entry_t)(elt);\
- } \
- MACRO_END
-
- /*
- * Macro: queue_field [internal use only]
- * Function:
- * Find the queue_chain_t (or queue_t) for the
- * given element (thing) in the given queue (head)
- */
- #define queue_field(head, thing, type, field) \
- (((head) == (thing)) ? (head) : &((type)(thing))->field)
-
- /*
- * Macro: queue_remove
- * Header:
- * void queue_remove(q, qe, type, field)
- * arguments as in queue_enter
- */
- #define queue_remove(head, elt, type, field) \
- MACRO_BEGIN \
- register queue_entry_t next, prev; \
- \
- next = (elt)->field.next; \
- prev = (elt)->field.prev; \
- \
- queue_field((head), next, type, field)->prev = prev; \
- queue_field((head), prev, type, field)->next = next; \
- MACRO_END
-
- /*
- * Macro: queue_assign
- */
- #define queue_assign(to, from, type, field) \
- MACRO_BEGIN \
- ((type)((from)->prev))->field.next = (to); \
- ((type)((from)->next))->field.prev = (to); \
- *to = *from; \
- MACRO_END
-
- #define queue_remove_first(h, e, t, f) \
- MACRO_BEGIN \
- e = (t) queue_first((h)); \
- queue_remove((h), (e), t, f); \
- MACRO_END
-
- #define queue_remove_last(h, e, t, f) \
- MACRO_BEGIN \
- e = (t) queue_last((h)); \
- queue_remove((h), (e), t, f); \
- MACRO_END
-
- /*
- * Macro: queue_enter_first
- * Header:
- * void queue_enter_first(q, elt, type, field)
- * queue_t q;
- * <type> elt;
- * <type> is what's in our queue
- * <fieVis the chain field in (*<type>)
- */
- #define queue_enter_first(head, elt, type, field) \
- MACRO_BEGIN \
- if (queue_empty((head))) { \
- (head)->next = (queue_entry_t) elt; \
- (head)->prev = (queue_entry_t) elt; \
- (elt)->field.next = head; \
- (elt)->field.prev = head; \
- } \
- else { \
- register queue_entry_t next; \
- \
- next = (head)->next; \
- (elt)->field.prev = head; \
- (elt)->field.next = next; \
- (head)->next = (queue_entry_t)(elt); \
- ((type)next)->field.prev = (queue_entry_t)(elt);\
- } \
- MACRO_END
-
- /*
- * Macro: queue_last
- * Function:
- * Returns the last entry in the queue,
- * Header:
- * queue_entry_t queue_last(q)
- * queue_t q; \* IN *\
- */
- #define queue_last(q) ((q)->prev)
-
- /*
- * Macro: queue_prev
- * Header:
- * queue_entry_t queue_prev(qc)
- * queue_t qc;
- */
- #define queue_prev(qc) ((qc)->prev)
-
- /*
- * Macro: queue_iterate
- * Function:
- * iterate over each item in the queue.
- * Generates a 'for' loop, setting elt to
- * each item in turn (by reference).
- * Header:
- * queue_iterate(q, elt, type, field)
- * queue_t q;
- * <type> elt;
- * <type> is what's in our queue
- * <field> is the chain field in (*<type>)
- */
- #define queue_iterate(head, elt, type, field) \
- for ((elt) = (type) queue_first(head); \
- !queue_end((head), (queue_entry_t)(elt)); \
- (elt) = (type) queue_next(&(elt)->field))
-
- /*
- * Define macros for queues with locks.
- */
- struct mpqueue_head {
- struct queue_entry head; /* header for queue */
- simple_lock_data_t lock; /* lock for queue */
- };
-
- typedef struct mpqueue_head mpqueue_head_t;
-
- #define round_mpq(size) (size)
-
- #define mpqueue_init(q) \
- MACRO_BEGIN \
- queue_init(&(q)->head); \
- simple_lock_init(&(q)->lock); \
- MACRO_END
-
- #define mpenqueue_tail(q, elt) \
- MACRO_BEGIN \
- simple_lock(&(q)->lock); \
- enqueue_tail(&(q)->head, elt); \
- simple_unlock(&(q)->lock); \
- MACRO_END
-
- #define mpdIue_head(q, elt) \
- MACRO_BEGIN \
- simple_lock(&(q)->lock); \
- if (queue_empty(&(q)->head)) \
- *(elt) = 0; \
- else \
- *(elt) = dequeue_head(&(q)->head); \
- simple_unlock(&(q)->lock); \
- MACRO_END
-
- #endif _KERN_INTERNAL_QUEUE_H_
-