|
|
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) 1991,1990,1989,1988,1987 Carnegie Mellon University
28: * All Rights Reserved.
29: *
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.
35: *
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.
39: *
40: * Carnegie Mellon requests users of this software to return to
41: *
42: * Software Distribution Coordinator or [email protected]
43: * School of Computer Science
44: * Carnegie Mellon University
45: * Pittsburgh PA 15213-3890
46: *
47: * any improvements or extensions that they make and grant Carnegie Mellon rights
48: * to redistribute these changes.
49: */
50: /*
51: * File: queue.h
52: * Author: Avadis Tevanian, Jr.
53: * Date: 1985
54: *
55: * Type definitions for generic queues.
56: *
57: */
58:
59: #ifndef _KERN_QUEUE_H_
60: #define _KERN_QUEUE_H_
61:
62: #include <kern/lock.h>
63: #include <kern/macro_help.h>
64:
65: /*
66: * Queue of abstract objects. Queue is maintained
67: * within that object.
68: *
69: * Supports fast removal from within the queue.
70: *
71: * How to declare a queue of elements of type "foo_t":
72: * In the "*foo_t" type, you must have a field of
73: * type "queue_chain_t" to hold together this queue.
74: * There may be more than one chain through a
75: * "foo_t", for use by different queues.
76: *
77: * Declare the queue as a "queue_t" type.
78: *
79: * Elements of the queue (of type "foo_t", that is)
80: * are referred to by reference, and cast to type
81: * "queue_entry_t" within this module.
82: */
83:
84: /*
85: * A generic doubly-linked list (queue).
86: */
87:
88: struct queue_entry {
89: struct queue_entry *next; /* next element */
90: struct queue_entry *prev; /* previous element */
91: };
92:
93: typedef struct queue_entry *queue_t;
94: typedef struct queue_entry queue_head_t;
95: typedef struct queue_entry queue_chain_t;
96: typedef struct queue_entry *queue_entry_t;
97:
98: /*
99: * enqueue puts "elt" on the "queue".
100: * dequeue returns the first element in the "queue".
101: * remqueue removes the specified "elt" from the specified "queue".
102: */
103:
104: #define enqueue(queue,elt) enqueue_tail(queue, elt)
105: #define dequeue(queue) dequeue_head(queue)
106:
107: /*
108: * Routines to implement queue package.
109: */
110:
111: #ifndef _KERN_QUEUE_FUNCTION_SCOPE_
112: #define _KERN_QUEUE_FUNCTION_SCOPE_ static __inline__
113: #define _KERN_QUEUE_H_INTERNAL_SCOPING_
114: #endif
115:
116: /*
117: * Insert element at head of queue.
118: */
119: _KERN_QUEUE_FUNCTION_SCOPE_
120: void enqueue_head(
121: register queue_t que,
122: register queue_entry_t elt)
123: {
124: elt->next = que->next;
125: elt->prev = que;
126: elt->next->prev = elt;
127: que->next = elt;
128: }
129:
130: /*
131: * Insert element at tail of queue.
132: */
133: _KERN_QUEUE_FUNCTION_SCOPE_
134: void enqueue_tail(
135: register queue_t que,
136: register queue_entry_t elt)
137: {
138: elt->next = que;
139: elt->prev = que->prev;
140: elt->prev->next = elt;
141: que->prev = elt;
142: }
143:
144: /*
145: * Remove and return element at head of queue.
146: */
147: _KERN_QUEUE_FUNCTION_SCOPE_
148: queue_entry_t dequeue_head(
149: register queue_t que)
150: {
151: register queue_entry_t elt;
152:
153: if (que->next == que)
154: return((queue_entry_t)0);
155:
156: elt = que->next;
157: elt->next->prev = que;
158: que->next = elt->next;
159: return(elt);
160: }
161:
162: /*
163: * Remove and return element at tail of queue.
164: */
165: _KERN_QUEUE_FUNCTION_SCOPE_
166: queue_entry_t dequeue_tail(
167: register queue_t que)
168: {
169: register queue_entry_t elt;
170:
171: if (que->prev == que)
172: return((queue_entry_t)0);
173:
174: elt = que->prev;
175: elt->prev->next = que;
176: que->prev = elt->prev;
177: return(elt);
178: }
179:
180: /*
181: * Remove arbitrary element from queue.
182: * Does not check whether element is on queue - the world
183: * will go haywire if it isn't.
184: */
185:
186: _KERN_QUEUE_FUNCTION_SCOPE_
187: /*ARGSUSED*/
188: void remqueue(
189: queue_t que,
190: register queue_entry_t elt)
191: {
192: elt->next->prev = elt->prev;
193: elt->prev->next = elt->next;
194: }
195:
196: /*
197: * Routines to directly imitate the VAX hardware queue
198: * package.
199: */
200: _KERN_QUEUE_FUNCTION_SCOPE_
201: void insque(
202: register struct queue_entry *entry,
203: register struct queue_entry *pred)
204: {
205: entry->next = pred->next;
206: entry->prev = pred;
207: (pred->next)->prev = entry;
208: pred->next = entry;
209: }
210:
211: _KERN_QUEUE_FUNCTION_SCOPE_
212: struct queue_entry
213: *remque(
214: register struct queue_entry *elt)
215: {
216: (elt->next)->prev = elt->prev;
217: (elt->prev)->next = elt->next;
218: return(elt);
219: }
220:
221: #ifdef _KERN_QUEUE_H_INTERNAL_SCOPING_
222: #undef _KERN_QUEUE_H_INTERNAL_SCOPING_
223: #endif
224:
225: /*
226: * Macro: queue_init
227: * Function:
228: * Initialize the given queue.
229: * Header:
230: * void queue_init(q)
231: * queue_t q; *MODIFIED*
232: */
233: #define queue_init(q) ((q)->next = (q)->prev = q)
234:
235: /*
236: * Macro: queue_first
237: * Function:
238: * Returns the first entry in the queue,
239: * Header:
240: * queue_entry_t queue_first(q)
241: * queue_t q; *IN*
242: */
243: #define queue_first(q) ((q)->next)
244:
245: /*
246: * Macro: queue_next
247: * Function:
248: * Returns the entry after an item in the queue.
249: * Header:
250: * queue_entry_t queue_next(qc)
251: * queue_t qc;
252: */
253: #define queue_next(qc) ((qc)->next)
254:
255: /*
256: * Macro: queue_last
257: * Function:
258: * Returns the last entry in the queue.
259: * Header:
260: * queue_entry_t queue_last(q)
261: * queue_t q; *IN*
262: */
263: #define queue_last(q) ((q)->prev)
264:
265: /*
266: * Macro: queue_prev
267: * Function:
268: * Returns the entry before an item in the queue.
269: * Header:
270: * queue_entry_t queue_prev(qc)
271: * queue_t qc;
272: */
273: #define queue_prev(qc) ((qc)->prev)
274:
275: /*
276: * Macro: queue_end
277: * Function:
278: * Tests whether a new entry is really the end of
279: * the queue.
280: * Header:
281: * boolean_t queue_end(q, qe)
282: * queue_t q;
283: * queue_entry_t qe;
284: */
285: #define queue_end(q, qe) ((q) == (qe))
286:
287: /*
288: * Macro: queue_empty
289: * Function:
290: * Tests whether a queue is empty.
291: * Header:
292: * boolean_t queue_empty(q)
293: * queue_t q;
294: */
295: #define queue_empty(q) queue_end((q), queue_first(q))
296:
297:
298: /*----------------------------------------------------------------*/
299: /*
300: * Macros that operate on generic structures. The queue
301: * chain may be at any location within the structure, and there
302: * may be more than one chain.
303: */
304:
305: /*
306: * Macro: queue_enter
307: * Function:
308: * Insert a new element at the tail of the queue.
309: * Header:
310: * void queue_enter(q, elt, type, field)
311: * queue_t q;
312: * <type> elt;
313: * <type> is what's in our queue
314: * <field> is the chain field in (*<type>)
315: */
316: #define queue_enter(head, elt, type, field) \
317: MACRO_BEGIN \
318: register queue_entry_t prev; \
319: \
320: prev = (head)->prev; \
321: if ((head) == prev) { \
322: (head)->next = (queue_entry_t) (elt); \
323: } \
324: else { \
325: ((type)prev)->field.next = (queue_entry_t)(elt);\
326: } \
327: (elt)->field.prev = prev; \
328: (elt)->field.next = head; \
329: (head)->prev = (queue_entry_t) elt; \
330: MACRO_END
331:
332: /*
333: * Macro: queue_enter_first
334: * Function:
335: * Insert a new element at the head of the queue.
336: * Header:
337: * void queue_enter_first(q, elt, type, field)
338: * queue_t q;
339: * <type> elt;
340: * <type> is what's in our queue
341: * <field> is the chain field in (*<type>)
342: */
343: #define queue_enter_first(head, elt, type, field) \
344: MACRO_BEGIN \
345: register queue_entry_t next; \
346: \
347: next = (head)->next; \
348: if ((head) == next) { \
349: (head)->prev = (queue_entry_t) (elt); \
350: } \
351: else { \
352: ((type)next)->field.prev = (queue_entry_t)(elt);\
353: } \
354: (elt)->field.next = next; \
355: (elt)->field.prev = head; \
356: (head)->next = (queue_entry_t) elt; \
357: MACRO_END
358:
359: /*
360: * Macro: queue_field [internal use only]
361: * Function:
362: * Find the queue_chain_t (or queue_t) for the
363: * given element (thing) in the given queue (head)
364: */
365: #define queue_field(head, thing, type, field) \
366: (((head) == (thing)) ? (head) : &((type)(thing))->field)
367:
368: /*
369: * Macro: queue_remove
370: * Function:
371: * Remove an arbitrary item from the queue.
372: * Header:
373: * void queue_remove(q, qe, type, field)
374: * arguments as in queue_enter
375: */
376: #define queue_remove(head, elt, type, field) \
377: MACRO_BEGIN \
378: register queue_entry_t next, prev; \
379: \
380: next = (elt)->field.next; \
381: prev = (elt)->field.prev; \
382: \
383: if ((head) == next) \
384: (head)->prev = prev; \
385: else \
386: ((type)next)->field.prev = prev; \
387: \
388: if ((head) == prev) \
389: (head)->next = next; \
390: else \
391: ((type)prev)->field.next = next; \
392: MACRO_END
393:
394: /*
395: * Macro: queue_remove_first
396: * Function:
397: * Remove and return the entry at the head of
398: * the queue.
399: * Header:
400: * queue_remove_first(head, entry, type, field)
401: * entry is returned by reference
402: */
403: #define queue_remove_first(head, entry, type, field) \
404: MACRO_BEGIN \
405: register queue_entry_t next; \
406: \
407: (entry) = (type) ((head)->next); \
408: next = (entry)->field.next; \
409: \
410: if ((head) == next) \
411: (head)->prev = (head); \
412: else \
413: ((type)(next))->field.prev = (head); \
414: (head)->next = next; \
415: MACRO_END
416:
417: /*
418: * Macro: queue_remove_last
419: * Function:
420: * Remove and return the entry at the tail of
421: * the queue.
422: * Header:
423: * queue_remove_last(head, entry, type, field)
424: * entry is returned by reference
425: */
426: #define queue_remove_last(head, entry, type, field) \
427: MACRO_BEGIN \
428: register queue_entry_t prev; \
429: \
430: (entry) = (type) ((head)->prev); \
431: prev = (entry)->field.prev; \
432: \
433: if ((head) == prev) \
434: (head)->next = (head); \
435: else \
436: ((type)(prev))->field.next = (head); \
437: (head)->prev = prev; \
438: MACRO_END
439:
440: /*
441: * Macro: queue_assign
442: */
443: #define queue_assign(to, from, type, field) \
444: MACRO_BEGIN \
445: ((type)((from)->prev))->field.next = (to); \
446: ((type)((from)->next))->field.prev = (to); \
447: *to = *from; \
448: MACRO_END
449:
450: /*
451: * Macro: queue_iterate
452: * Function:
453: * iterate over each item in the queue.
454: * Generates a 'for' loop, setting elt to
455: * each item in turn (by reference).
456: * Header:
457: * queue_iterate(q, elt, type, field)
458: * queue_t q;
459: * <type> elt;
460: * <type> is what's in our queue
461: * <field> is the chain field in (*<type>)
462: */
463: #define queue_iterate(head, elt, type, field) \
464: for ((elt) = (type) queue_first(head); \
465: !queue_end((head), (queue_entry_t)(elt)); \
466: (elt) = (type) queue_next(&(elt)->field))
467:
468: #endif /* _KERN_QUEUE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.