FreeBSD/Linux Kernel Cross Reference
sys/kern/queue.h
1 /*
2 * Mach Operating System
3 * Copyright (c) 1993-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 Software.Distribution@CS.CMU.EDU
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 * HISTORY
28 * $Log: queue.h,v $
29 * Revision 2.6 93/11/17 17:19:37 dbg
30 * Added remqueue_macro.
31 * [93/05/11 dbg]
32 *
33 * Added enqueue_tail_macro, dequeue_head_macro. Added ANSI
34 * function prototypes. Used macro_help.
35 * [93/04/01 dbg]
36 *
37 * Revision 2.5 92/05/21 17:15:24 jfriedl
38 * Removed comment starter from within comments to shut up gcc warnings.
39 * [92/05/16 jfriedl]
40 *
41 * Revision 2.4 91/05/14 16:45:55 mrt
42 * Correcting copyright
43 *
44 * Revision 2.3 91/02/05 17:28:43 mrt
45 * Changed to new Mach copyright
46 * [91/02/01 16:16:28 mrt]
47 *
48 * Revision 2.2 89/09/08 11:26:11 dbg
49 * Streamlined generic queue macros.
50 * [89/08/17 dbg]
51 *
52 * 19-Dec-88 David Golub (dbg) at Carnegie-Mellon University
53 * Added queue_remove_last; removed round_queue. [Changes from
54 * mwyoung: 19 Dec 88.]
55 *
56 * 29-Nov-88 David Golub (dbg) at Carnegie-Mellon University
57 * Removed include of cputypes.h. Added queue_iterate.
58 * Split into two groups the macros that operate directly on
59 * queues (or expect the queue chain to be first in a structure)
60 * and those that operate on generic structures (where the chain
61 * may be anywhere).
62 *
63 * 17-Jan-88 Daniel Julin (dpj) at Carnegie-Mellon University
64 * Added queue_enter_first, queue_last and queue_prev for use by
65 * the TCP netport code.
66 *
67 * 12-Jun-85 Avadis Tevanian (avie) at Carnegie-Mellon University
68 * Created.
69 *
70 */
71 /*
72 * File: queue.h
73 * Author: Avadis Tevanian, Jr.
74 * Date: 1985
75 *
76 * Type definitions for generic queues.
77 *
78 */
79
80 #ifndef _KERN_QUEUE_H_
81 #define _KERN_QUEUE_H_
82
83 #include <kern/lock.h>
84 #include <kern/macro_help.h>
85
86 /*
87 * Queue of abstract objects. Queue is maintained
88 * within that object.
89 *
90 * Supports fast removal from within the queue.
91 *
92 * How to declare a queue of elements of type "foo_t":
93 * In the "*foo_t" type, you must have a field of
94 * type "queue_chain_t" to hold together this queue.
95 * There may be more than one chain through a
96 * "foo_t", for use by different queues.
97 *
98 * Declare the queue as a "queue_t" type.
99 *
100 * Elements of the queue (of type "foo_t", that is)
101 * are referred to by reference, and cast to type
102 * "queue_entry_t" within this module.
103 */
104
105 /*
106 * A generic doubly-linked list (queue).
107 */
108
109 struct queue_entry {
110 struct queue_entry *next; /* next element */
111 struct queue_entry *prev; /* previous element */
112 };
113
114 typedef struct queue_entry *queue_t;
115 typedef struct queue_entry queue_head_t;
116 typedef struct queue_entry queue_chain_t;
117 typedef struct queue_entry *queue_entry_t;
118
119 /*
120 * enqueue puts "elt" on the "queue".
121 * dequeue returns the first element in the "queue".
122 * remqueue removes the specified "elt" from the specified "queue".
123 */
124
125 #define enqueue(queue,elt) enqueue_tail(queue, elt)
126 #define dequeue(queue) dequeue_head(queue)
127
128 void enqueue_head(queue_t que, queue_entry_t elt);
129 void enqueue_tail(queue_t que, queue_entry_t elt);
130 queue_entry_t dequeue_head(queue_t que);
131 queue_entry_t dequeue_tail(queue_t que);
132 void remqueue(queue_t que, queue_entry_t elt);
133
134 /*
135 * Macro: queue_init
136 * Function:
137 * Initialize the given queue.
138 * Header:
139 * void queue_init(q)
140 * queue_t q; *MODIFIED*
141 */
142 #define queue_init(q) ((q)->next = (q)->prev = q)
143
144 /*
145 * Macro: queue_first
146 * Function:
147 * Returns the first entry in the queue,
148 * Header:
149 * queue_entry_t queue_first(q)
150 * queue_t q; *IN*
151 */
152 #define queue_first(q) ((q)->next)
153
154 /*
155 * Macro: queue_next
156 * Function:
157 * Returns the entry after an item in the queue.
158 * Header:
159 * queue_entry_t queue_next(qc)
160 * queue_t qc;
161 */
162 #define queue_next(qc) ((qc)->next)
163
164 /*
165 * Macro: queue_last
166 * Function:
167 * Returns the last entry in the queue.
168 * Header:
169 * queue_entry_t queue_last(q)
170 * queue_t q; *IN*
171 */
172 #define queue_last(q) ((q)->prev)
173
174 /*
175 * Macro: queue_prev
176 * Function:
177 * Returns the entry before an item in the queue.
178 * Header:
179 * queue_entry_t queue_prev(qc)
180 * queue_t qc;
181 */
182 #define queue_prev(qc) ((qc)->prev)
183
184 /*
185 * Macro: queue_end
186 * Function:
187 * Tests whether a new entry is really the end of
188 * the queue.
189 * Header:
190 * boolean_t queue_end(q, qe)
191 * queue_t q;
192 * queue_entry_t qe;
193 */
194 #define queue_end(q, qe) ((q) == (qe))
195
196 /*
197 * Macro: queue_empty
198 * Function:
199 * Tests whether a queue is empty.
200 * Header:
201 * boolean_t queue_empty(q)
202 * queue_t q;
203 */
204 #define queue_empty(q) queue_end((q), queue_first(q))
205
206
207 /*
208 * Macro: enqueue_tail_macro
209 * Function:
210 * Adds the element at the tail of the queue.
211 * Header:
212 * void enqueue_tail_macro(queue_t que, queue_entry_t elt)
213 */
214 #define enqueue_tail_macro(que, elt) \
215 MACRO_BEGIN \
216 (elt)->next = (que); \
217 ((elt)->prev = (que)->prev)->next = (elt); \
218 (que)->prev = (elt); \
219 MACRO_END
220
221 /*
222 * Macro: dequeue_head_macro
223 * Function:
224 * Removes the element at the head of the queue.
225 * Assumes that the queue is not empty.
226 * Header:
227 * void dequeue_tail_macro(queue_t que, queue_entry_t& elt)
228 * (elt is an lvalue)
229 */
230 #define dequeue_head_macro(que, elt) \
231 MACRO_BEGIN \
232 (elt) = (que)->next; \
233 ((que)->next = (elt)->next)->prev = (que); \
234 MACRO_END
235
236 /*
237 * Macro: remqueue_macro
238 * Function:
239 * Removes an arbitrary element from the queue.
240 * Assumes that the element is on the queue.
241 * Header:
242 * void remqueue_macro(queue_t que, queue_entry_t elt)
243 */
244 #define remqueue_macro(que, elt) \
245 MACRO_BEGIN \
246 (elt)->next->prev = (elt)->prev; \
247 (elt)->prev->next = (elt)->next; \
248 MACRO_END
249
250 /*----------------------------------------------------------------*/
251 /*
252 * Macros that operate on generic structures. The queue
253 * chain may be at any location within the structure, and there
254 * may be more than one chain.
255 */
256
257 /*
258 * Macro: queue_enter
259 * Function:
260 * Insert a new element at the tail of the queue.
261 * Header:
262 * void queue_enter(q, elt, type, field)
263 * queue_t q;
264 * <type> elt;
265 * <type> is what's in our queue
266 * <field> is the chain field in (*<type>)
267 */
268 #define queue_enter(head, elt, type, field) \
269 MACRO_BEGIN \
270 register queue_entry_t prev; \
271 \
272 prev = (head)->prev; \
273 if ((head) == prev) { \
274 (head)->next = (queue_entry_t) (elt); \
275 } \
276 else { \
277 ((type)prev)->field.next = (queue_entry_t)(elt);\
278 } \
279 (elt)->field.prev = prev; \
280 (elt)->field.next = head; \
281 (head)->prev = (queue_entry_t) elt; \
282 MACRO_END
283
284 /*
285 * Macro: queue_enter_first
286 * Function:
287 * Insert a new element at the head of the queue.
288 * Header:
289 * void queue_enter_first(q, elt, type, field)
290 * queue_t q;
291 * <type> elt;
292 * <type> is what's in our queue
293 * <field> is the chain field in (*<type>)
294 */
295 #define queue_enter_first(head, elt, type, field) \
296 MACRO_BEGIN \
297 register queue_entry_t next; \
298 \
299 next = (head)->next; \
300 if ((head) == next) { \
301 (head)->prev = (queue_entry_t) (elt); \
302 } \
303 else { \
304 ((type)next)->field.prev = (queue_entry_t)(elt);\
305 } \
306 (elt)->field.next = next; \
307 (elt)->field.prev = head; \
308 (head)->next = (queue_entry_t) elt; \
309 MACRO_END
310
311 /*
312 * Macro: queue_field [internal use only]
313 * Function:
314 * Find the queue_chain_t (or queue_t) for the
315 * given element (thing) in the given queue (head)
316 */
317 #define queue_field(head, thing, type, field) \
318 (((head) == (thing)) ? (head) : &((type)(thing))->field)
319
320 /*
321 * Macro: queue_remove
322 * Function:
323 * Remove an arbitrary item from the queue.
324 * Header:
325 * void queue_remove(q, qe, type, field)
326 * arguments as in queue_enter
327 */
328 #define queue_remove(head, elt, type, field) \
329 MACRO_BEGIN \
330 register queue_entry_t next, prev; \
331 \
332 next = (elt)->field.next; \
333 prev = (elt)->field.prev; \
334 \
335 if ((head) == next) \
336 (head)->prev = prev; \
337 else \
338 ((type)next)->field.prev = prev; \
339 \
340 if ((head) == prev) \
341 (head)->next = next; \
342 else \
343 ((type)prev)->field.next = next; \
344 MACRO_END
345
346 /*
347 * Macro: queue_remove_first
348 * Function:
349 * Remove and return the entry at the head of
350 * the queue.
351 * Header:
352 * queue_remove_first(head, entry, type, field)
353 * entry is returned by reference
354 */
355 #define queue_remove_first(head, entry, type, field) \
356 MACRO_BEGIN \
357 register queue_entry_t next; \
358 \
359 (entry) = (type) ((head)->next); \
360 next = (entry)->field.next; \
361 \
362 if ((head) == next) \
363 (head)->prev = (head); \
364 else \
365 ((type)(next))->field.prev = (head); \
366 (head)->next = next; \
367 MACRO_END
368
369 /*
370 * Macro: queue_remove_last
371 * Function:
372 * Remove and return the entry at the tail of
373 * the queue.
374 * Header:
375 * queue_remove_last(head, entry, type, field)
376 * entry is returned by reference
377 */
378 #define queue_remove_last(head, entry, type, field) \
379 MACRO_BEGIN \
380 register queue_entry_t prev; \
381 \
382 (entry) = (type) ((head)->prev); \
383 prev = (entry)->field.prev; \
384 \
385 if ((head) == prev) \
386 (head)->next = (head); \
387 else \
388 ((type)(prev))->field.next = (head); \
389 (head)->prev = prev; \
390 MACRO_END
391
392 /*
393 * Macro: queue_assign
394 */
395 #define queue_assign(to, from, type, field) \
396 MACRO_BEGIN \
397 ((type)((from)->prev))->field.next = (to); \
398 ((type)((from)->next))->field.prev = (to); \
399 *to = *from; \
400 MACRO_END
401
402 /*
403 * Macro: queue_iterate
404 * Function:
405 * iterate over each item in the queue.
406 * Generates a 'for' loop, setting elt to
407 * each item in turn (by reference).
408 * Header:
409 * queue_iterate(q, elt, type, field)
410 * queue_t q;
411 * <type> elt;
412 * <type> is what's in our queue
413 * <field> is the chain field in (*<type>)
414 */
415 #define queue_iterate(head, elt, type, field) \
416 for ((elt) = (type) queue_first(head); \
417 !queue_end((head), (queue_entry_t)(elt)); \
418 (elt) = (type) queue_next(&(elt)->field))
419
420
421
422 /*----------------------------------------------------------------*/
423 /*
424 * Define macros for queues with locks.
425 */
426 struct mpqueue_head {
427 struct queue_entry head; /* header for queue */
428 struct slock lock; /* lock for queue */
429 };
430
431 typedef struct mpqueue_head mpqueue_head_t;
432
433 #define round_mpq(size) (size)
434
435 #define mpqueue_init(q) \
436 MACRO_BEGIN \
437 queue_init(&(q)->head); \
438 simple_lock_init(&(q)->lock); \
439 MACRO_END
440
441 #define mpenqueue_tail(q, elt) \
442 MACRO_BEGIN \
443 simple_lock(&(q)->lock); \
444 enqueue_tail(&(q)->head, elt); \
445 simple_unlock(&(q)->lock); \
446 MACRO_END
447
448 #define mpdequeue_head(q, elt) \
449 MACRO_BEGIN \
450 simple_lock(&(q)->lock); \
451 if (queue_empty(&(q)->head)) \
452 *(elt) = 0; \
453 else \
454 *(elt) = dequeue_head(&(q)->head); \
455 simple_unlock(&(q)->lock); \
456 MACRO_END
457
458 #endif /* _KERN_QUEUE_H_ */
Cache object: 07fb93e592d540d2bf7789a7ebcd4470
|