Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/libarchive/unzip/la_queue.h
39478 views
1
/* SPDX-License-Identifier: BSD-3-Clause
2
*
3
* Copyright (c) 1991, 1993
4
* The Regents of the University of California. All rights reserved.
5
*/
6
7
#ifndef _SYS_QUEUE_H_
8
#define _SYS_QUEUE_H_
9
10
/*
11
* This file defines four types of data structures: singly-linked lists,
12
* singly-linked tail queues, lists and tail queues.
13
*
14
* A singly-linked list is headed by a single forward pointer. The elements
15
* are singly linked for minimum space and pointer manipulation overhead at
16
* the expense of O(n) removal for arbitrary elements. New elements can be
17
* added to the list after an existing element or at the head of the list.
18
* Elements being removed from the head of the list should use the explicit
19
* macro for this purpose for optimum efficiency. A singly-linked list may
20
* only be traversed in the forward direction. Singly-linked lists are ideal
21
* for applications with large datasets and few or no removals or for
22
* implementing a LIFO queue.
23
*
24
* A singly-linked tail queue is headed by a pair of pointers, one to the
25
* head of the list and the other to the tail of the list. The elements are
26
* singly linked for minimum space and pointer manipulation overhead at the
27
* expense of O(n) removal for arbitrary elements. New elements can be added
28
* to the list after an existing element, at the head of the list, or at the
29
* end of the list. Elements being removed from the head of the tail queue
30
* should use the explicit macro for this purpose for optimum efficiency.
31
* A singly-linked tail queue may only be traversed in the forward direction.
32
* Singly-linked tail queues are ideal for applications with large datasets
33
* and few or no removals or for implementing a FIFO queue.
34
*
35
* A list is headed by a single forward pointer (or an array of forward
36
* pointers for a hash table header). The elements are doubly linked
37
* so that an arbitrary element can be removed without a need to
38
* traverse the list. New elements can be added to the list before
39
* or after an existing element or at the head of the list. A list
40
* may be traversed in either direction.
41
*
42
* A tail queue is headed by a pair of pointers, one to the head of the
43
* list and the other to the tail of the list. The elements are doubly
44
* linked so that an arbitrary element can be removed without a need to
45
* traverse the list. New elements can be added to the list before or
46
* after an existing element, at the head of the list, or at the end of
47
* the list. A tail queue may be traversed in either direction.
48
*
49
* For details on the use of these macros, see the queue(3) manual page.
50
*
51
* Below is a summary of implemented functions where:
52
* + means the macro is available
53
* - means the macro is not available
54
* s means the macro is available but is slow (runs in O(n) time)
55
*
56
* SLIST LIST STAILQ TAILQ
57
* _HEAD + + + +
58
* _CLASS_HEAD + + + +
59
* _HEAD_INITIALIZER + + + +
60
* _ENTRY + + + +
61
* _CLASS_ENTRY + + + +
62
* _INIT + + + +
63
* _EMPTY + + + +
64
* _FIRST + + + +
65
* _NEXT + + + +
66
* _PREV - + - +
67
* _LAST - - + +
68
* _LAST_FAST - - - +
69
* _FOREACH + + + +
70
* _FOREACH_FROM + + + +
71
* _FOREACH_SAFE + + + +
72
* _FOREACH_FROM_SAFE + + + +
73
* _FOREACH_REVERSE - - - +
74
* _FOREACH_REVERSE_FROM - - - +
75
* _FOREACH_REVERSE_SAFE - - - +
76
* _FOREACH_REVERSE_FROM_SAFE - - - +
77
* _INSERT_HEAD + + + +
78
* _INSERT_BEFORE - + - +
79
* _INSERT_AFTER + + + +
80
* _INSERT_TAIL - - + +
81
* _CONCAT s s + +
82
* _REMOVE_AFTER + - + -
83
* _REMOVE_HEAD + - + -
84
* _REMOVE s + s +
85
* _SWAP + + + +
86
*/
87
#ifdef QUEUE_MACRO_DEBUG
88
#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH
89
#define QUEUE_MACRO_DEBUG_TRACE
90
#define QUEUE_MACRO_DEBUG_TRASH
91
#endif
92
93
#ifdef QUEUE_MACRO_DEBUG_TRACE
94
/* Store the last 2 places the queue element or head was altered */
95
struct qm_trace {
96
unsigned long lastline;
97
unsigned long prevline;
98
const char *lastfile;
99
const char *prevfile;
100
};
101
102
#define TRACEBUF struct qm_trace trace;
103
#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } ,
104
105
#define QMD_TRACE_HEAD(head) do { \
106
(head)->trace.prevline = (head)->trace.lastline; \
107
(head)->trace.prevfile = (head)->trace.lastfile; \
108
(head)->trace.lastline = __LINE__; \
109
(head)->trace.lastfile = __FILE__; \
110
} while (0)
111
112
#define QMD_TRACE_ELEM(elem) do { \
113
(elem)->trace.prevline = (elem)->trace.lastline; \
114
(elem)->trace.prevfile = (elem)->trace.lastfile; \
115
(elem)->trace.lastline = __LINE__; \
116
(elem)->trace.lastfile = __FILE__; \
117
} while (0)
118
119
#else /* !QUEUE_MACRO_DEBUG_TRACE */
120
#define QMD_TRACE_ELEM(elem)
121
#define QMD_TRACE_HEAD(head)
122
#define TRACEBUF
123
#define TRACEBUF_INITIALIZER
124
#endif /* QUEUE_MACRO_DEBUG_TRACE */
125
126
#ifdef QUEUE_MACRO_DEBUG_TRASH
127
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
128
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
129
#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1)
130
#else /* !QUEUE_MACRO_DEBUG_TRASH */
131
#define QMD_SAVELINK(name, link)
132
#define TRASHIT(x)
133
#define QMD_IS_TRASHED(x) 0
134
#endif /* QUEUE_MACRO_DEBUG_TRASH */
135
136
#ifdef __cplusplus
137
/*
138
* In C++ there can be structure lists and class lists:
139
*/
140
#define QUEUE_TYPEOF(type) type
141
#else
142
#define QUEUE_TYPEOF(type) struct type
143
#endif
144
145
/*
146
* Singly-linked List declarations.
147
*/
148
#define SLIST_HEAD(name, type) \
149
struct name { \
150
struct type *slh_first; /* first element */ \
151
}
152
153
#define SLIST_CLASS_HEAD(name, type) \
154
struct name { \
155
class type *slh_first; /* first element */ \
156
}
157
158
#define SLIST_HEAD_INITIALIZER(head) \
159
{ NULL }
160
161
#define SLIST_ENTRY(type) \
162
struct { \
163
struct type *sle_next; /* next element */ \
164
}
165
166
#define SLIST_CLASS_ENTRY(type) \
167
struct { \
168
class type *sle_next; /* next element */ \
169
}
170
171
/*
172
* Singly-linked List functions.
173
*/
174
#if (defined(_KERNEL) && defined(INVARIANTS))
175
#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \
176
if (*(prevp) != (elm)) \
177
panic("Bad prevptr *(%p) == %p != %p", \
178
(prevp), *(prevp), (elm)); \
179
} while (0)
180
#else
181
#define QMD_SLIST_CHECK_PREVPTR(prevp, elm)
182
#endif
183
184
#define SLIST_CONCAT(head1, head2, type, field) do { \
185
QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \
186
if (curelm == NULL) { \
187
if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \
188
SLIST_INIT(head2); \
189
} else if (SLIST_FIRST(head2) != NULL) { \
190
while (SLIST_NEXT(curelm, field) != NULL) \
191
curelm = SLIST_NEXT(curelm, field); \
192
SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \
193
SLIST_INIT(head2); \
194
} \
195
} while (0)
196
197
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
198
199
#define SLIST_FIRST(head) ((head)->slh_first)
200
201
#define SLIST_FOREACH(var, head, field) \
202
for ((var) = SLIST_FIRST((head)); \
203
(var); \
204
(var) = SLIST_NEXT((var), field))
205
206
#define SLIST_FOREACH_FROM(var, head, field) \
207
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
208
(var); \
209
(var) = SLIST_NEXT((var), field))
210
211
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
212
for ((var) = SLIST_FIRST((head)); \
213
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
214
(var) = (tvar))
215
216
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
217
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
218
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
219
(var) = (tvar))
220
221
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
222
for ((varp) = &SLIST_FIRST((head)); \
223
((var) = *(varp)) != NULL; \
224
(varp) = &SLIST_NEXT((var), field))
225
226
#define SLIST_INIT(head) do { \
227
SLIST_FIRST((head)) = NULL; \
228
} while (0)
229
230
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
231
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
232
SLIST_NEXT((slistelm), field) = (elm); \
233
} while (0)
234
235
#define SLIST_INSERT_HEAD(head, elm, field) do { \
236
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
237
SLIST_FIRST((head)) = (elm); \
238
} while (0)
239
240
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
241
242
#define SLIST_REMOVE(head, elm, type, field) do { \
243
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
244
if (SLIST_FIRST((head)) == (elm)) { \
245
SLIST_REMOVE_HEAD((head), field); \
246
} \
247
else { \
248
QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \
249
while (SLIST_NEXT(curelm, field) != (elm)) \
250
curelm = SLIST_NEXT(curelm, field); \
251
SLIST_REMOVE_AFTER(curelm, field); \
252
} \
253
TRASHIT(*oldnext); \
254
} while (0)
255
256
#define SLIST_REMOVE_AFTER(elm, field) do { \
257
SLIST_NEXT(elm, field) = \
258
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
259
} while (0)
260
261
#define SLIST_REMOVE_HEAD(head, field) do { \
262
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
263
} while (0)
264
265
#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \
266
QMD_SLIST_CHECK_PREVPTR(prevp, elm); \
267
*(prevp) = SLIST_NEXT(elm, field); \
268
TRASHIT((elm)->field.sle_next); \
269
} while (0)
270
271
#define SLIST_SWAP(head1, head2, type) do { \
272
QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \
273
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
274
SLIST_FIRST(head2) = swap_first; \
275
} while (0)
276
277
/*
278
* Singly-linked Tail queue declarations.
279
*/
280
#define STAILQ_HEAD(name, type) \
281
struct name { \
282
struct type *stqh_first;/* first element */ \
283
struct type **stqh_last;/* addr of last next element */ \
284
}
285
286
#define STAILQ_CLASS_HEAD(name, type) \
287
struct name { \
288
class type *stqh_first; /* first element */ \
289
class type **stqh_last; /* addr of last next element */ \
290
}
291
292
#define STAILQ_HEAD_INITIALIZER(head) \
293
{ NULL, &(head).stqh_first }
294
295
#define STAILQ_ENTRY(type) \
296
struct { \
297
struct type *stqe_next; /* next element */ \
298
}
299
300
#define STAILQ_CLASS_ENTRY(type) \
301
struct { \
302
class type *stqe_next; /* next element */ \
303
}
304
305
/*
306
* Singly-linked Tail queue functions.
307
*/
308
#define STAILQ_CONCAT(head1, head2) do { \
309
if (!STAILQ_EMPTY((head2))) { \
310
*(head1)->stqh_last = (head2)->stqh_first; \
311
(head1)->stqh_last = (head2)->stqh_last; \
312
STAILQ_INIT((head2)); \
313
} \
314
} while (0)
315
316
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
317
318
#define STAILQ_FIRST(head) ((head)->stqh_first)
319
320
#define STAILQ_FOREACH(var, head, field) \
321
for((var) = STAILQ_FIRST((head)); \
322
(var); \
323
(var) = STAILQ_NEXT((var), field))
324
325
#define STAILQ_FOREACH_FROM(var, head, field) \
326
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
327
(var); \
328
(var) = STAILQ_NEXT((var), field))
329
330
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
331
for ((var) = STAILQ_FIRST((head)); \
332
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
333
(var) = (tvar))
334
335
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
336
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
337
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
338
(var) = (tvar))
339
340
#define STAILQ_INIT(head) do { \
341
STAILQ_FIRST((head)) = NULL; \
342
(head)->stqh_last = &STAILQ_FIRST((head)); \
343
} while (0)
344
345
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
346
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
347
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
348
STAILQ_NEXT((tqelm), field) = (elm); \
349
} while (0)
350
351
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
352
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
353
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
354
STAILQ_FIRST((head)) = (elm); \
355
} while (0)
356
357
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
358
STAILQ_NEXT((elm), field) = NULL; \
359
*(head)->stqh_last = (elm); \
360
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
361
} while (0)
362
363
#define STAILQ_LAST(head, type, field) \
364
(STAILQ_EMPTY((head)) ? NULL : \
365
__containerof((head)->stqh_last, \
366
QUEUE_TYPEOF(type), field.stqe_next))
367
368
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
369
370
#define STAILQ_REMOVE(head, elm, type, field) do { \
371
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
372
if (STAILQ_FIRST((head)) == (elm)) { \
373
STAILQ_REMOVE_HEAD((head), field); \
374
} \
375
else { \
376
QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \
377
while (STAILQ_NEXT(curelm, field) != (elm)) \
378
curelm = STAILQ_NEXT(curelm, field); \
379
STAILQ_REMOVE_AFTER(head, curelm, field); \
380
} \
381
TRASHIT(*oldnext); \
382
} while (0)
383
384
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
385
if ((STAILQ_NEXT(elm, field) = \
386
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
387
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
388
} while (0)
389
390
#define STAILQ_REMOVE_HEAD(head, field) do { \
391
if ((STAILQ_FIRST((head)) = \
392
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
393
(head)->stqh_last = &STAILQ_FIRST((head)); \
394
} while (0)
395
396
#define STAILQ_SWAP(head1, head2, type) do { \
397
QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \
398
QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \
399
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
400
(head1)->stqh_last = (head2)->stqh_last; \
401
STAILQ_FIRST(head2) = swap_first; \
402
(head2)->stqh_last = swap_last; \
403
if (STAILQ_EMPTY(head1)) \
404
(head1)->stqh_last = &STAILQ_FIRST(head1); \
405
if (STAILQ_EMPTY(head2)) \
406
(head2)->stqh_last = &STAILQ_FIRST(head2); \
407
} while (0)
408
409
410
/*
411
* List declarations.
412
*/
413
#define LIST_HEAD(name, type) \
414
struct name { \
415
struct type *lh_first; /* first element */ \
416
}
417
418
#define LIST_CLASS_HEAD(name, type) \
419
struct name { \
420
class type *lh_first; /* first element */ \
421
}
422
423
#define LIST_HEAD_INITIALIZER(head) \
424
{ NULL }
425
426
#define LIST_ENTRY(type) \
427
struct { \
428
struct type *le_next; /* next element */ \
429
struct type **le_prev; /* address of previous next element */ \
430
}
431
432
#define LIST_CLASS_ENTRY(type) \
433
struct { \
434
class type *le_next; /* next element */ \
435
class type **le_prev; /* address of previous next element */ \
436
}
437
438
/*
439
* List functions.
440
*/
441
442
#if (defined(_KERNEL) && defined(INVARIANTS))
443
/*
444
* QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME)
445
*
446
* If the list is non-empty, validates that the first element of the list
447
* points back at 'head.'
448
*/
449
#define QMD_LIST_CHECK_HEAD(head, field) do { \
450
if (LIST_FIRST((head)) != NULL && \
451
LIST_FIRST((head))->field.le_prev != \
452
&LIST_FIRST((head))) \
453
panic("Bad list head %p first->prev != head", (head)); \
454
} while (0)
455
456
/*
457
* QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME)
458
*
459
* If an element follows 'elm' in the list, validates that the next element
460
* points back at 'elm.'
461
*/
462
#define QMD_LIST_CHECK_NEXT(elm, field) do { \
463
if (LIST_NEXT((elm), field) != NULL && \
464
LIST_NEXT((elm), field)->field.le_prev != \
465
&((elm)->field.le_next)) \
466
panic("Bad link elm %p next->prev != elm", (elm)); \
467
} while (0)
468
469
/*
470
* QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME)
471
*
472
* Validates that the previous element (or head of the list) points to 'elm.'
473
*/
474
#define QMD_LIST_CHECK_PREV(elm, field) do { \
475
if (*(elm)->field.le_prev != (elm)) \
476
panic("Bad link elm %p prev->next != elm", (elm)); \
477
} while (0)
478
#else
479
#define QMD_LIST_CHECK_HEAD(head, field)
480
#define QMD_LIST_CHECK_NEXT(elm, field)
481
#define QMD_LIST_CHECK_PREV(elm, field)
482
#endif /* (_KERNEL && INVARIANTS) */
483
484
#define LIST_CONCAT(head1, head2, type, field) do { \
485
QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \
486
if (curelm == NULL) { \
487
if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \
488
LIST_FIRST(head2)->field.le_prev = \
489
&LIST_FIRST((head1)); \
490
LIST_INIT(head2); \
491
} \
492
} else if (LIST_FIRST(head2) != NULL) { \
493
while (LIST_NEXT(curelm, field) != NULL) \
494
curelm = LIST_NEXT(curelm, field); \
495
LIST_NEXT(curelm, field) = LIST_FIRST(head2); \
496
LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \
497
LIST_INIT(head2); \
498
} \
499
} while (0)
500
501
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
502
503
#define LIST_FIRST(head) ((head)->lh_first)
504
505
#define LIST_FOREACH(var, head, field) \
506
for ((var) = LIST_FIRST((head)); \
507
(var); \
508
(var) = LIST_NEXT((var), field))
509
510
#define LIST_FOREACH_FROM(var, head, field) \
511
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
512
(var); \
513
(var) = LIST_NEXT((var), field))
514
515
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
516
for ((var) = LIST_FIRST((head)); \
517
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
518
(var) = (tvar))
519
520
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
521
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
522
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
523
(var) = (tvar))
524
525
#define LIST_INIT(head) do { \
526
LIST_FIRST((head)) = NULL; \
527
} while (0)
528
529
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
530
QMD_LIST_CHECK_NEXT(listelm, field); \
531
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
532
LIST_NEXT((listelm), field)->field.le_prev = \
533
&LIST_NEXT((elm), field); \
534
LIST_NEXT((listelm), field) = (elm); \
535
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
536
} while (0)
537
538
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
539
QMD_LIST_CHECK_PREV(listelm, field); \
540
(elm)->field.le_prev = (listelm)->field.le_prev; \
541
LIST_NEXT((elm), field) = (listelm); \
542
*(listelm)->field.le_prev = (elm); \
543
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
544
} while (0)
545
546
#define LIST_INSERT_HEAD(head, elm, field) do { \
547
QMD_LIST_CHECK_HEAD((head), field); \
548
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
549
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
550
LIST_FIRST((head)) = (elm); \
551
(elm)->field.le_prev = &LIST_FIRST((head)); \
552
} while (0)
553
554
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
555
556
#define LIST_PREV(elm, head, type, field) \
557
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
558
__containerof((elm)->field.le_prev, \
559
QUEUE_TYPEOF(type), field.le_next))
560
561
#define LIST_REMOVE(elm, field) do { \
562
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
563
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
564
QMD_LIST_CHECK_NEXT(elm, field); \
565
QMD_LIST_CHECK_PREV(elm, field); \
566
if (LIST_NEXT((elm), field) != NULL) \
567
LIST_NEXT((elm), field)->field.le_prev = \
568
(elm)->field.le_prev; \
569
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
570
TRASHIT(*oldnext); \
571
TRASHIT(*oldprev); \
572
} while (0)
573
574
#define LIST_SWAP(head1, head2, type, field) do { \
575
QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \
576
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
577
LIST_FIRST((head2)) = swap_tmp; \
578
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
579
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
580
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
581
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
582
} while (0)
583
584
/*
585
* Tail queue declarations.
586
*/
587
#define TAILQ_HEAD(name, type) \
588
struct name { \
589
struct type *tqh_first; /* first element */ \
590
struct type **tqh_last; /* addr of last next element */ \
591
TRACEBUF \
592
}
593
594
#define TAILQ_CLASS_HEAD(name, type) \
595
struct name { \
596
class type *tqh_first; /* first element */ \
597
class type **tqh_last; /* addr of last next element */ \
598
TRACEBUF \
599
}
600
601
#define TAILQ_HEAD_INITIALIZER(head) \
602
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
603
604
#define TAILQ_ENTRY(type) \
605
struct { \
606
struct type *tqe_next; /* next element */ \
607
struct type **tqe_prev; /* address of previous next element */ \
608
TRACEBUF \
609
}
610
611
#define TAILQ_CLASS_ENTRY(type) \
612
struct { \
613
class type *tqe_next; /* next element */ \
614
class type **tqe_prev; /* address of previous next element */ \
615
TRACEBUF \
616
}
617
618
/*
619
* Tail queue functions.
620
*/
621
#if (defined(_KERNEL) && defined(INVARIANTS))
622
/*
623
* QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
624
*
625
* If the tailq is non-empty, validates that the first element of the tailq
626
* points back at 'head.'
627
*/
628
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
629
if (!TAILQ_EMPTY(head) && \
630
TAILQ_FIRST((head))->field.tqe_prev != \
631
&TAILQ_FIRST((head))) \
632
panic("Bad tailq head %p first->prev != head", (head)); \
633
} while (0)
634
635
/*
636
* QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME)
637
*
638
* Validates that the tail of the tailq is a pointer to pointer to NULL.
639
*/
640
#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
641
if (*(head)->tqh_last != NULL) \
642
panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
643
} while (0)
644
645
/*
646
* QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME)
647
*
648
* If an element follows 'elm' in the tailq, validates that the next element
649
* points back at 'elm.'
650
*/
651
#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
652
if (TAILQ_NEXT((elm), field) != NULL && \
653
TAILQ_NEXT((elm), field)->field.tqe_prev != \
654
&((elm)->field.tqe_next)) \
655
panic("Bad link elm %p next->prev != elm", (elm)); \
656
} while (0)
657
658
/*
659
* QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME)
660
*
661
* Validates that the previous element (or head of the tailq) points to 'elm.'
662
*/
663
#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
664
if (*(elm)->field.tqe_prev != (elm)) \
665
panic("Bad link elm %p prev->next != elm", (elm)); \
666
} while (0)
667
#else
668
#define QMD_TAILQ_CHECK_HEAD(head, field)
669
#define QMD_TAILQ_CHECK_TAIL(head, headname)
670
#define QMD_TAILQ_CHECK_NEXT(elm, field)
671
#define QMD_TAILQ_CHECK_PREV(elm, field)
672
#endif /* (_KERNEL && INVARIANTS) */
673
674
#define TAILQ_CONCAT(head1, head2, field) do { \
675
if (!TAILQ_EMPTY(head2)) { \
676
*(head1)->tqh_last = (head2)->tqh_first; \
677
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
678
(head1)->tqh_last = (head2)->tqh_last; \
679
TAILQ_INIT((head2)); \
680
QMD_TRACE_HEAD(head1); \
681
QMD_TRACE_HEAD(head2); \
682
} \
683
} while (0)
684
685
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
686
687
#define TAILQ_FIRST(head) ((head)->tqh_first)
688
689
#define TAILQ_FOREACH(var, head, field) \
690
for ((var) = TAILQ_FIRST((head)); \
691
(var); \
692
(var) = TAILQ_NEXT((var), field))
693
694
#define TAILQ_FOREACH_FROM(var, head, field) \
695
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
696
(var); \
697
(var) = TAILQ_NEXT((var), field))
698
699
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
700
for ((var) = TAILQ_FIRST((head)); \
701
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
702
(var) = (tvar))
703
704
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
705
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
706
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
707
(var) = (tvar))
708
709
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
710
for ((var) = TAILQ_LAST((head), headname); \
711
(var); \
712
(var) = TAILQ_PREV((var), headname, field))
713
714
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
715
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
716
(var); \
717
(var) = TAILQ_PREV((var), headname, field))
718
719
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
720
for ((var) = TAILQ_LAST((head), headname); \
721
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
722
(var) = (tvar))
723
724
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
725
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
726
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
727
(var) = (tvar))
728
729
#define TAILQ_INIT(head) do { \
730
TAILQ_FIRST((head)) = NULL; \
731
(head)->tqh_last = &TAILQ_FIRST((head)); \
732
QMD_TRACE_HEAD(head); \
733
} while (0)
734
735
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
736
QMD_TAILQ_CHECK_NEXT(listelm, field); \
737
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
738
TAILQ_NEXT((elm), field)->field.tqe_prev = \
739
&TAILQ_NEXT((elm), field); \
740
else { \
741
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
742
QMD_TRACE_HEAD(head); \
743
} \
744
TAILQ_NEXT((listelm), field) = (elm); \
745
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
746
QMD_TRACE_ELEM(&(elm)->field); \
747
QMD_TRACE_ELEM(&(listelm)->field); \
748
} while (0)
749
750
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
751
QMD_TAILQ_CHECK_PREV(listelm, field); \
752
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
753
TAILQ_NEXT((elm), field) = (listelm); \
754
*(listelm)->field.tqe_prev = (elm); \
755
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
756
QMD_TRACE_ELEM(&(elm)->field); \
757
QMD_TRACE_ELEM(&(listelm)->field); \
758
} while (0)
759
760
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
761
QMD_TAILQ_CHECK_HEAD(head, field); \
762
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
763
TAILQ_FIRST((head))->field.tqe_prev = \
764
&TAILQ_NEXT((elm), field); \
765
else \
766
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
767
TAILQ_FIRST((head)) = (elm); \
768
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
769
QMD_TRACE_HEAD(head); \
770
QMD_TRACE_ELEM(&(elm)->field); \
771
} while (0)
772
773
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
774
QMD_TAILQ_CHECK_TAIL(head, field); \
775
TAILQ_NEXT((elm), field) = NULL; \
776
(elm)->field.tqe_prev = (head)->tqh_last; \
777
*(head)->tqh_last = (elm); \
778
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
779
QMD_TRACE_HEAD(head); \
780
QMD_TRACE_ELEM(&(elm)->field); \
781
} while (0)
782
783
#define TAILQ_LAST(head, headname) \
784
(*(((struct headname *)((head)->tqh_last))->tqh_last))
785
786
/*
787
* The FAST function is fast in that it causes no data access other
788
* then the access to the head. The standard LAST function above
789
* will cause a data access of both the element you want and
790
* the previous element. FAST is very useful for instances when
791
* you may want to prefetch the last data element.
792
*/
793
#define TAILQ_LAST_FAST(head, type, field) \
794
(TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next))
795
796
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
797
798
#define TAILQ_PREV(elm, headname, field) \
799
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
800
801
#define TAILQ_PREV_FAST(elm, head, type, field) \
802
((elm)->field.tqe_prev == &(head)->tqh_first ? NULL : \
803
__containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next))
804
805
#define TAILQ_REMOVE(head, elm, field) do { \
806
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
807
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
808
QMD_TAILQ_CHECK_NEXT(elm, field); \
809
QMD_TAILQ_CHECK_PREV(elm, field); \
810
if ((TAILQ_NEXT((elm), field)) != NULL) \
811
TAILQ_NEXT((elm), field)->field.tqe_prev = \
812
(elm)->field.tqe_prev; \
813
else { \
814
(head)->tqh_last = (elm)->field.tqe_prev; \
815
QMD_TRACE_HEAD(head); \
816
} \
817
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
818
TRASHIT(*oldnext); \
819
TRASHIT(*oldprev); \
820
QMD_TRACE_ELEM(&(elm)->field); \
821
} while (0)
822
823
#define TAILQ_SWAP(head1, head2, type, field) do { \
824
QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \
825
QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \
826
(head1)->tqh_first = (head2)->tqh_first; \
827
(head1)->tqh_last = (head2)->tqh_last; \
828
(head2)->tqh_first = swap_first; \
829
(head2)->tqh_last = swap_last; \
830
if ((swap_first = (head1)->tqh_first) != NULL) \
831
swap_first->field.tqe_prev = &(head1)->tqh_first; \
832
else \
833
(head1)->tqh_last = &(head1)->tqh_first; \
834
if ((swap_first = (head2)->tqh_first) != NULL) \
835
swap_first->field.tqe_prev = &(head2)->tqh_first; \
836
else \
837
(head2)->tqh_last = &(head2)->tqh_first; \
838
} while (0)
839
840
#endif /* !_SYS_QUEUE_H_ */
841
842