|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Mach Operating System
27: * Copyright (c) 1989 Carnegie-Mellon University
28: * Copyright (c) 1988 Carnegie-Mellon University
29: * Copyright (c) 1987 Carnegie-Mellon University
30: * All rights reserved. The CMU software License Agreement specifies
31: * the terms and conditions for use and redistribution.
32: */
33: /*
34: * File: queue.h
35: *
36: * Type definitions for generic queues.
37: */
38:
39: #ifdef KERNEL_PRIVATE
40: #warning Obsolete header file: <kernserv/queue.h>, use <kern/queue.h> \
41: instead; or better yet, just say no!!
42: #import <kern/queue.h>
43:
44: #else /* KERNEL_PRIVATE */
45:
46: #ifndef _KERN_QUEUE_H_
47: #define _KERN_QUEUE_H_
48:
49: #import <mach/machine/vm_types.h>
50: #import <kernserv/lock.h>
51: #import <kernserv/macro_help.h>
52:
53: /*
54: * Queue of abstract objects. Queue is maintained
55: * within that object.
56: *
57: * Supports fast removal from within the queue.
58: *
59: * How to declare a queue of elements of type "foo_t":
60: * In the "*foo_t" type, you must have a field of
61: * type "queue_chain_t" to hold together this queue.
62: * There may be more than one chain through a
63: * "foo_t", for use by different queues.
64: *
65: * Declare the queue as a "queue_t" type.
66: *
67: * Elements of the queue (of type "foo_t", that is)
68: * are referred to by reference, and cast to type
69: * "queue_entry_t" within this module.
70: */
71:
72: /*
73: * A generic doubly-linked list (queue).
74: */
75:
76: struct queue_entry {
77: struct queue_entry *next; /* next element */
78: struct queue_entry *prev; /* previous element */
79: };
80:
81: typedef struct queue_entry *queue_t;
82: typedef struct queue_entry queue_head_t;
83: typedef struct queue_entry queue_chain_t;
84: typedef struct queue_entry *queue_entry_t;
85:
86: /*
87: * enqueue puts "elt" on the "queue".
88: * dequeue returns the first element in the "queue".
89: * remqueue removes the specified "elt" from the specified "queue".
90: */
91:
92: #define enqueue(queue,elt) enqueue_tail(queue, elt)
93: #define dequeue(queue) dequeue_head(queue)
94:
95: extern void enqueue_head();
96: extern void enqueue_tail();
97: extern queue_entry_t dequeue_head();
98: extern queue_entry_t dequeue_tail();
99: extern void remqueue();
100:
101:
102: /*
103: * Macro: queue_init
104: * Function:
105: * Initialize the given queue.
106: * Header:
107: * void queue_init(q)
108: * queue_t q; \* MODIFIED *\
109: */
110: #define queue_init(q) ((q)->next = (q)->prev = q)
111:
112: /*
113: * Macro: queue_first
114: * Function:
115: * Returns the first entry in the queue,
116: * Header:
117: * queue_entry_t queue_first(q)
118: * queue_t q; \* IN *\
119: */
120: #define queue_first(q) ((q)->next)
121:
122: /*
123: * Macro: queue_next
124: * Header:
125: * queue_entry_t queue_next(qc)
126: * queue_t qc;
127: */
128: #define queue_next(qc) ((qc)->next)
129:
130: /*
131: * Macro: queue_end
132: * Header:
133: * boolean_t queue_end(q, qe)
134: * queue_t q;
135: * queue_entry_t qe;
136: */
137: #define queue_end(q, qe) ((q) == (qe))
138:
139: #define queue_empty(q) queue_end((q), queue_first(q))
140:
141: /*
142: * Macro: queue_enter
143: * Header:
144: * void queue_enter(q, elt, type, field)
145: * queue_t q;
146: * <type> elt;
147: * <type> is what's in our queue
148: * <field> is the chain field in (*<type>)
149: */
150: #define queue_enter(head, elt, type, field) \
151: MACRO_BEGIN \
152: if (queue_empty((head))) { \
153: (head)->next = (queue_entry_t) elt; \
154: (head)->prev = (queue_entry_t) elt; \
155: (elt)->field.next = head; \
156: (elt)->field.prev = head; \
157: } \
158: else { \
159: register queue_entry_t prev; \
160: \
161: prev = (head)->prev; \
162: (elt)->field.prev = prev; \
163: (elt)->field.next = head; \
164: (head)->prev = (queue_entry_t)(elt); \
165: ((type)prev)->field.next = (queue_entry_t)(elt);\
166: } \
167: MACRO_END
168:
169: /*
170: * Macro: queue_field [internal use only]
171: * Function:
172: * Find the queue_chain_t (or queue_t) for the
173: * given element (thing) in the given queue (head)
174: */
175: #define queue_field(head, thing, type, field) \
176: (((head) == (thing)) ? (head) : &((type)(thing))->field)
177:
178: /*
179: * Macro: queue_remove
180: * Header:
181: * void queue_remove(q, qe, type, field)
182: * arguments as in queue_enter
183: */
184: #define queue_remove(head, elt, type, field) \
185: MACRO_BEGIN \
186: register queue_entry_t next, prev; \
187: \
188: next = (elt)->field.next; \
189: prev = (elt)->field.prev; \
190: \
191: queue_field((head), next, type, field)->prev = prev; \
192: queue_field((head), prev, type, field)->next = next; \
193: MACRO_END
194:
195: /*
196: * Macro: queue_assign
197: */
198: #define queue_assign(to, from, type, field) \
199: MACRO_BEGIN \
200: ((type)((from)->prev))->field.next = (to); \
201: ((type)((from)->next))->field.prev = (to); \
202: *to = *from; \
203: MACRO_END
204:
205: #define queue_remove_first(h, e, t, f) \
206: MACRO_BEGIN \
207: e = (t) queue_first((h)); \
208: queue_remove((h), (e), t, f); \
209: MACRO_END
210:
211: #define queue_remove_last(h, e, t, f) \
212: MACRO_BEGIN \
213: e = (t) queue_last((h)); \
214: queue_remove((h), (e), t, f); \
215: MACRO_END
216:
217: /*
218: * Macro: queue_enter_first
219: * Header:
220: * void queue_enter_first(q, elt, type, field)
221: * queue_t q;
222: * <type> elt;
223: * <type> is what's in our queue
224: * <field> is the chain field in (*<type>)
225: */
226: #define queue_enter_first(head, elt, type, field) \
227: MACRO_BEGIN \
228: if (queue_empty((head))) { \
229: (head)->next = (queue_entry_t) elt; \
230: (head)->prev = (queue_entry_t) elt; \
231: (elt)->field.next = head; \
232: (elt)->field.prev = head; \
233: } \
234: else { \
235: register queue_entry_t next; \
236: \
237: next = (head)->next; \
238: (elt)->field.prev = head; \
239: (elt)->field.next = next; \
240: (head)->next = (queue_entry_t)(elt); \
241: ((type)next)->field.prev = (queue_entry_t)(elt);\
242: } \
243: MACRO_END
244:
245: /*
246: * Macro: queue_last
247: * Function:
248: * Returns the last entry in the queue,
249: * Header:
250: * queue_entry_t queue_last(q)
251: * queue_t q; \* IN *\
252: */
253: #define queue_last(q) ((q)->prev)
254:
255: /*
256: * Macro: queue_prev
257: * Header:
258: * queue_entry_t queue_prev(qc)
259: * queue_t qc;
260: */
261: #define queue_prev(qc) ((qc)->prev)
262:
263: /*
264: * Macro: queue_iterate
265: * Function:
266: * iterate over each item in the queue.
267: * Generates a 'for' loop, setting elt to
268: * each item in turn (by reference).
269: * Header:
270: * queue_iterate(q, elt, type, field)
271: * queue_t q;
272: * <type> elt;
273: * <type> is what's in our queue
274: * <field> is the chain field in (*<type>)
275: */
276: #define queue_iterate(head, elt, type, field) \
277: for ((elt) = (type) queue_first(head); \
278: !queue_end((head), (queue_entry_t)(elt)); \
279: (elt) = (type) queue_next(&(elt)->field))
280:
281: #ifdef KERNEL
282:
283: /*
284: * Define macros for queues with locks.
285: */
286: struct mpqueue_head {
287: struct queue_entry head; /* header for queue */
288: simple_lock_data_t lock; /* lock for queue */
289: };
290:
291: typedef struct mpqueue_head mpqueue_head_t;
292:
293: #define round_mpq(size) (size)
294:
295: #define mpqueue_init(q) \
296: MACRO_BEGIN \
297: queue_init(&(q)->head); \
298: simple_lock_init(&(q)->lock); \
299: MACRO_END
300:
301: #define mpenqueue_tail(q, elt) \
302: MACRO_BEGIN \
303: simple_lock(&(q)->lock); \
304: enqueue_tail(&(q)->head, elt); \
305: simple_unlock(&(q)->lock); \
306: MACRO_END
307:
308: #define mpdequeue_head(q, elt) \
309: MACRO_BEGIN \
310: simple_lock(&(q)->lock); \
311: if (queue_empty(&(q)->head)) \
312: *(elt) = 0; \
313: else \
314: *(elt) = dequeue_head(&(q)->head); \
315: simple_unlock(&(q)->lock); \
316: MACRO_END
317:
318: #endif /* KERNEL */
319:
320: #endif /* _KERN_QUEUE_H_ */
321:
322: #endif /* KERNEL_PRIVATE */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.