Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/include/sudo_queue.h
1532 views
1
/*
2
* SPDX-License-Identifier: BSD-3-Clause
3
*
4
* Copyright (c) 1991, 1993
5
* The Regents of the University of California. All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
* 3. Neither the name of the University nor the names of its contributors
16
* may be used to endorse or promote products derived from this software
17
* without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
* SUCH DAMAGE.
30
*
31
* @(#)queue.h 8.5 (Berkeley) 8/20/94
32
* $FreeBSD: head/sys/sys/queue.h 251887 2013-06-18 02:57:56Z lstewart $
33
*/
34
35
#ifndef SUDO_QUEUE_H
36
#define SUDO_QUEUE_H
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
68
* may be traversed in either direction.
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
* A headless tail queue lacks a head structure, The first element acts
78
* as a de facto list head. It uses the same entry struct as a regular
79
* tail queue for easy conversion from headless to headful.
80
* It is capable of concatenating queues as well as individual elements.
81
* Traversing in reverse is more expensive due to lack of a list head.
82
* Note: elements must be initialized before use.
83
*
84
* For details on the use of these macros, see the queue(3) manual page.
85
*
86
*
87
* SLIST LIST STAILQ TAILQ
88
* _HEAD + + + +
89
* _HEAD_INITIALIZER + + + +
90
* _ENTRY + + + +
91
* _INIT + + + +
92
* _EMPTY + + + +
93
* _FIRST + + + +
94
* _NEXT + + + +
95
* _PREV - + - +
96
* _LAST - - + +
97
* _FOREACH + + + +
98
* _FOREACH_FROM + + + +
99
* _FOREACH_SAFE + + + +
100
* _FOREACH_FROM_SAFE + + + +
101
* _FOREACH_REVERSE - - - +
102
* _FOREACH_REVERSE_FROM - - - +
103
* _FOREACH_REVERSE_SAFE - - - +
104
* _FOREACH_REVERSE_FROM_SAFE - - - +
105
* _INSERT_HEAD + + + +
106
* _INSERT_BEFORE - + - +
107
* _INSERT_AFTER + + + +
108
* _INSERT_TAIL - - + +
109
* _CONCAT - - + +
110
* _REMOVE_AFTER + - + -
111
* _REMOVE_HEAD + - + -
112
* _REMOVE + + + +
113
* _SWAP + + + +
114
*
115
*/
116
#ifdef QUEUE_MACRO_DEBUG
117
/* Store the last 2 places the queue element or head was altered */
118
struct qm_trace {
119
unsigned long lastline;
120
unsigned long prevline;
121
const char *lastfile;
122
const char *prevfile;
123
};
124
125
#undef TRACEBUF
126
#define TRACEBUF struct qm_trace trace;
127
#undef TRACEBUF_INITIALIZER
128
#define TRACEBUF_INITIALIZER { __FILE__, __LINE__, NULL, 0 } ,
129
#undef TRASHIT
130
#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
131
#undef QMD_SAVELINK
132
#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
133
134
#undef QMD_TRACE_HEAD
135
#define QMD_TRACE_HEAD(head) do { \
136
(head)->trace.prevline = (head)->trace.lastline; \
137
(head)->trace.prevfile = (head)->trace.lastfile; \
138
(head)->trace.lastline = __LINE__; \
139
(head)->trace.lastfile = __FILE__; \
140
} while (0)
141
142
#undef QMD_TRACE_ELEM
143
#define QMD_TRACE_ELEM(elem) do { \
144
(elem)->trace.prevline = (elem)->trace.lastline; \
145
(elem)->trace.prevfile = (elem)->trace.lastfile; \
146
(elem)->trace.lastline = __LINE__; \
147
(elem)->trace.lastfile = __FILE__; \
148
} while (0)
149
150
#else
151
#undef QMD_TRACE_ELEM
152
#define QMD_TRACE_ELEM(elem)
153
#undef QMD_TRACE_HEAD
154
#define QMD_TRACE_HEAD(head)
155
#undef QMD_SAVELINK
156
#define QMD_SAVELINK(name, link)
157
#undef TRACEBUF
158
#define TRACEBUF
159
#undef TRACEBUF_INITIALIZER
160
#define TRACEBUF_INITIALIZER
161
#undef TRASHIT
162
#define TRASHIT(x)
163
#endif /* QUEUE_MACRO_DEBUG */
164
165
/*
166
* XXX - Work around a bug in the llvm static analyzer.
167
* https://bugs.llvm.org//show_bug.cgi?id=18222
168
*/
169
#ifdef __clang_analyzer__
170
# define ANALYZER_ASSERT(x) do { \
171
if (!__builtin_expect(!(x), 0)) \
172
__builtin_trap(); \
173
} while (0)
174
#else
175
# define ANALYZER_ASSERT(x) do {} while (0)
176
#endif /* __clang_analyzer__ */
177
178
/*
179
* Singly-linked List declarations.
180
*/
181
#undef SLIST_HEAD
182
#define SLIST_HEAD(name, type) \
183
struct name { \
184
struct type *slh_first; /* first element */ \
185
}
186
187
#undef SLIST_HEAD_INITIALIZER
188
#define SLIST_HEAD_INITIALIZER(head) \
189
{ NULL }
190
191
#undef SLIST_ENTRY
192
#define SLIST_ENTRY(type) \
193
struct { \
194
struct type *sle_next; /* next element */ \
195
}
196
197
/*
198
* Singly-linked List functions.
199
*/
200
#undef SLIST_EMPTY
201
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
202
203
#undef SLIST_FIRST
204
#define SLIST_FIRST(head) ((head)->slh_first)
205
206
#undef SLIST_FOREACH
207
#define SLIST_FOREACH(var, head, field) \
208
for ((var) = SLIST_FIRST((head)); \
209
(var); \
210
(var) = SLIST_NEXT((var), field))
211
212
#undef SLIST_FOREACH_FROM
213
#define SLIST_FOREACH_FROM(var, head, field) \
214
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
215
(var); \
216
(var) = SLIST_NEXT((var), field))
217
218
#undef SLIST_FOREACH_SAFE
219
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
220
for ((var) = SLIST_FIRST((head)); \
221
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
222
(var) = (tvar))
223
224
#undef SLIST_FOREACH_FROM_SAFE
225
#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
226
for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \
227
(var) && ((tvar) = SLIST_NEXT((var), field), 1); \
228
(var) = (tvar))
229
230
#undef SLIST_FOREACH_PREVPTR
231
#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
232
for ((varp) = &SLIST_FIRST((head)); \
233
((var) = *(varp)) != NULL; \
234
(varp) = &SLIST_NEXT((var), field))
235
236
#undef SLIST_INIT
237
#define SLIST_INIT(head) do { \
238
SLIST_FIRST((head)) = NULL; \
239
} while (0)
240
241
#undef SLIST_INSERT_AFTER
242
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
243
SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
244
SLIST_NEXT((slistelm), field) = (elm); \
245
} while (0)
246
247
#undef SLIST_INSERT_HEAD
248
#define SLIST_INSERT_HEAD(head, elm, field) do { \
249
SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
250
SLIST_FIRST((head)) = (elm); \
251
} while (0)
252
253
#undef SLIST_NEXT
254
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
255
256
#undef SLIST_REMOVE
257
#define SLIST_REMOVE(head, elm, type, field) do { \
258
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
259
if (SLIST_FIRST((head)) == (elm)) { \
260
SLIST_REMOVE_HEAD((head), field); \
261
} \
262
else { \
263
struct type *curelm = SLIST_FIRST((head)); \
264
while (SLIST_NEXT(curelm, field) != (elm)) \
265
curelm = SLIST_NEXT(curelm, field); \
266
SLIST_REMOVE_AFTER(curelm, field); \
267
} \
268
TRASHIT(*oldnext); \
269
} while (0)
270
271
#undef SLIST_REMOVE_AFTER
272
#define SLIST_REMOVE_AFTER(elm, field) do { \
273
SLIST_NEXT(elm, field) = \
274
SLIST_NEXT(SLIST_NEXT(elm, field), field); \
275
} while (0)
276
277
#undef SLIST_REMOVE_HEAD
278
#define SLIST_REMOVE_HEAD(head, field) do { \
279
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
280
} while (0)
281
282
#undef SLIST_SWAP
283
#define SLIST_SWAP(head1, head2, type) do { \
284
struct type *swap_first = SLIST_FIRST(head1); \
285
SLIST_FIRST(head1) = SLIST_FIRST(head2); \
286
SLIST_FIRST(head2) = swap_first; \
287
} while (0)
288
289
/*
290
* Singly-linked Tail queue declarations.
291
*/
292
#undef STAILQ_HEAD
293
#define STAILQ_HEAD(name, type) \
294
struct name { \
295
struct type *stqh_first;/* first element */ \
296
struct type **stqh_last;/* addr of last next element */ \
297
}
298
299
#undef STAILQ_HEAD_INITIALIZER
300
#define STAILQ_HEAD_INITIALIZER(head) \
301
{ NULL, &(head).stqh_first }
302
303
#undef STAILQ_ENTRY
304
#define STAILQ_ENTRY(type) \
305
struct { \
306
struct type *stqe_next; /* next element */ \
307
}
308
309
/*
310
* Singly-linked Tail queue functions.
311
*/
312
#undef STAILQ_CONCAT
313
#define STAILQ_CONCAT(head1, head2) do { \
314
if (!STAILQ_EMPTY((head2))) { \
315
*(head1)->stqh_last = (head2)->stqh_first; \
316
(head1)->stqh_last = (head2)->stqh_last; \
317
STAILQ_INIT((head2)); \
318
} \
319
} while (0)
320
321
#undef STAILQ_EMPTY
322
#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
323
324
#undef STAILQ_FIRST
325
#define STAILQ_FIRST(head) ((head)->stqh_first)
326
327
#undef STAILQ_FOREACH
328
#define STAILQ_FOREACH(var, head, field) \
329
for ((var) = STAILQ_FIRST((head)); \
330
(var); \
331
(var) = STAILQ_NEXT((var), field))
332
333
#undef STAILQ_FOREACH_FROM
334
#define STAILQ_FOREACH_FROM(var, head, field) \
335
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
336
(var); \
337
(var) = STAILQ_NEXT((var), field))
338
339
#undef STAILQ_FOREACH_SAFE
340
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
341
for ((var) = STAILQ_FIRST((head)); \
342
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
343
(var) = (tvar))
344
345
#undef STAILQ_FOREACH_FROM_SAFE
346
#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
347
for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \
348
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
349
(var) = (tvar))
350
351
#undef STAILQ_INIT
352
#define STAILQ_INIT(head) do { \
353
STAILQ_FIRST((head)) = NULL; \
354
(head)->stqh_last = &STAILQ_FIRST((head)); \
355
} while (0)
356
357
#undef STAILQ_INSERT_AFTER
358
#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
359
if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
360
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
361
STAILQ_NEXT((tqelm), field) = (elm); \
362
} while (0)
363
364
#undef STAILQ_INSERT_HEAD
365
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
366
if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
367
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
368
STAILQ_FIRST((head)) = (elm); \
369
} while (0)
370
371
#undef STAILQ_INSERT_TAIL
372
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
373
STAILQ_NEXT((elm), field) = NULL; \
374
*(head)->stqh_last = (elm); \
375
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
376
} while (0)
377
378
#undef STAILQ_LAST
379
#define STAILQ_LAST(head, type, field) \
380
(STAILQ_EMPTY((head)) ? NULL : \
381
__containerof((head)->stqh_last, struct type, field.stqe_next))
382
383
#undef STAILQ_NEXT
384
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
385
386
#undef STAILQ_REMOVE
387
#define STAILQ_REMOVE(head, elm, type, field) do { \
388
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
389
if (STAILQ_FIRST((head)) == (elm)) { \
390
STAILQ_REMOVE_HEAD((head), field); \
391
} \
392
else { \
393
struct type *curelm = STAILQ_FIRST((head)); \
394
while (STAILQ_NEXT(curelm, field) != (elm)) \
395
curelm = STAILQ_NEXT(curelm, field); \
396
STAILQ_REMOVE_AFTER(head, curelm, field); \
397
} \
398
TRASHIT(*oldnext); \
399
} while (0)
400
401
#undef STAILQ_REMOVE_AFTER
402
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
403
if ((STAILQ_NEXT(elm, field) = \
404
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
405
(head)->stqh_last = &STAILQ_NEXT((elm), field); \
406
} while (0)
407
408
#undef STAILQ_REMOVE_HEAD
409
#define STAILQ_REMOVE_HEAD(head, field) do { \
410
if ((STAILQ_FIRST((head)) = \
411
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
412
(head)->stqh_last = &STAILQ_FIRST((head)); \
413
} while (0)
414
415
#undef STAILQ_SWAP
416
#define STAILQ_SWAP(head1, head2, type) do { \
417
struct type *swap_first = STAILQ_FIRST(head1); \
418
struct type **swap_last = (head1)->stqh_last; \
419
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
420
(head1)->stqh_last = (head2)->stqh_last; \
421
STAILQ_FIRST(head2) = swap_first; \
422
(head2)->stqh_last = swap_last; \
423
if (STAILQ_EMPTY(head1)) \
424
(head1)->stqh_last = &STAILQ_FIRST(head1); \
425
if (STAILQ_EMPTY(head2)) \
426
(head2)->stqh_last = &STAILQ_FIRST(head2); \
427
} while (0)
428
429
430
/*
431
* List declarations.
432
*/
433
#undef LIST_HEAD
434
#define LIST_HEAD(name, type) \
435
struct name { \
436
struct type *lh_first; /* first element */ \
437
}
438
439
#undef LIST_HEAD_INITIALIZER
440
#define LIST_HEAD_INITIALIZER(head) \
441
{ NULL }
442
443
#undef LIST_ENTRY
444
#define LIST_ENTRY(type) \
445
struct { \
446
struct type *le_next; /* next element */ \
447
struct type **le_prev; /* address of previous next element */ \
448
}
449
450
/*
451
* List functions.
452
*/
453
#undef LIST_EMPTY
454
#define LIST_EMPTY(head) ((head)->lh_first == NULL)
455
456
#undef LIST_FIRST
457
#define LIST_FIRST(head) ((head)->lh_first)
458
459
#undef LIST_FOREACH
460
#define LIST_FOREACH(var, head, field) \
461
for ((var) = LIST_FIRST((head)); \
462
(var); \
463
(var) = LIST_NEXT((var), field))
464
465
#undef LIST_FOREACH_FROM
466
#define LIST_FOREACH_FROM(var, head, field) \
467
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
468
(var); \
469
(var) = LIST_NEXT((var), field))
470
471
#undef LIST_FOREACH_SAFE
472
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
473
for ((var) = LIST_FIRST((head)); \
474
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
475
(var) = (tvar))
476
477
#undef LIST_FOREACH_FROM_SAFE
478
#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \
479
for ((var) = ((var) ? (var) : LIST_FIRST((head))); \
480
(var) && ((tvar) = LIST_NEXT((var), field), 1); \
481
(var) = (tvar))
482
483
#undef LIST_INIT
484
#define LIST_INIT(head) do { \
485
LIST_FIRST((head)) = NULL; \
486
} while (0)
487
488
#undef LIST_INSERT_AFTER
489
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
490
if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
491
LIST_NEXT((listelm), field)->field.le_prev = \
492
&LIST_NEXT((elm), field); \
493
LIST_NEXT((listelm), field) = (elm); \
494
(elm)->field.le_prev = &LIST_NEXT((listelm), field); \
495
} while (0)
496
497
#undef LIST_INSERT_BEFORE
498
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
499
(elm)->field.le_prev = (listelm)->field.le_prev; \
500
LIST_NEXT((elm), field) = (listelm); \
501
*(listelm)->field.le_prev = (elm); \
502
(listelm)->field.le_prev = &LIST_NEXT((elm), field); \
503
} while (0)
504
505
#undef LIST_INSERT_HEAD
506
#define LIST_INSERT_HEAD(head, elm, field) do { \
507
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
508
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
509
LIST_FIRST((head)) = (elm); \
510
(elm)->field.le_prev = &LIST_FIRST((head)); \
511
} while (0)
512
513
#undef LIST_NEXT
514
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
515
516
#undef LIST_PREV
517
#define LIST_PREV(elm, head, type, field) \
518
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \
519
__containerof((elm)->field.le_prev, struct type, field.le_next))
520
521
#undef LIST_REMOVE
522
#define LIST_REMOVE(elm, field) do { \
523
ANALYZER_ASSERT(elm != NULL); \
524
QMD_SAVELINK(oldnext, (elm)->field.le_next); \
525
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
526
if (LIST_NEXT((elm), field) != NULL) \
527
LIST_NEXT((elm), field)->field.le_prev = \
528
(elm)->field.le_prev; \
529
*(elm)->field.le_prev = LIST_NEXT((elm), field); \
530
TRASHIT(*oldnext); \
531
TRASHIT(*oldprev); \
532
} while (0)
533
534
#undef LIST_SWAP
535
#define LIST_SWAP(head1, head2, type, field) do { \
536
struct type *swap_tmp = LIST_FIRST((head1)); \
537
LIST_FIRST((head1)) = LIST_FIRST((head2)); \
538
LIST_FIRST((head2)) = swap_tmp; \
539
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
540
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
541
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
542
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
543
} while (0)
544
545
/*
546
* Tail queue declarations.
547
*/
548
#undef TAILQ_HEAD
549
#define TAILQ_HEAD(name, type) \
550
struct name { \
551
struct type *tqh_first; /* first element */ \
552
struct type **tqh_last; /* addr of last next element */ \
553
TRACEBUF \
554
}
555
556
#undef TAILQ_HEAD_INITIALIZER
557
#define TAILQ_HEAD_INITIALIZER(head) \
558
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }
559
560
#undef TAILQ_ENTRY
561
#define TAILQ_ENTRY(type) \
562
struct { \
563
struct type *tqe_next; /* next element */ \
564
struct type **tqe_prev; /* address of previous next element */ \
565
TRACEBUF \
566
}
567
568
/*
569
* Tail queue functions.
570
*/
571
#undef TAILQ_CONCAT
572
#define TAILQ_CONCAT(head1, head2, field) do { \
573
if (!TAILQ_EMPTY(head2)) { \
574
*(head1)->tqh_last = (head2)->tqh_first; \
575
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
576
(head1)->tqh_last = (head2)->tqh_last; \
577
TAILQ_INIT((head2)); \
578
QMD_TRACE_HEAD(head1); \
579
QMD_TRACE_HEAD(head2); \
580
} \
581
} while (0)
582
583
#undef TAILQ_EMPTY
584
#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
585
586
#undef TAILQ_FIRST
587
#define TAILQ_FIRST(head) ((head)->tqh_first)
588
589
#undef TAILQ_FOREACH
590
#define TAILQ_FOREACH(var, head, field) \
591
for ((var) = TAILQ_FIRST((head)); \
592
(var); \
593
(var) = TAILQ_NEXT((var), field))
594
595
#undef TAILQ_FOREACH_FROM
596
#define TAILQ_FOREACH_FROM(var, head, field) \
597
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
598
(var); \
599
(var) = TAILQ_NEXT((var), field))
600
601
#undef TAILQ_FOREACH_SAFE
602
#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
603
for ((var) = TAILQ_FIRST((head)); \
604
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
605
(var) = (tvar))
606
607
#undef TAILQ_FOREACH_FROM_SAFE
608
#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \
609
for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \
610
(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
611
(var) = (tvar))
612
613
#undef TAILQ_FOREACH_REVERSE
614
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
615
for ((var) = TAILQ_LAST((head), headname); \
616
(var); \
617
(var) = TAILQ_PREV((var), headname, field))
618
619
#undef TAILQ_FOREACH_REVERSE_FROM
620
#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \
621
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
622
(var); \
623
(var) = TAILQ_PREV((var), headname, field))
624
625
#undef TAILQ_FOREACH_REVERSE_SAFE
626
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
627
for ((var) = TAILQ_LAST((head), headname); \
628
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
629
(var) = (tvar))
630
631
#undef TAILQ_FOREACH_REVERSE_FROM_SAFE
632
#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \
633
for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \
634
(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
635
(var) = (tvar))
636
637
#undef TAILQ_INIT
638
#define TAILQ_INIT(head) do { \
639
TAILQ_FIRST((head)) = NULL; \
640
(head)->tqh_last = &TAILQ_FIRST((head)); \
641
QMD_TRACE_HEAD(head); \
642
} while (0)
643
644
#undef TAILQ_INSERT_AFTER
645
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
646
if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
647
TAILQ_NEXT((elm), field)->field.tqe_prev = \
648
&TAILQ_NEXT((elm), field); \
649
else { \
650
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
651
QMD_TRACE_HEAD(head); \
652
} \
653
TAILQ_NEXT((listelm), field) = (elm); \
654
(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
655
QMD_TRACE_ELEM(&(elm)->field); \
656
QMD_TRACE_ELEM(&listelm->field); \
657
} while (0)
658
659
#undef TAILQ_INSERT_BEFORE
660
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
661
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
662
TAILQ_NEXT((elm), field) = (listelm); \
663
*(listelm)->field.tqe_prev = (elm); \
664
(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
665
QMD_TRACE_ELEM(&(elm)->field); \
666
QMD_TRACE_ELEM(&listelm->field); \
667
} while (0)
668
669
#undef TAILQ_INSERT_HEAD
670
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
671
if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
672
TAILQ_FIRST((head))->field.tqe_prev = \
673
&TAILQ_NEXT((elm), field); \
674
else \
675
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
676
TAILQ_FIRST((head)) = (elm); \
677
(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
678
QMD_TRACE_HEAD(head); \
679
QMD_TRACE_ELEM(&(elm)->field); \
680
} while (0)
681
682
#undef TAILQ_INSERT_TAIL
683
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
684
TAILQ_NEXT((elm), field) = NULL; \
685
(elm)->field.tqe_prev = (head)->tqh_last; \
686
*(head)->tqh_last = (elm); \
687
(head)->tqh_last = &TAILQ_NEXT((elm), field); \
688
QMD_TRACE_HEAD(head); \
689
QMD_TRACE_ELEM(&(elm)->field); \
690
} while (0)
691
692
#undef TAILQ_LAST
693
#define TAILQ_LAST(head, headname) \
694
(*(((struct headname *)((head)->tqh_last))->tqh_last))
695
696
#undef TAILQ_NEXT
697
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
698
699
#undef TAILQ_PREV
700
#define TAILQ_PREV(elm, headname, field) \
701
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
702
703
#undef TAILQ_REMOVE
704
#define TAILQ_REMOVE(head, elm, field) do { \
705
ANALYZER_ASSERT(elm != NULL); \
706
QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
707
QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
708
if ((TAILQ_NEXT((elm), field)) != NULL) \
709
TAILQ_NEXT((elm), field)->field.tqe_prev = \
710
(elm)->field.tqe_prev; \
711
else { \
712
(head)->tqh_last = (elm)->field.tqe_prev; \
713
QMD_TRACE_HEAD(head); \
714
} \
715
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
716
TRASHIT(*oldnext); \
717
TRASHIT(*oldprev); \
718
QMD_TRACE_ELEM(&(elm)->field); \
719
} while (0)
720
721
#undef TAILQ_SWAP
722
#define TAILQ_SWAP(head1, head2, type, field) do { \
723
struct type *swap_first = (head1)->tqh_first; \
724
struct type **swap_last = (head1)->tqh_last; \
725
(head1)->tqh_first = (head2)->tqh_first; \
726
(head1)->tqh_last = (head2)->tqh_last; \
727
(head2)->tqh_first = swap_first; \
728
(head2)->tqh_last = swap_last; \
729
if ((swap_first = (head1)->tqh_first) != NULL) \
730
swap_first->field.tqe_prev = &(head1)->tqh_first; \
731
else \
732
(head1)->tqh_last = &(head1)->tqh_first; \
733
if ((swap_first = (head2)->tqh_first) != NULL) \
734
swap_first->field.tqe_prev = &(head2)->tqh_first; \
735
else \
736
(head2)->tqh_last = &(head2)->tqh_first; \
737
} while (0)
738
739
/*
740
* Headless Tail queue definitions.
741
*/
742
#undef HLTQ_ENTRY
743
#define HLTQ_ENTRY(type) TAILQ_ENTRY(type)
744
745
#undef HLTQ_INIT
746
#define HLTQ_INIT(entry, field) do { \
747
(entry)->field.tqe_next = NULL; \
748
(entry)->field.tqe_prev = &(entry)->field.tqe_next; \
749
} while (0)
750
751
#undef HLTQ_INITIALIZER
752
#define HLTQ_INITIALIZER(entry, field) \
753
{ NULL, &(entry)->field.tqe_next }
754
755
#undef HLTQ_FIRST
756
#define HLTQ_FIRST(elm) (elm)
757
758
#undef HLTQ_END
759
#define HLTQ_END(elm) NULL
760
761
#undef HLTQ_NEXT
762
#define HLTQ_NEXT(elm, field) ((elm)->field.tqe_next)
763
764
#undef HLTQ_LAST
765
#define HLTQ_LAST(elm, type, field) \
766
((elm)->field.tqe_next == NULL ? (elm) : \
767
__containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
768
769
#undef HLTQ_PREV
770
#define HLTQ_PREV(elm, type, field) \
771
(*(elm)->field.tqe_prev == NULL ? NULL : \
772
__containerof((elm)->field.tqe_prev, struct type, field.tqe_next))
773
774
#undef HLTQ_FOREACH
775
#define HLTQ_FOREACH(var, head, field) \
776
for ((var) = HLTQ_FIRST(head); \
777
(var) != HLTQ_END(head); \
778
(var) = HLTQ_NEXT(var, field))
779
780
#undef HLTQ_FOREACH_SAFE
781
#define HLTQ_FOREACH_SAFE(var, head, field, tvar) \
782
for ((var) = HLTQ_FIRST(head); \
783
(var) != HLTQ_END(head) && \
784
((tvar) = HLTQ_NEXT(var, field), 1); \
785
(var) = (tvar))
786
787
#undef HLTQ_FOREACH_REVERSE
788
#define HLTQ_FOREACH_REVERSE(var, head, headname, field) \
789
for ((var) = HLTQ_LAST(head, headname); \
790
(var) != HLTQ_END(head); \
791
(var) = HLTQ_PREV(var, headname, field))
792
793
#undef HLTQ_FOREACH_REVERSE_SAFE
794
#define HLTQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
795
for ((var) = HLTQ_LAST(head, headname); \
796
(var) != HLTQ_END(head) && \
797
((tvar) = HLTQ_PREV(var, headname, field), 1); \
798
(var) = (tvar))
799
800
/* Concatenate queue2 to the end of queue1. */
801
#undef HLTQ_CONCAT
802
#define HLTQ_CONCAT(queue1, queue2, field) do { \
803
(queue2)->field.tqe_prev = (queue1)->field.tqe_prev; \
804
*(queue1)->field.tqe_prev = (queue2); \
805
(queue1)->field.tqe_prev = &(queue2)->field.tqe_next; \
806
} while (0)
807
808
/* Convert a headless tailq to a headful one. */
809
#define HLTQ_TO_TAILQ(head, hl, field) do { \
810
(head)->tqh_first = (hl); \
811
(head)->tqh_last = (hl)->field.tqe_prev; \
812
(hl)->field.tqe_prev = &(head)->tqh_first; \
813
} while (0)
814
815
/* Concatenate a headless tail queue to the end of a regular tail queue. */
816
#define TAILQ_CONCAT_HLTQ(head, hl, field) do { \
817
void *last = (hl)->field.tqe_prev; \
818
(hl)->field.tqe_prev = (head)->tqh_last; \
819
*(head)->tqh_last = (hl); \
820
(head)->tqh_last = last; \
821
} while (0)
822
823
#endif /* !SUDO_QUEUE_H */
824
825