Subversion Repositories Kolibri OS

Rev

Rev 4874 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
4921 Serge 1
/*-
4349 Serge 2
 * Copyright (c) 1991, 1993
3
 *	The Regents of the University of California.  All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions
7
 * are met:
8
 * 1. Redistributions of source code must retain the above copyright
9
 *    notice, this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright
11
 *    notice, this list of conditions and the following disclaimer in the
12
 *    documentation and/or other materials provided with the distribution.
13
 * 4. Neither the name of the University nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 *
29
 *	@(#)queue.h	8.5 (Berkeley) 8/20/94
4921 Serge 30
 * $FreeBSD$
4349 Serge 31
 */
32
 
33
#ifndef _SYS_QUEUE_H_
34
#define	_SYS_QUEUE_H_
35
 
4921 Serge 36
#include 
4349 Serge 37
 
38
/*
39
 * This file defines four types of data structures: singly-linked lists,
40
 * singly-linked tail queues, lists and tail queues.
41
 *
42
 * A singly-linked list is headed by a single forward pointer. The elements
43
 * are singly linked for minimum space and pointer manipulation overhead at
44
 * the expense of O(n) removal for arbitrary elements. New elements can be
45
 * added to the list after an existing element or at the head of the list.
46
 * Elements being removed from the head of the list should use the explicit
47
 * macro for this purpose for optimum efficiency. A singly-linked list may
48
 * only be traversed in the forward direction.  Singly-linked lists are ideal
49
 * for applications with large datasets and few or no removals or for
50
 * implementing a LIFO queue.
51
 *
52
 * A singly-linked tail queue is headed by a pair of pointers, one to the
53
 * head of the list and the other to the tail of the list. The elements are
54
 * singly linked for minimum space and pointer manipulation overhead at the
55
 * expense of O(n) removal for arbitrary elements. New elements can be added
56
 * to the list after an existing element, at the head of the list, or at the
57
 * end of the list. Elements being removed from the head of the tail queue
58
 * should use the explicit macro for this purpose for optimum efficiency.
59
 * A singly-linked tail queue may only be traversed in the forward direction.
60
 * Singly-linked tail queues are ideal for applications with large datasets
61
 * and few or no removals or for implementing a FIFO queue.
62
 *
63
 * A list is headed by a single forward pointer (or an array of forward
64
 * pointers for a hash table header). The elements are doubly linked
65
 * so that an arbitrary element can be removed without a need to
66
 * traverse the list. New elements can be added to the list before
67
 * or after an existing element or at the head of the list. A list
4921 Serge 68
 * may be traversed in either direction.
4349 Serge 69
 *
70
 * A tail queue is headed by a pair of pointers, one to the head of the
71
 * list and the other to the tail of the list. The elements are doubly
72
 * linked so that an arbitrary element can be removed without a need to
73
 * traverse the list. New elements can be added to the list before or
74
 * after an existing element, at the head of the list, or at the end of
75
 * the list. A tail queue may be traversed in either direction.
76
 *
77
 * For details on the use of these macros, see the queue(3) manual page.
78
 *
79
 *
80
 *			SLIST	LIST	STAILQ	TAILQ
81
 * _HEAD		+	+	+	+
82
 * _HEAD_INITIALIZER	+	+	+	+
83
 * _ENTRY		+	+	+	+
84
 * _INIT		+	+	+	+
85
 * _EMPTY		+	+	+	+
86
 * _FIRST		+	+	+	+
87
 * _NEXT		+	+	+	+
4921 Serge 88
 * _PREV			-	+	-	+
4349 Serge 89
 * _LAST		-	-	+	+
90
 * _FOREACH		+	+	+	+
4921 Serge 91
 * _FOREACH_SAFE		+	+	+	+
4349 Serge 92
 * _FOREACH_REVERSE	-	-	-	+
4921 Serge 93
 * _FOREACH_REVERSE_SAFE	-	-	-	+
4349 Serge 94
 * _INSERT_HEAD		+	+	+	+
95
 * _INSERT_BEFORE	-	+	-	+
96
 * _INSERT_AFTER	+	+	+	+
97
 * _INSERT_TAIL		-	-	+	+
98
 * _CONCAT		-	-	+	+
4921 Serge 99
 * _REMOVE_AFTER		+	-	+	-
4349 Serge 100
 * _REMOVE_HEAD		+	-	+	-
101
 * _REMOVE		+	+	+	+
4921 Serge 102
 * _SWAP			+	+	+	+
4349 Serge 103
 *
104
 */
4921 Serge 105
#ifdef QUEUE_MACRO_DEBUG
106
/* Store the last 2 places the queue element or head was altered */
107
struct qm_trace {
108
	unsigned long	 lastline;
109
	unsigned long	 prevline;
110
	const char	*lastfile;
111
	const char	*prevfile;
112
};
4349 Serge 113
 
4921 Serge 114
#define	TRACEBUF	struct qm_trace trace;
115
#define	TRACEBUF_INITIALIZER	{ __FILE__, __LINE__, NULL, 0 } ,
116
#define	TRASHIT(x)	do {(x) = (void *)-1;} while (0)
117
#define	QMD_SAVELINK(name, link)	void **name = (void *)&(link)
118
 
119
#define	QMD_TRACE_HEAD(head) do {					\
120
	(head)->trace.prevline = (head)->trace.lastline;		\
121
	(head)->trace.prevfile = (head)->trace.lastfile;		\
122
	(head)->trace.lastline = __LINE__;				\
123
	(head)->trace.lastfile = __FILE__;				\
124
} while (0)
125
 
126
#define	QMD_TRACE_ELEM(elem) do {					\
127
	(elem)->trace.prevline = (elem)->trace.lastline;		\
128
	(elem)->trace.prevfile = (elem)->trace.lastfile;		\
129
	(elem)->trace.lastline = __LINE__;				\
130
	(elem)->trace.lastfile = __FILE__;				\
131
} while (0)
132
 
133
#else
134
#define	QMD_TRACE_ELEM(elem)
135
#define	QMD_TRACE_HEAD(head)
136
#define	QMD_SAVELINK(name, link)
137
#define	TRACEBUF
138
#define	TRACEBUF_INITIALIZER
139
#define	TRASHIT(x)
140
#endif	/* QUEUE_MACRO_DEBUG */
141
 
4349 Serge 142
/*
143
 * Singly-linked List declarations.
144
 */
145
#define	SLIST_HEAD(name, type)						\
146
struct name {								\
147
	struct type *slh_first;	/* first element */			\
148
}
149
 
150
#define	SLIST_HEAD_INITIALIZER(head)					\
151
	{ NULL }
152
 
153
#define	SLIST_ENTRY(type)						\
154
struct {								\
155
	struct type *sle_next;	/* next element */			\
156
}
157
 
158
/*
159
 * Singly-linked List functions.
160
 */
161
#define	SLIST_EMPTY(head)	((head)->slh_first == NULL)
162
 
163
#define	SLIST_FIRST(head)	((head)->slh_first)
164
 
165
#define	SLIST_FOREACH(var, head, field)					\
166
	for ((var) = SLIST_FIRST((head));				\
167
	    (var);							\
168
	    (var) = SLIST_NEXT((var), field))
169
 
4921 Serge 170
#define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\
171
	for ((var) = SLIST_FIRST((head));				\
172
	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\
173
	    (var) = (tvar))
174
 
175
#define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\
176
	for ((varp) = &SLIST_FIRST((head));				\
177
	    ((var) = *(varp)) != NULL;					\
178
	    (varp) = &SLIST_NEXT((var), field))
179
 
4349 Serge 180
#define	SLIST_INIT(head) do {						\
181
	SLIST_FIRST((head)) = NULL;					\
182
} while (0)
183
 
184
#define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\
185
	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\
186
	SLIST_NEXT((slistelm), field) = (elm);				\
187
} while (0)
188
 
189
#define	SLIST_INSERT_HEAD(head, elm, field) do {			\
190
	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\
191
	SLIST_FIRST((head)) = (elm);					\
192
} while (0)
193
 
194
#define	SLIST_NEXT(elm, field)	((elm)->field.sle_next)
195
 
196
#define	SLIST_REMOVE(head, elm, type, field) do {			\
4921 Serge 197
	QMD_SAVELINK(oldnext, (elm)->field.sle_next);			\
4349 Serge 198
	if (SLIST_FIRST((head)) == (elm)) {				\
199
		SLIST_REMOVE_HEAD((head), field);			\
200
	}								\
201
	else {								\
202
		struct type *curelm = SLIST_FIRST((head));		\
203
		while (SLIST_NEXT(curelm, field) != (elm))		\
204
			curelm = SLIST_NEXT(curelm, field);		\
4921 Serge 205
		SLIST_REMOVE_AFTER(curelm, field);			\
4349 Serge 206
	}								\
4921 Serge 207
	TRASHIT(*oldnext);						\
4349 Serge 208
} while (0)
209
 
4921 Serge 210
#define SLIST_REMOVE_AFTER(elm, field) do {				\
211
	SLIST_NEXT(elm, field) =					\
212
	    SLIST_NEXT(SLIST_NEXT(elm, field), field);			\
213
} while (0)
214
 
4349 Serge 215
#define	SLIST_REMOVE_HEAD(head, field) do {				\
216
	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\
217
} while (0)
218
 
4921 Serge 219
#define SLIST_SWAP(head1, head2, type) do {				\
220
	struct type *swap_first = SLIST_FIRST(head1);			\
221
	SLIST_FIRST(head1) = SLIST_FIRST(head2);			\
222
	SLIST_FIRST(head2) = swap_first;				\
223
} while (0)
224
 
4349 Serge 225
/*
226
 * Singly-linked Tail queue declarations.
227
 */
228
#define	STAILQ_HEAD(name, type)						\
229
struct name {								\
230
	struct type *stqh_first;/* first element */			\
231
	struct type **stqh_last;/* addr of last next element */		\
232
}
233
 
234
#define	STAILQ_HEAD_INITIALIZER(head)					\
235
	{ NULL, &(head).stqh_first }
236
 
237
#define	STAILQ_ENTRY(type)						\
238
struct {								\
239
	struct type *stqe_next;	/* next element */			\
240
}
241
 
242
/*
243
 * Singly-linked Tail queue functions.
244
 */
245
#define	STAILQ_CONCAT(head1, head2) do {				\
246
	if (!STAILQ_EMPTY((head2))) {					\
247
		*(head1)->stqh_last = (head2)->stqh_first;		\
248
		(head1)->stqh_last = (head2)->stqh_last;		\
249
		STAILQ_INIT((head2));					\
250
	}								\
251
} while (0)
252
 
253
#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
254
 
255
#define	STAILQ_FIRST(head)	((head)->stqh_first)
256
 
257
#define	STAILQ_FOREACH(var, head, field)				\
258
	for((var) = STAILQ_FIRST((head));				\
259
	   (var);							\
260
	   (var) = STAILQ_NEXT((var), field))
261
 
4921 Serge 262
 
263
#define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\
264
	for ((var) = STAILQ_FIRST((head));				\
265
	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\
266
	    (var) = (tvar))
267
 
4349 Serge 268
#define	STAILQ_INIT(head) do {						\
269
	STAILQ_FIRST((head)) = NULL;					\
270
	(head)->stqh_last = &STAILQ_FIRST((head));			\
271
} while (0)
272
 
273
#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
274
	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
275
		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
276
	STAILQ_NEXT((tqelm), field) = (elm);				\
277
} while (0)
278
 
279
#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
280
	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
281
		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
282
	STAILQ_FIRST((head)) = (elm);					\
283
} while (0)
284
 
285
#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
286
	STAILQ_NEXT((elm), field) = NULL;				\
287
	*(head)->stqh_last = (elm);					\
288
	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
289
} while (0)
290
 
291
#define	STAILQ_LAST(head, type, field)					\
4921 Serge 292
	(STAILQ_EMPTY((head)) ? NULL :					\
293
	    __containerof((head)->stqh_last, struct type, field.stqe_next))
4349 Serge 294
 
295
#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
296
 
297
#define	STAILQ_REMOVE(head, elm, type, field) do {			\
4921 Serge 298
	QMD_SAVELINK(oldnext, (elm)->field.stqe_next);			\
4349 Serge 299
	if (STAILQ_FIRST((head)) == (elm)) {				\
300
		STAILQ_REMOVE_HEAD((head), field);			\
301
	}								\
302
	else {								\
303
		struct type *curelm = STAILQ_FIRST((head));		\
304
		while (STAILQ_NEXT(curelm, field) != (elm))		\
305
			curelm = STAILQ_NEXT(curelm, field);		\
4921 Serge 306
		STAILQ_REMOVE_AFTER(head, curelm, field);		\
4349 Serge 307
	}								\
4921 Serge 308
	TRASHIT(*oldnext);						\
4349 Serge 309
} while (0)
310
 
4921 Serge 311
#define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
312
	if ((STAILQ_NEXT(elm, field) =					\
313
	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
314
		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
315
} while (0)
316
 
4349 Serge 317
#define	STAILQ_REMOVE_HEAD(head, field) do {				\
318
	if ((STAILQ_FIRST((head)) =					\
319
	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
320
		(head)->stqh_last = &STAILQ_FIRST((head));		\
321
} while (0)
322
 
323
#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
324
	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
325
		(head)->stqh_last = &STAILQ_FIRST((head));		\
326
} while (0)
327
 
4921 Serge 328
#define STAILQ_SWAP(head1, head2, type) do {				\
329
	struct type *swap_first = STAILQ_FIRST(head1);			\
330
	struct type **swap_last = (head1)->stqh_last;			\
331
	STAILQ_FIRST(head1) = STAILQ_FIRST(head2);			\
332
	(head1)->stqh_last = (head2)->stqh_last;			\
333
	STAILQ_FIRST(head2) = swap_first;				\
334
	(head2)->stqh_last = swap_last;					\
335
	if (STAILQ_EMPTY(head1))					\
336
		(head1)->stqh_last = &STAILQ_FIRST(head1);		\
337
	if (STAILQ_EMPTY(head2))					\
338
		(head2)->stqh_last = &STAILQ_FIRST(head2);		\
339
} while (0)
340
 
341
 
4349 Serge 342
/*
343
 * List declarations.
344
 */
345
#define	LIST_HEAD(name, type)						\
346
struct name {								\
347
	struct type *lh_first;	/* first element */			\
348
}
349
 
350
#define	LIST_HEAD_INITIALIZER(head)					\
351
	{ NULL }
352
 
353
#define	LIST_ENTRY(type)						\
354
struct {								\
355
	struct type *le_next;	/* next element */			\
356
	struct type **le_prev;	/* address of previous next element */	\
357
}
358
 
359
/*
360
 * List functions.
361
 */
362
 
4921 Serge 363
#if (defined(_KERNEL) && defined(INVARIANTS))
364
#define	QMD_LIST_CHECK_HEAD(head, field) do {				\
365
	if (LIST_FIRST((head)) != NULL &&				\
366
	    LIST_FIRST((head))->field.le_prev !=			\
367
	     &LIST_FIRST((head)))					\
368
		panic("Bad list head %p first->prev != head", (head));	\
369
} while (0)
370
 
371
#define	QMD_LIST_CHECK_NEXT(elm, field) do {				\
372
	if (LIST_NEXT((elm), field) != NULL &&				\
373
	    LIST_NEXT((elm), field)->field.le_prev !=			\
374
	     &((elm)->field.le_next))					\
375
	     	panic("Bad link elm %p next->prev != elm", (elm));	\
376
} while (0)
377
 
378
#define	QMD_LIST_CHECK_PREV(elm, field) do {				\
379
	if (*(elm)->field.le_prev != (elm))				\
380
		panic("Bad link elm %p prev->next != elm", (elm));	\
381
} while (0)
382
#else
383
#define	QMD_LIST_CHECK_HEAD(head, field)
384
#define	QMD_LIST_CHECK_NEXT(elm, field)
385
#define	QMD_LIST_CHECK_PREV(elm, field)
386
#endif /* (_KERNEL && INVARIANTS) */
387
 
4349 Serge 388
#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
389
 
390
#define	LIST_FIRST(head)	((head)->lh_first)
391
 
392
#define	LIST_FOREACH(var, head, field)					\
393
	for ((var) = LIST_FIRST((head));				\
394
	    (var);							\
395
	    (var) = LIST_NEXT((var), field))
396
 
4921 Serge 397
#define	LIST_FOREACH_SAFE(var, head, field, tvar)			\
398
	for ((var) = LIST_FIRST((head));				\
399
	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\
400
	    (var) = (tvar))
401
 
4349 Serge 402
#define	LIST_INIT(head) do {						\
403
	LIST_FIRST((head)) = NULL;					\
404
} while (0)
405
 
406
#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
4921 Serge 407
	QMD_LIST_CHECK_NEXT(listelm, field);				\
4349 Serge 408
	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
409
		LIST_NEXT((listelm), field)->field.le_prev =		\
410
		    &LIST_NEXT((elm), field);				\
411
	LIST_NEXT((listelm), field) = (elm);				\
412
	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
413
} while (0)
414
 
415
#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
4921 Serge 416
	QMD_LIST_CHECK_PREV(listelm, field);				\
4349 Serge 417
	(elm)->field.le_prev = (listelm)->field.le_prev;		\
418
	LIST_NEXT((elm), field) = (listelm);				\
419
	*(listelm)->field.le_prev = (elm);				\
420
	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
421
} while (0)
422
 
423
#define	LIST_INSERT_HEAD(head, elm, field) do {				\
4921 Serge 424
	QMD_LIST_CHECK_HEAD((head), field);				\
4349 Serge 425
	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
426
		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
427
	LIST_FIRST((head)) = (elm);					\
428
	(elm)->field.le_prev = &LIST_FIRST((head));			\
429
} while (0)
430
 
431
#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
432
 
4921 Serge 433
#define	LIST_PREV(elm, head, type, field)				\
434
	((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL :		\
435
	    __containerof((elm)->field.le_prev, struct type, field.le_next))
436
 
4349 Serge 437
#define	LIST_REMOVE(elm, field) do {					\
4921 Serge 438
	QMD_SAVELINK(oldnext, (elm)->field.le_next);			\
439
	QMD_SAVELINK(oldprev, (elm)->field.le_prev);			\
440
	QMD_LIST_CHECK_NEXT(elm, field);				\
441
	QMD_LIST_CHECK_PREV(elm, field);				\
4349 Serge 442
	if (LIST_NEXT((elm), field) != NULL)				\
443
		LIST_NEXT((elm), field)->field.le_prev = 		\
444
		    (elm)->field.le_prev;				\
445
	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
4921 Serge 446
	TRASHIT(*oldnext);						\
447
	TRASHIT(*oldprev);						\
4349 Serge 448
} while (0)
449
 
4921 Serge 450
#define LIST_SWAP(head1, head2, type, field) do {			\
451
	struct type *swap_tmp = LIST_FIRST((head1));			\
452
	LIST_FIRST((head1)) = LIST_FIRST((head2));			\
453
	LIST_FIRST((head2)) = swap_tmp;					\
454
	if ((swap_tmp = LIST_FIRST((head1))) != NULL)			\
455
		swap_tmp->field.le_prev = &LIST_FIRST((head1));		\
456
	if ((swap_tmp = LIST_FIRST((head2))) != NULL)			\
457
		swap_tmp->field.le_prev = &LIST_FIRST((head2));		\
458
} while (0)
459
 
4349 Serge 460
/*
461
 * Tail queue declarations.
462
 */
463
#define	TAILQ_HEAD(name, type)						\
464
struct name {								\
465
	struct type *tqh_first;	/* first element */			\
466
	struct type **tqh_last;	/* addr of last next element */		\
4921 Serge 467
	TRACEBUF							\
4349 Serge 468
}
469
 
470
#define	TAILQ_HEAD_INITIALIZER(head)					\
4921 Serge 471
	{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
4349 Serge 472
 
473
#define	TAILQ_ENTRY(type)						\
474
struct {								\
475
	struct type *tqe_next;	/* next element */			\
476
	struct type **tqe_prev;	/* address of previous next element */	\
4921 Serge 477
	TRACEBUF							\
4349 Serge 478
}
479
 
480
/*
481
 * Tail queue functions.
482
 */
4921 Serge 483
#if (defined(_KERNEL) && defined(INVARIANTS))
484
#define	QMD_TAILQ_CHECK_HEAD(head, field) do {				\
485
	if (!TAILQ_EMPTY(head) &&					\
486
	    TAILQ_FIRST((head))->field.tqe_prev !=			\
487
	     &TAILQ_FIRST((head)))					\
488
		panic("Bad tailq head %p first->prev != head", (head));	\
489
} while (0)
490
 
491
#define	QMD_TAILQ_CHECK_TAIL(head, field) do {				\
492
	if (*(head)->tqh_last != NULL)					\
493
	    	panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); 	\
494
} while (0)
495
 
496
#define	QMD_TAILQ_CHECK_NEXT(elm, field) do {				\
497
	if (TAILQ_NEXT((elm), field) != NULL &&				\
498
	    TAILQ_NEXT((elm), field)->field.tqe_prev !=			\
499
	     &((elm)->field.tqe_next))					\
500
		panic("Bad link elm %p next->prev != elm", (elm));	\
501
} while (0)
502
 
503
#define	QMD_TAILQ_CHECK_PREV(elm, field) do {				\
504
	if (*(elm)->field.tqe_prev != (elm))				\
505
		panic("Bad link elm %p prev->next != elm", (elm));	\
506
} while (0)
507
#else
508
#define	QMD_TAILQ_CHECK_HEAD(head, field)
509
#define	QMD_TAILQ_CHECK_TAIL(head, headname)
510
#define	QMD_TAILQ_CHECK_NEXT(elm, field)
511
#define	QMD_TAILQ_CHECK_PREV(elm, field)
512
#endif /* (_KERNEL && INVARIANTS) */
513
 
4349 Serge 514
#define	TAILQ_CONCAT(head1, head2, field) do {				\
515
	if (!TAILQ_EMPTY(head2)) {					\
516
		*(head1)->tqh_last = (head2)->tqh_first;		\
517
		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\
518
		(head1)->tqh_last = (head2)->tqh_last;			\
519
		TAILQ_INIT((head2));					\
4921 Serge 520
		QMD_TRACE_HEAD(head1);					\
521
		QMD_TRACE_HEAD(head2);					\
4349 Serge 522
	}								\
523
} while (0)
524
 
525
#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
526
 
527
#define	TAILQ_FIRST(head)	((head)->tqh_first)
528
 
529
#define	TAILQ_FOREACH(var, head, field)					\
530
	for ((var) = TAILQ_FIRST((head));				\
531
	    (var);							\
532
	    (var) = TAILQ_NEXT((var), field))
533
 
4921 Serge 534
#define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\
535
	for ((var) = TAILQ_FIRST((head));				\
536
	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\
537
	    (var) = (tvar))
538
 
4349 Serge 539
#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
540
	for ((var) = TAILQ_LAST((head), headname);			\
541
	    (var);							\
542
	    (var) = TAILQ_PREV((var), headname, field))
543
 
4921 Serge 544
#define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\
545
	for ((var) = TAILQ_LAST((head), headname);			\
546
	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\
547
	    (var) = (tvar))
548
 
4349 Serge 549
#define	TAILQ_INIT(head) do {						\
550
	TAILQ_FIRST((head)) = NULL;					\
551
	(head)->tqh_last = &TAILQ_FIRST((head));			\
4921 Serge 552
	QMD_TRACE_HEAD(head);						\
4349 Serge 553
} while (0)
554
 
555
#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
4921 Serge 556
	QMD_TAILQ_CHECK_NEXT(listelm, field);				\
4349 Serge 557
	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
558
		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
559
		    &TAILQ_NEXT((elm), field);				\
4921 Serge 560
	else {								\
4349 Serge 561
		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
4921 Serge 562
		QMD_TRACE_HEAD(head);					\
563
	}								\
4349 Serge 564
	TAILQ_NEXT((listelm), field) = (elm);				\
565
	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
4921 Serge 566
	QMD_TRACE_ELEM(&(elm)->field);					\
567
	QMD_TRACE_ELEM(&listelm->field);				\
4349 Serge 568
} while (0)
569
 
570
#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
4921 Serge 571
	QMD_TAILQ_CHECK_PREV(listelm, field);				\
4349 Serge 572
	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
573
	TAILQ_NEXT((elm), field) = (listelm);				\
574
	*(listelm)->field.tqe_prev = (elm);				\
575
	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
4921 Serge 576
	QMD_TRACE_ELEM(&(elm)->field);					\
577
	QMD_TRACE_ELEM(&listelm->field);				\
4349 Serge 578
} while (0)
579
 
580
#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
4921 Serge 581
	QMD_TAILQ_CHECK_HEAD(head, field);				\
4349 Serge 582
	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
583
		TAILQ_FIRST((head))->field.tqe_prev =			\
584
		    &TAILQ_NEXT((elm), field);				\
585
	else								\
586
		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
587
	TAILQ_FIRST((head)) = (elm);					\
588
	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
4921 Serge 589
	QMD_TRACE_HEAD(head);						\
590
	QMD_TRACE_ELEM(&(elm)->field);					\
4349 Serge 591
} while (0)
592
 
593
#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
4921 Serge 594
	QMD_TAILQ_CHECK_TAIL(head, field);				\
4349 Serge 595
	TAILQ_NEXT((elm), field) = NULL;				\
596
	(elm)->field.tqe_prev = (head)->tqh_last;			\
597
	*(head)->tqh_last = (elm);					\
598
	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
4921 Serge 599
	QMD_TRACE_HEAD(head);						\
600
	QMD_TRACE_ELEM(&(elm)->field);					\
4349 Serge 601
} while (0)
602
 
603
#define	TAILQ_LAST(head, headname)					\
604
	(*(((struct headname *)((head)->tqh_last))->tqh_last))
605
 
606
#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
607
 
608
#define	TAILQ_PREV(elm, headname, field)				\
609
	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
610
 
611
#define	TAILQ_REMOVE(head, elm, field) do {				\
4921 Serge 612
	QMD_SAVELINK(oldnext, (elm)->field.tqe_next);			\
613
	QMD_SAVELINK(oldprev, (elm)->field.tqe_prev);			\
614
	QMD_TAILQ_CHECK_NEXT(elm, field);				\
615
	QMD_TAILQ_CHECK_PREV(elm, field);				\
4349 Serge 616
	if ((TAILQ_NEXT((elm), field)) != NULL)				\
617
		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
618
		    (elm)->field.tqe_prev;				\
4921 Serge 619
	else {								\
4349 Serge 620
		(head)->tqh_last = (elm)->field.tqe_prev;		\
4921 Serge 621
		QMD_TRACE_HEAD(head);					\
622
	}								\
4349 Serge 623
	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
4921 Serge 624
	TRASHIT(*oldnext);						\
625
	TRASHIT(*oldprev);						\
626
	QMD_TRACE_ELEM(&(elm)->field);					\
4349 Serge 627
} while (0)
628
 
4921 Serge 629
#define TAILQ_SWAP(head1, head2, type, field) do {			\
630
	struct type *swap_first = (head1)->tqh_first;			\
631
	struct type **swap_last = (head1)->tqh_last;			\
632
	(head1)->tqh_first = (head2)->tqh_first;			\
633
	(head1)->tqh_last = (head2)->tqh_last;				\
634
	(head2)->tqh_first = swap_first;				\
635
	(head2)->tqh_last = swap_last;					\
636
	if ((swap_first = (head1)->tqh_first) != NULL)			\
637
		swap_first->field.tqe_prev = &(head1)->tqh_first;	\
638
	else								\
639
		(head1)->tqh_last = &(head1)->tqh_first;		\
640
	if ((swap_first = (head2)->tqh_first) != NULL)			\
641
		swap_first->field.tqe_prev = &(head2)->tqh_first;	\
642
	else								\
643
		(head2)->tqh_last = &(head2)->tqh_first;		\
644
} while (0)
4349 Serge 645
 
646
#ifdef _KERNEL
647
 
648
/*
649
 * XXX insque() and remque() are an old way of handling certain queues.
650
 * They bogusly assumes that all queue heads look alike.
651
 */
652
 
653
struct quehead {
654
	struct quehead *qh_link;
655
	struct quehead *qh_rlink;
656
};
657
 
658
#ifdef	__GNUC__
659
 
660
static __inline void
661
insque(void *a, void *b)
662
{
663
	struct quehead *element = (struct quehead *)a,
664
		 *head = (struct quehead *)b;
665
 
666
	element->qh_link = head->qh_link;
667
	element->qh_rlink = head;
668
	head->qh_link = element;
669
	element->qh_link->qh_rlink = element;
670
}
671
 
672
static __inline void
673
remque(void *a)
674
{
675
	struct quehead *element = (struct quehead *)a;
676
 
677
	element->qh_link->qh_rlink = element->qh_rlink;
678
	element->qh_rlink->qh_link = element->qh_link;
679
	element->qh_rlink = 0;
680
}
681
 
682
#else /* !__GNUC__ */
683
 
684
void	insque(void *a, void *b);
685
void	remque(void *a);
686
 
687
#endif /* __GNUC__ */
688
 
689
#endif /* _KERNEL */
690
 
691
#endif /* !_SYS_QUEUE_H_ */