|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon rights ! 24: * to redistribute these changes. ! 25: */ ! 26: /* ! 27: * File: queue.h ! 28: * Author: Avadis Tevanian, Jr. ! 29: * Date: 1985 ! 30: * ! 31: * Type definitions for generic queues. ! 32: * ! 33: */ ! 34: ! 35: #ifndef _KERN_QUEUE_H_ ! 36: #define _KERN_QUEUE_H_ ! 37: ! 38: #include <kern/lock.h> ! 39: ! 40: /* ! 41: * Queue of abstract objects. Queue is maintained ! 42: * within that object. ! 43: * ! 44: * Supports fast removal from within the queue. ! 45: * ! 46: * How to declare a queue of elements of type "foo_t": ! 47: * In the "*foo_t" type, you must have a field of ! 48: * type "queue_chain_t" to hold together this queue. ! 49: * There may be more than one chain through a ! 50: * "foo_t", for use by different queues. ! 51: * ! 52: * Declare the queue as a "queue_t" type. ! 53: * ! 54: * Elements of the queue (of type "foo_t", that is) ! 55: * are referred to by reference, and cast to type ! 56: * "queue_entry_t" within this module. ! 57: */ ! 58: ! 59: /* ! 60: * A generic doubly-linked list (queue). ! 61: */ ! 62: ! 63: struct queue_entry { ! 64: struct queue_entry *next; /* next element */ ! 65: struct queue_entry *prev; /* previous element */ ! 66: }; ! 67: ! 68: typedef struct queue_entry *queue_t; ! 69: typedef struct queue_entry queue_head_t; ! 70: typedef struct queue_entry queue_chain_t; ! 71: typedef struct queue_entry *queue_entry_t; ! 72: ! 73: /* ! 74: * enqueue puts "elt" on the "queue". ! 75: * dequeue returns the first element in the "queue". ! 76: * remqueue removes the specified "elt" from the specified "queue". ! 77: */ ! 78: ! 79: #define enqueue(queue,elt) enqueue_tail(queue, elt) ! 80: #define dequeue(queue) dequeue_head(queue) ! 81: ! 82: void enqueue_head(); ! 83: void enqueue_tail(); ! 84: queue_entry_t dequeue_head(); ! 85: queue_entry_t dequeue_tail(); ! 86: void remqueue(); ! 87: ! 88: /* ! 89: * Macro: queue_init ! 90: * Function: ! 91: * Initialize the given queue. ! 92: * Header: ! 93: * void queue_init(q) ! 94: * queue_t q; *MODIFIED* ! 95: */ ! 96: #define queue_init(q) ((q)->next = (q)->prev = q) ! 97: ! 98: /* ! 99: * Macro: queue_first ! 100: * Function: ! 101: * Returns the first entry in the queue, ! 102: * Header: ! 103: * queue_entry_t queue_first(q) ! 104: * queue_t q; *IN* ! 105: */ ! 106: #define queue_first(q) ((q)->next) ! 107: ! 108: /* ! 109: * Macro: queue_next ! 110: * Function: ! 111: * Returns the entry after an item in the queue. ! 112: * Header: ! 113: * queue_entry_t queue_next(qc) ! 114: * queue_t qc; ! 115: */ ! 116: #define queue_next(qc) ((qc)->next) ! 117: ! 118: /* ! 119: * Macro: queue_last ! 120: * Function: ! 121: * Returns the last entry in the queue. ! 122: * Header: ! 123: * queue_entry_t queue_last(q) ! 124: * queue_t q; *IN* ! 125: */ ! 126: #define queue_last(q) ((q)->prev) ! 127: ! 128: /* ! 129: * Macro: queue_prev ! 130: * Function: ! 131: * Returns the entry before an item in the queue. ! 132: * Header: ! 133: * queue_entry_t queue_prev(qc) ! 134: * queue_t qc; ! 135: */ ! 136: #define queue_prev(qc) ((qc)->prev) ! 137: ! 138: /* ! 139: * Macro: queue_end ! 140: * Function: ! 141: * Tests whether a new entry is really the end of ! 142: * the queue. ! 143: * Header: ! 144: * boolean_t queue_end(q, qe) ! 145: * queue_t q; ! 146: * queue_entry_t qe; ! 147: */ ! 148: #define queue_end(q, qe) ((q) == (qe)) ! 149: ! 150: /* ! 151: * Macro: queue_empty ! 152: * Function: ! 153: * Tests whether a queue is empty. ! 154: * Header: ! 155: * boolean_t queue_empty(q) ! 156: * queue_t q; ! 157: */ ! 158: #define queue_empty(q) queue_end((q), queue_first(q)) ! 159: ! 160: ! 161: /*----------------------------------------------------------------*/ ! 162: /* ! 163: * Macros that operate on generic structures. The queue ! 164: * chain may be at any location within the structure, and there ! 165: * may be more than one chain. ! 166: */ ! 167: ! 168: /* ! 169: * Macro: queue_enter ! 170: * Function: ! 171: * Insert a new element at the tail of the queue. ! 172: * Header: ! 173: * void queue_enter(q, elt, type, field) ! 174: * queue_t q; ! 175: * <type> elt; ! 176: * <type> is what's in our queue ! 177: * <field> is the chain field in (*<type>) ! 178: */ ! 179: #define queue_enter(head, elt, type, field) \ ! 180: { \ ! 181: register queue_entry_t prev; \ ! 182: \ ! 183: prev = (head)->prev; \ ! 184: if ((head) == prev) { \ ! 185: (head)->next = (queue_entry_t) (elt); \ ! 186: } \ ! 187: else { \ ! 188: ((type)prev)->field.next = (queue_entry_t)(elt);\ ! 189: } \ ! 190: (elt)->field.prev = prev; \ ! 191: (elt)->field.next = head; \ ! 192: (head)->prev = (queue_entry_t) elt; \ ! 193: } ! 194: ! 195: /* ! 196: * Macro: queue_enter_first ! 197: * Function: ! 198: * Insert a new element at the head of the queue. ! 199: * Header: ! 200: * void queue_enter_first(q, elt, type, field) ! 201: * queue_t q; ! 202: * <type> elt; ! 203: * <type> is what's in our queue ! 204: * <field> is the chain field in (*<type>) ! 205: */ ! 206: #define queue_enter_first(head, elt, type, field) \ ! 207: { \ ! 208: register queue_entry_t next; \ ! 209: \ ! 210: next = (head)->next; \ ! 211: if ((head) == next) { \ ! 212: (head)->prev = (queue_entry_t) (elt); \ ! 213: } \ ! 214: else { \ ! 215: ((type)next)->field.prev = (queue_entry_t)(elt);\ ! 216: } \ ! 217: (elt)->field.next = next; \ ! 218: (elt)->field.prev = head; \ ! 219: (head)->next = (queue_entry_t) elt; \ ! 220: } ! 221: ! 222: /* ! 223: * Macro: queue_field [internal use only] ! 224: * Function: ! 225: * Find the queue_chain_t (or queue_t) for the ! 226: * given element (thing) in the given queue (head) ! 227: */ ! 228: #define queue_field(head, thing, type, field) \ ! 229: (((head) == (thing)) ? (head) : &((type)(thing))->field) ! 230: ! 231: /* ! 232: * Macro: queue_remove ! 233: * Function: ! 234: * Remove an arbitrary item from the queue. ! 235: * Header: ! 236: * void queue_remove(q, qe, type, field) ! 237: * arguments as in queue_enter ! 238: */ ! 239: #define queue_remove(head, elt, type, field) \ ! 240: { \ ! 241: register queue_entry_t next, prev; \ ! 242: \ ! 243: next = (elt)->field.next; \ ! 244: prev = (elt)->field.prev; \ ! 245: \ ! 246: if ((head) == next) \ ! 247: (head)->prev = prev; \ ! 248: else \ ! 249: ((type)next)->field.prev = prev; \ ! 250: \ ! 251: if ((head) == prev) \ ! 252: (head)->next = next; \ ! 253: else \ ! 254: ((type)prev)->field.next = next; \ ! 255: } ! 256: ! 257: /* ! 258: * Macro: queue_remove_first ! 259: * Function: ! 260: * Remove and return the entry at the head of ! 261: * the queue. ! 262: * Header: ! 263: * queue_remove_first(head, entry, type, field) ! 264: * entry is returned by reference ! 265: */ ! 266: #define queue_remove_first(head, entry, type, field) \ ! 267: { \ ! 268: register queue_entry_t next; \ ! 269: \ ! 270: (entry) = (type) ((head)->next); \ ! 271: next = (entry)->field.next; \ ! 272: \ ! 273: if ((head) == next) \ ! 274: (head)->prev = (head); \ ! 275: else \ ! 276: ((type)(next))->field.prev = (head); \ ! 277: (head)->next = next; \ ! 278: } ! 279: ! 280: /* ! 281: * Macro: queue_remove_last ! 282: * Function: ! 283: * Remove and return the entry at the tail of ! 284: * the queue. ! 285: * Header: ! 286: * queue_remove_last(head, entry, type, field) ! 287: * entry is returned by reference ! 288: */ ! 289: #define queue_remove_last(head, entry, type, field) \ ! 290: { \ ! 291: register queue_entry_t prev; \ ! 292: \ ! 293: (entry) = (type) ((head)->prev); \ ! 294: prev = (entry)->field.prev; \ ! 295: \ ! 296: if ((head) == prev) \ ! 297: (head)->next = (head); \ ! 298: else \ ! 299: ((type)(prev))->field.next = (head); \ ! 300: (head)->prev = prev; \ ! 301: } ! 302: ! 303: /* ! 304: * Macro: queue_assign ! 305: */ ! 306: #define queue_assign(to, from, type, field) \ ! 307: { \ ! 308: ((type)((from)->prev))->field.next = (to); \ ! 309: ((type)((from)->next))->field.prev = (to); \ ! 310: *to = *from; \ ! 311: } ! 312: ! 313: /* ! 314: * Macro: queue_iterate ! 315: * Function: ! 316: * iterate over each item in the queue. ! 317: * Generates a 'for' loop, setting elt to ! 318: * each item in turn (by reference). ! 319: * Header: ! 320: * queue_iterate(q, elt, type, field) ! 321: * queue_t q; ! 322: * <type> elt; ! 323: * <type> is what's in our queue ! 324: * <field> is the chain field in (*<type>) ! 325: */ ! 326: #define queue_iterate(head, elt, type, field) \ ! 327: for ((elt) = (type) queue_first(head); \ ! 328: !queue_end((head), (queue_entry_t)(elt)); \ ! 329: (elt) = (type) queue_next(&(elt)->field)) ! 330: ! 331: ! 332: ! 333: /*----------------------------------------------------------------*/ ! 334: /* ! 335: * Define macros for queues with locks. ! 336: */ ! 337: struct mpqueue_head { ! 338: struct queue_entry head; /* header for queue */ ! 339: struct slock lock; /* lock for queue */ ! 340: }; ! 341: ! 342: typedef struct mpqueue_head mpqueue_head_t; ! 343: ! 344: #define round_mpq(size) (size) ! 345: ! 346: #define mpqueue_init(q) \ ! 347: { \ ! 348: queue_init(&(q)->head); \ ! 349: simple_lock_init(&(q)->lock); \ ! 350: } ! 351: ! 352: #define mpenqueue_tail(q, elt) \ ! 353: simple_lock(&(q)->lock); \ ! 354: enqueue_tail(&(q)->head, elt); \ ! 355: simple_unlock(&(q)->lock); ! 356: ! 357: #define mpdequeue_head(q, elt) \ ! 358: simple_lock(&(q)->lock); \ ! 359: if (queue_empty(&(q)->head)) \ ! 360: *(elt) = 0; \ ! 361: else \ ! 362: *(elt) = dequeue_head(&(q)->head); \ ! 363: simple_unlock(&(q)->lock); ! 364: ! 365: /* ! 366: * Old queue stuff, will go away soon. ! 367: */ ! 368: ! 369: #endif /* _KERN_QUEUE_H_ */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.