|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
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.
11: *
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
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
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: */
52: /*
53: * File: queue.h
54: * Author: Avadis Tevanian, Jr.
55: * Date: 1985
56: *
57: * Type definitions for generic queues.
58: *
59: */
60:
61: #ifndef _KERN_QUEUE_H_
62: #define _KERN_QUEUE_H_
63:
64: #include <kern/lock.h>
65: #include <kern/macro_help.h>
66:
67: /*
68: * Queue of abstract objects. Queue is maintained
69: * within that object.
70: *
71: * Supports fast removal from within the queue.
72: *
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.
78: *
79: * Declare the queue as a "queue_t" type.
80: *
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.
84: */
85:
86: /*
87: * A generic doubly-linked list (queue).
88: */
89:
90: struct queue_entry {
91: struct queue_entry *next; /* next element */
92: struct queue_entry *prev; /* previous element */
93: };
94:
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;
99:
100: /*
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".
104: */
105:
106: #define enqueue(queue,elt) enqueue_tail(queue, elt)
107: #define dequeue(queue) dequeue_head(queue)
108:
109: #if !defined(__GNUC__)
110:
111: /* Enqueue element to head of queue */
112: extern void enqueue_head(
113: queue_t que,
114: queue_entry_t elt);
115:
116: /* Enqueue element to tail of queue */
117: extern void enqueue_tail(
118: queue_t que,
119: queue_entry_t elt);
120:
121: /* Dequeue element from head of queue */
122: extern queue_entry_t dequeue_head(
123: queue_t que);
124:
125: /* Dequeue element from tail of queue */
126: extern queue_entry_t dequeue_tail(
127: queue_t que);
128:
129: /* Dequeue element */
130: extern void remqueue(
131: queue_t que,
132: queue_entry_t elt);
133:
134: /* Enqueue element after a particular elem */
135: extern void insque(
136: queue_entry_t entry,
137: queue_entry_t pred);
138:
139: /* Dequeue element */
140: extern int remque(
141: queue_entry_t elt);
142:
143: #else
144:
145: static __inline__ void
146: enqueue_head(
147: queue_t que,
148: queue_entry_t elt)
149: {
150: elt->next = que->next;
151: elt->prev = que;
152: elt->next->prev = elt;
153: que->next = elt;
154: }
155:
156: static __inline__ void
157: enqueue_tail(
158: queue_t que,
159: queue_entry_t elt)
160: {
161: elt->next = que;
162: elt->prev = que->prev;
163: elt->prev->next = elt;
164: que->prev = elt;
165: }
166:
167: static __inline__ queue_entry_t
168: dequeue_head(
169: queue_t que)
170: {
171: register queue_entry_t elt = (queue_entry_t) 0;
172:
173: if (que->next != que) {
174: elt = que->next;
175: elt->next->prev = que;
176: que->next = elt->next;
177: }
178:
179: return (elt);
180: }
181:
182: static __inline__ queue_entry_t
183: dequeue_tail(
184: queue_t que)
185: {
186: register queue_entry_t elt = (queue_entry_t) 0;
187:
188: if (que->prev != que) {
189: elt = que->prev;
190: elt->prev->next = que;
191: que->prev = elt->prev;
192: }
193:
194: return (elt);
195: }
196:
197: static __inline__ void
198: remqueue(
199: queue_t que,
200: queue_entry_t elt)
201: {
202: elt->next->prev = elt->prev;
203: elt->prev->next = elt->next;
204: }
205:
206: static __inline__ void
207: insque(
208: queue_entry_t entry,
209: queue_entry_t pred)
210: {
211: entry->next = pred->next;
212: entry->prev = pred;
213: (pred->next)->prev = entry;
214: pred->next = entry;
215: }
216:
217: static __inline__ integer_t
218: remque(
219: register queue_entry_t elt)
220: {
221: (elt->next)->prev = elt->prev;
222: (elt->prev)->next = elt->next;
223:
224: return((integer_t)elt);
225: }
226:
227: #endif /* defined(__GNUC__) */
228:
229: /*
230: * Macro: queue_init
231: * Function:
232: * Initialize the given queue.
233: * Header:
234: * void queue_init(q)
235: * queue_t q; \* MODIFIED *\
236: */
237: #define queue_init(q) \
238: MACRO_BEGIN \
239: (q)->next = (q);\
240: (q)->prev = (q);\
241: MACRO_END
242:
243: /*
244: * Macro: queue_first
245: * Function:
246: * Returns the first entry in the queue,
247: * Header:
248: * queue_entry_t queue_first(q)
249: * queue_t q; \* IN *\
250: */
251: #define queue_first(q) ((q)->next)
252:
253: /*
254: * Macro: queue_next
255: * Function:
256: * Returns the entry after an item in the queue.
257: * Header:
258: * queue_entry_t queue_next(qc)
259: * queue_t qc;
260: */
261: #define queue_next(qc) ((qc)->next)
262:
263: /*
264: * Macro: queue_last
265: * Function:
266: * Returns the last entry in the queue.
267: * Header:
268: * queue_entry_t queue_last(q)
269: * queue_t q; \* IN *\
270: */
271: #define queue_last(q) ((q)->prev)
272:
273: /*
274: * Macro: queue_prev
275: * Function:
276: * Returns the entry before an item in the queue.
277: * Header:
278: * queue_entry_t queue_prev(qc)
279: * queue_t qc;
280: */
281: #define queue_prev(qc) ((qc)->prev)
282:
283: /*
284: * Macro: queue_end
285: * Function:
286: * Tests whether a new entry is really the end of
287: * the queue.
288: * Header:
289: * boolean_t queue_end(q, qe)
290: * queue_t q;
291: * queue_entry_t qe;
292: */
293: #define queue_end(q, qe) ((q) == (qe))
294:
295: /*
296: * Macro: queue_empty
297: * Function:
298: * Tests whether a queue is empty.
299: * Header:
300: * boolean_t queue_empty(q)
301: * queue_t q;
302: */
303: #define queue_empty(q) queue_end((q), queue_first(q))
304:
305:
306: /*----------------------------------------------------------------*/
307: /*
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.
311: */
312:
313: /*
314: * Macro: queue_enter
315: * Function:
316: * Insert a new element at the tail of the queue.
317: * Header:
318: * void queue_enter(q, elt, type, field)
319: * queue_t q;
320: * <type> elt;
321: * <type> is what's in our queue
322: * <field> is the chain field in (*<type>)
323: */
324: #define queue_enter(head, elt, type, field) \
325: MACRO_BEGIN \
326: register queue_entry_t prev; \
327: \
328: prev = (head)->prev; \
329: if ((head) == prev) { \
330: (head)->next = (queue_entry_t) (elt); \
331: } \
332: else { \
333: ((type)prev)->field.next = (queue_entry_t)(elt);\
334: } \
335: (elt)->field.prev = prev; \
336: (elt)->field.next = head; \
337: (head)->prev = (queue_entry_t) elt; \
338: MACRO_END
339:
340: /*
341: * Macro: queue_enter_first
342: * Function:
343: * Insert a new element at the head of the queue.
344: * Header:
345: * void queue_enter_first(q, elt, type, field)
346: * queue_t q;
347: * <type> elt;
348: * <type> is what's in our queue
349: * <field> is the chain field in (*<type>)
350: */
351: #define queue_enter_first(head, elt, type, field) \
352: MACRO_BEGIN \
353: register queue_entry_t next; \
354: \
355: next = (head)->next; \
356: if ((head) == next) { \
357: (head)->prev = (queue_entry_t) (elt); \
358: } \
359: else { \
360: ((type)next)->field.prev = (queue_entry_t)(elt);\
361: } \
362: (elt)->field.next = next; \
363: (elt)->field.prev = head; \
364: (head)->next = (queue_entry_t) elt; \
365: MACRO_END
366:
367: /*
368: * Macro: queue_insert_before
369: * Function:
370: * Insert a new element before a given element.
371: * Header:
372: * void queue_insert_before(q, elt, cur, type, field)
373: * queue_t q;
374: * <type> elt;
375: * <type> cur;
376: * <type> is what's in our queue
377: * <field> is the chain field in (*<type>)
378: */
379: #define queue_insert_before(head, elt, cur, type, field) \
380: MACRO_BEGIN \
381: register queue_entry_t prev; \
382: \
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);\
391: } \
392: (head)->prev = (queue_entry_t)(elt); \
393: } else { \
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);\
402: } \
403: (cur)->field.prev = (queue_entry_t)(elt); \
404: } \
405: MACRO_END
406:
407: /*
408: * Macro: queue_insert_after
409: * Function:
410: * Insert a new element after a given element.
411: * Header:
412: * void queue_insert_after(q, elt, cur, type, field)
413: * queue_t q;
414: * <type> elt;
415: * <type> cur;
416: * <type> is what's in our queue
417: * <field> is the chain field in (*<type>)
418: */
419: #define queue_insert_after(head, elt, cur, type, field) \
420: MACRO_BEGIN \
421: register queue_entry_t next; \
422: \
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);\
431: } \
432: (head)->next = (queue_entry_t)(elt); \
433: } else { \
434: (elt)->field.prev = (queue_entry_t)(cur); \
435: if ((head)->prev == (queue_entry_t)(cur)) { \
436: /* last element */ \
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);\
442: } \
443: (cur)->field.next = (queue_entry_t)(elt); \
444: } \
445: MACRO_END
446:
447: /*
448: * Macro: queue_field [internal use only]
449: * Function:
450: * Find the queue_chain_t (or queue_t) for the
451: * given element (thing) in the given queue (head)
452: */
453: #define queue_field(head, thing, type, field) \
454: (((head) == (thing)) ? (head) : &((type)(thing))->field)
455:
456: /*
457: * Macro: queue_remove
458: * Function:
459: * Remove an arbitrary item from the queue.
460: * Header:
461: * void queue_remove(q, qe, type, field)
462: * arguments as in queue_enter
463: */
464: #define queue_remove(head, elt, type, field) \
465: MACRO_BEGIN \
466: register queue_entry_t next, prev; \
467: \
468: next = (elt)->field.next; \
469: prev = (elt)->field.prev; \
470: \
471: if ((head) == next) \
472: (head)->prev = prev; \
473: else \
474: ((type)next)->field.prev = prev; \
475: \
476: if ((head) == prev) \
477: (head)->next = next; \
478: else \
479: ((type)prev)->field.next = next; \
480: MACRO_END
481:
482: /*
483: * Macro: queue_remove_first
484: * Function:
485: * Remove and return the entry at the head of
486: * the queue.
487: * Header:
488: * queue_remove_first(head, entry, type, field)
489: * entry is returned by reference
490: */
491: #define queue_remove_first(head, entry, type, field) \
492: MACRO_BEGIN \
493: register queue_entry_t next; \
494: \
495: (entry) = (type) ((head)->next); \
496: next = (entry)->field.next; \
497: \
498: if ((head) == next) \
499: (head)->prev = (head); \
500: else \
501: ((type)(next))->field.prev = (head); \
502: (head)->next = next; \
503: MACRO_END
504:
505: /*
506: * Macro: queue_remove_last
507: * Function:
508: * Remove and return the entry at the tail of
509: * the queue.
510: * Header:
511: * queue_remove_last(head, entry, type, field)
512: * entry is returned by reference
513: */
514: #define queue_remove_last(head, entry, type, field) \
515: MACRO_BEGIN \
516: register queue_entry_t prev; \
517: \
518: (entry) = (type) ((head)->prev); \
519: prev = (entry)->field.prev; \
520: \
521: if ((head) == prev) \
522: (head)->next = (head); \
523: else \
524: ((type)(prev))->field.next = (head); \
525: (head)->prev = prev; \
526: MACRO_END
527:
528: /*
529: * Macro: queue_assign
530: */
531: #define queue_assign(to, from, type, field) \
532: MACRO_BEGIN \
533: ((type)((from)->prev))->field.next = (to); \
534: ((type)((from)->next))->field.prev = (to); \
535: *to = *from; \
536: MACRO_END
537:
538: /*
539: * Macro: queue_new_head
540: * Function:
541: * rebase old queue to new queue head
542: * Header:
543: * queue_new_head(old, new, type, field)
544: * queue_t old;
545: * queue_t new;
546: * <type> is what's in our queue
547: * <field> is the chain field in (*<type>)
548: */
549: #define queue_new_head(old, new, type, field) \
550: MACRO_BEGIN \
551: if (!queue_empty(new)) { \
552: *(new) = *(old); \
553: ((type)((new)->next))->field.prev = (new); \
554: ((type)((new)->prev))->field.next = (new); \
555: } else { \
556: queue_init(new); \
557: } \
558: MACRO_END
559:
560: /*
561: * Macro: queue_iterate
562: * Function:
563: * iterate over each item in the queue.
564: * Generates a 'for' loop, setting elt to
565: * each item in turn (by reference).
566: * Header:
567: * queue_iterate(q, elt, type, field)
568: * queue_t q;
569: * <type> elt;
570: * <type> is what's in our queue
571: * <field> is the chain field in (*<type>)
572: */
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))
577:
578:
579: #ifdef MACH_KERNEL_PRIVATE
580: /*----------------------------------------------------------------*/
581: /*
582: * Define macros for queues with locks.
583: */
584: struct mpqueue_head {
585: struct queue_entry head; /* header for queue */
586: decl_simple_lock_data(, lock) /* lock for queue */
587: };
588:
589: typedef struct mpqueue_head mpqueue_head_t;
590:
591: #define round_mpq(size) (size)
592:
593: #define mpqueue_init(q) \
594: MACRO_BEGIN \
595: queue_init(&(q)->head); \
596: simple_lock_init(&(q)->lock, ETAP_MISC_Q); \
597: MACRO_END
598:
599: #define mpenqueue_tail(q, elt) \
600: MACRO_BEGIN \
601: simple_lock(&(q)->lock); \
602: enqueue_tail(&(q)->head, elt); \
603: simple_unlock(&(q)->lock); \
604: MACRO_END
605:
606: #define mpdequeue_head(q, elt) \
607: MACRO_BEGIN \
608: simple_lock(&(q)->lock); \
609: if (queue_empty(&(q)->head)) \
610: *(elt) = 0; \
611: else \
612: *(elt) = dequeue_head(&(q)->head); \
613: simple_unlock(&(q)->lock); \
614: MACRO_END
615:
616: #endif /* MACH_KERNEL_PRIVATE */
617:
618: #endif /* _KERN_QUEUE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.