xref: /freebsd/share/man/man3/queue.3 (revision 7a7741af18d6c8a804cc643cb7ecda9d730c6aa6)
1.\" Copyright (c) 1993
2.\"	The Regents of the University of California.  All rights reserved.
3.\"
4.\" Redistribution and use in source and binary forms, with or without
5.\" modification, are permitted provided that the following conditions
6.\" are met:
7.\" 1. Redistributions of source code must retain the above copyright
8.\"    notice, this list of conditions and the following disclaimer.
9.\" 2. Redistributions in binary form must reproduce the above copyright
10.\"    notice, this list of conditions and the following disclaimer in the
11.\"    documentation and/or other materials provided with the distribution.
12.\" 3. Neither the name of the University nor the names of its contributors
13.\"    may be used to endorse or promote products derived from this software
14.\"    without specific prior written permission.
15.\"
16.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
17.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
20.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26.\" SUCH DAMAGE.
27.\"
28.Dd April 8, 2024
29.Dt QUEUE 3
30.Os
31.Sh NAME
32.Nm SLIST_CLASS_ENTRY ,
33.Nm SLIST_CLASS_HEAD ,
34.Nm SLIST_CONCAT ,
35.Nm SLIST_EMPTY ,
36.Nm SLIST_ENTRY ,
37.Nm SLIST_FIRST ,
38.Nm SLIST_FOREACH ,
39.Nm SLIST_FOREACH_FROM ,
40.Nm SLIST_FOREACH_FROM_SAFE ,
41.Nm SLIST_FOREACH_SAFE ,
42.Nm SLIST_HEAD ,
43.Nm SLIST_HEAD_INITIALIZER ,
44.Nm SLIST_INIT ,
45.Nm SLIST_INSERT_AFTER ,
46.Nm SLIST_INSERT_HEAD ,
47.Nm SLIST_NEXT ,
48.Nm SLIST_REMOVE ,
49.Nm SLIST_REMOVE_AFTER ,
50.Nm SLIST_REMOVE_HEAD ,
51.Nm SLIST_SWAP ,
52.Nm STAILQ_CLASS_ENTRY ,
53.Nm STAILQ_CLASS_HEAD ,
54.Nm STAILQ_CONCAT ,
55.Nm STAILQ_EMPTY ,
56.Nm STAILQ_ENTRY ,
57.Nm STAILQ_FIRST ,
58.Nm STAILQ_FOREACH ,
59.Nm STAILQ_FOREACH_FROM ,
60.Nm STAILQ_FOREACH_FROM_SAFE ,
61.Nm STAILQ_FOREACH_SAFE ,
62.Nm STAILQ_HEAD ,
63.Nm STAILQ_HEAD_INITIALIZER ,
64.Nm STAILQ_INIT ,
65.Nm STAILQ_INSERT_AFTER ,
66.Nm STAILQ_INSERT_HEAD ,
67.Nm STAILQ_INSERT_TAIL ,
68.Nm STAILQ_LAST ,
69.Nm STAILQ_NEXT ,
70.Nm STAILQ_REMOVE ,
71.Nm STAILQ_REMOVE_AFTER ,
72.Nm STAILQ_REMOVE_HEAD ,
73.Nm STAILQ_SWAP ,
74.Nm LIST_CLASS_ENTRY ,
75.Nm LIST_CLASS_HEAD ,
76.Nm LIST_CONCAT ,
77.Nm LIST_EMPTY ,
78.Nm LIST_ENTRY ,
79.Nm LIST_FIRST ,
80.Nm LIST_FOREACH ,
81.Nm LIST_FOREACH_FROM ,
82.Nm LIST_FOREACH_FROM_SAFE ,
83.Nm LIST_FOREACH_SAFE ,
84.Nm LIST_HEAD ,
85.Nm LIST_HEAD_INITIALIZER ,
86.Nm LIST_INIT ,
87.Nm LIST_INSERT_AFTER ,
88.Nm LIST_INSERT_BEFORE ,
89.Nm LIST_INSERT_HEAD ,
90.Nm LIST_NEXT ,
91.Nm LIST_PREV ,
92.Nm LIST_REMOVE ,
93.Nm LIST_REPLACE ,
94.Nm LIST_SWAP ,
95.Nm TAILQ_CLASS_ENTRY ,
96.Nm TAILQ_CLASS_HEAD ,
97.Nm TAILQ_CONCAT ,
98.Nm TAILQ_EMPTY ,
99.Nm TAILQ_ENTRY ,
100.Nm TAILQ_FIRST ,
101.Nm TAILQ_FOREACH ,
102.Nm TAILQ_FOREACH_FROM ,
103.Nm TAILQ_FOREACH_FROM_SAFE ,
104.Nm TAILQ_FOREACH_REVERSE ,
105.Nm TAILQ_FOREACH_REVERSE_FROM ,
106.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE ,
107.Nm TAILQ_FOREACH_REVERSE_SAFE ,
108.Nm TAILQ_FOREACH_SAFE ,
109.Nm TAILQ_HEAD ,
110.Nm TAILQ_HEAD_INITIALIZER ,
111.Nm TAILQ_INIT ,
112.Nm TAILQ_INSERT_AFTER ,
113.Nm TAILQ_INSERT_BEFORE ,
114.Nm TAILQ_INSERT_HEAD ,
115.Nm TAILQ_INSERT_TAIL ,
116.Nm TAILQ_LAST ,
117.Nm TAILQ_NEXT ,
118.Nm TAILQ_PREV ,
119.Nm TAILQ_REMOVE ,
120.Nm TAILQ_REPLACE ,
121.Nm TAILQ_SWAP
122.Nd implementations of singly-linked lists, singly-linked tail queues,
123lists and tail queues
124.Sh SYNOPSIS
125.In sys/queue.h
126.\"
127.Fn SLIST_CLASS_ENTRY "CLASSTYPE"
128.Fn SLIST_CLASS_HEAD "HEADNAME" "CLASSTYPE"
129.Fn SLIST_CONCAT "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE" "SLIST_ENTRY NAME"
130.Fn SLIST_EMPTY "SLIST_HEAD *head"
131.Fn SLIST_ENTRY "TYPE"
132.Fn SLIST_FIRST "SLIST_HEAD *head"
133.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
134.Fn SLIST_FOREACH_FROM "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
135.Fn SLIST_FOREACH_FROM_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
136.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME" "TYPE *temp_var"
137.Fn SLIST_HEAD "HEADNAME" "TYPE"
138.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
139.Fn SLIST_INIT "SLIST_HEAD *head"
140.Fn SLIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "SLIST_ENTRY NAME"
141.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
142.Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME"
143.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME"
144.Fn SLIST_REMOVE_AFTER "TYPE *elm" "SLIST_ENTRY NAME"
145.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME"
146.Fn SLIST_SWAP "SLIST_HEAD *head1" "SLIST_HEAD *head2" "TYPE"
147.\"
148.Fn STAILQ_CLASS_ENTRY "CLASSTYPE"
149.Fn STAILQ_CLASS_HEAD "HEADNAME" "CLASSTYPE"
150.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
151.Fn STAILQ_EMPTY "STAILQ_HEAD *head"
152.Fn STAILQ_ENTRY "TYPE"
153.Fn STAILQ_FIRST "STAILQ_HEAD *head"
154.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
155.Fn STAILQ_FOREACH_FROM "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
156.Fn STAILQ_FOREACH_FROM_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
157.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME" "TYPE *temp_var"
158.Fn STAILQ_HEAD "HEADNAME" "TYPE"
159.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
160.Fn STAILQ_INIT "STAILQ_HEAD *head"
161.Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "STAILQ_ENTRY NAME"
162.Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
163.Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
164.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
165.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
166.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
167.Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
168.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
169.Fn STAILQ_SWAP "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" "TYPE"
170.\"
171.Fn LIST_CLASS_ENTRY "CLASSTYPE"
172.Fn LIST_CLASS_HEAD "HEADNAME" "CLASSTYPE"
173.Fn LIST_CONCAT "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
174.Fn LIST_EMPTY "LIST_HEAD *head"
175.Fn LIST_ENTRY "TYPE"
176.Fn LIST_FIRST "LIST_HEAD *head"
177.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
178.Fn LIST_FOREACH_FROM "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
179.Fn LIST_FOREACH_FROM_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
180.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE *temp_var"
181.Fn LIST_HEAD "HEADNAME" "TYPE"
182.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
183.Fn LIST_INIT "LIST_HEAD *head"
184.Fn LIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
185.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
186.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
187.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
188.Fn LIST_PREV "TYPE *elm" "LIST_HEAD *head" "TYPE" "LIST_ENTRY NAME"
189.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
190.Fn LIST_REPLACE "TYPE *elm" "TYPE *new" "LIST_ENTRY NAME"
191.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
192.\"
193.Fn TAILQ_CLASS_ENTRY "CLASSTYPE"
194.Fn TAILQ_CLASS_HEAD "HEADNAME" "CLASSTYPE"
195.Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME"
196.Fn TAILQ_EMPTY "TAILQ_HEAD *head"
197.Fn TAILQ_ENTRY "TYPE"
198.Fn TAILQ_FIRST "TAILQ_HEAD *head"
199.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
200.Fn TAILQ_FOREACH_FROM "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
201.Fn TAILQ_FOREACH_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
202.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
203.Fn TAILQ_FOREACH_REVERSE_FROM "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME"
204.Fn TAILQ_FOREACH_REVERSE_FROM_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
205.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME" "TAILQ_ENTRY NAME" "TYPE *temp_var"
206.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME" "TYPE *temp_var"
207.Fn TAILQ_HEAD "HEADNAME" "TYPE"
208.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
209.Fn TAILQ_INIT "TAILQ_HEAD *head"
210.Fn TAILQ_INSERT_AFTER "TAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
211.Fn TAILQ_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
212.Fn TAILQ_INSERT_HEAD "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
213.Fn TAILQ_INSERT_TAIL "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
214.Fn TAILQ_LAST "TAILQ_HEAD *head" "HEADNAME"
215.Fn TAILQ_NEXT "TYPE *elm" "TAILQ_ENTRY NAME"
216.Fn TAILQ_PREV "TYPE *elm" "HEADNAME" "TAILQ_ENTRY NAME"
217.Fn TAILQ_REMOVE "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
218.Fn TAILQ_REPLACE "TAILQ_HEAD *head" "TYPE *elm" "TYPE *new" "TAILQ_ENTRY NAME"
219.Fn TAILQ_SWAP "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TYPE" "TAILQ_ENTRY NAME"
220.\"
221.Sh DESCRIPTION
222These macros define and operate on four types of data structures which
223can be used in both C and C++ source code:
224.Bl -enum -compact -offset indent
225.It
226Lists
227.It
228Singly-linked lists
229.It
230Singly-linked tail queues
231.It
232Tail queues
233.El
234All four structures support the following functionality:
235.Bl -enum -compact -offset indent
236.It
237Insertion of a new entry at the head of the list.
238.It
239Insertion of a new entry after any element in the list.
240.It
241O(1) removal of an entry from the head of the list.
242.It
243Forward traversal through the list.
244.It
245Swapping the contents of two lists.
246.El
247.Pp
248Singly-linked lists are the simplest of the four data structures
249and support only the above functionality.
250Singly-linked lists are ideal for applications with large datasets
251and few or no removals,
252or for implementing a LIFO queue.
253Singly-linked lists add the following functionality:
254.Bl -enum -compact -offset indent
255.It
256O(n) removal of any entry in the list.
257.It
258O(n) concatenation of two lists.
259.El
260.Pp
261Singly-linked tail queues add the following functionality:
262.Bl -enum -compact -offset indent
263.It
264Entries can be added at the end of a list.
265.It
266O(n) removal of any entry in the list.
267.It
268They may be concatenated.
269.El
270However:
271.Bl -enum -compact -offset indent
272.It
273All list insertions must specify the head of the list.
274.It
275Each head entry requires two pointers rather than one.
276.It
277Code size is about 15% greater and operations run about 20% slower
278than singly-linked lists.
279.El
280.Pp
281Singly-linked tail queues are ideal for applications with large datasets and
282few or no removals,
283or for implementing a FIFO queue.
284.Pp
285All doubly linked types of data structures (lists and tail queues)
286additionally allow:
287.Bl -enum -compact -offset indent
288.It
289Insertion of a new entry before any element in the list.
290.It
291O(1) removal of any entry in the list.
292.El
293However:
294.Bl -enum -compact -offset indent
295.It
296Each element requires two pointers rather than one.
297.It
298Code size and execution time of operations (except for removal) is about
299twice that of the singly-linked data-structures.
300.El
301.Pp
302Linked lists are the simplest of the doubly linked data structures.
303They add the following functionality over the above:
304.Bl -enum -compact -offset indent
305.It
306O(n) concatenation of two lists.
307.It
308They may be traversed backwards.
309.El
310However:
311.Bl -enum -compact -offset indent
312.It
313To traverse backwards, an entry to begin the traversal and the list in
314which it is contained must be specified.
315.El
316.Pp
317Tail queues add the following functionality:
318.Bl -enum -compact -offset indent
319.It
320Entries can be added at the end of a list.
321.It
322They may be traversed backwards, from tail to head.
323.It
324They may be concatenated.
325.El
326However:
327.Bl -enum -compact -offset indent
328.It
329All list insertions and removals must specify the head of the list.
330.It
331Each head entry requires two pointers rather than one.
332.It
333Code size is about 15% greater and operations run about 20% slower
334than singly-linked lists.
335.El
336.Pp
337In the macro definitions,
338.Fa TYPE
339is the name of a user defined structure.
340The structure must contain a field called
341.Fa NAME
342which is of type
343.Li SLIST_ENTRY ,
344.Li STAILQ_ENTRY ,
345.Li LIST_ENTRY ,
346or
347.Li TAILQ_ENTRY .
348In the macro definitions,
349.Fa CLASSTYPE
350is the name of a user defined class.
351The class must contain a field called
352.Fa NAME
353which is of type
354.Li SLIST_CLASS_ENTRY ,
355.Li STAILQ_CLASS_ENTRY ,
356.Li LIST_CLASS_ENTRY ,
357or
358.Li TAILQ_CLASS_ENTRY .
359The argument
360.Fa HEADNAME
361is the name of a user defined structure that must be declared
362using the macros
363.Li SLIST_HEAD ,
364.Li SLIST_CLASS_HEAD ,
365.Li STAILQ_HEAD ,
366.Li STAILQ_CLASS_HEAD ,
367.Li LIST_HEAD ,
368.Li LIST_CLASS_HEAD ,
369.Li TAILQ_HEAD ,
370or
371.Li TAILQ_CLASS_HEAD .
372See the examples below for further explanation of how these
373macros are used.
374.Sh SINGLY-LINKED LISTS
375A singly-linked list is headed by a structure defined by the
376.Nm SLIST_HEAD
377macro.
378This structure contains a single pointer to the first element
379on the list.
380The elements are singly linked for minimum space and pointer manipulation
381overhead at the expense of O(n) removal for arbitrary elements.
382New elements can be added to the list after an existing element or
383at the head of the list.
384An
385.Fa SLIST_HEAD
386structure is declared as follows:
387.Bd -literal -offset indent
388SLIST_HEAD(HEADNAME, TYPE) head;
389.Ed
390.Pp
391where
392.Fa HEADNAME
393is the name of the structure to be defined, and
394.Fa TYPE
395is the type of the elements to be linked into the list.
396A pointer to the head of the list can later be declared as:
397.Bd -literal -offset indent
398struct HEADNAME *headp;
399.Ed
400.Pp
401(The names
402.Li head
403and
404.Li headp
405are user selectable.)
406.Pp
407The macro
408.Nm SLIST_HEAD_INITIALIZER
409evaluates to an initializer for the list
410.Fa head .
411.Pp
412The macro
413.Nm SLIST_CONCAT
414concatenates the list headed by
415.Fa head2
416onto the end of the one headed by
417.Fa head1
418removing all entries from the former.
419Use of this macro should be avoided as it traverses the entirety of the
420.Fa head1
421list.
422A singly-linked tail queue should be used if this macro is needed in
423high-usage code paths or to operate on long lists.
424.Pp
425The macro
426.Nm SLIST_EMPTY
427evaluates to true if there are no elements in the list.
428.Pp
429The macro
430.Nm SLIST_ENTRY
431declares a structure that connects the elements in
432the list.
433.Pp
434The macro
435.Nm SLIST_FIRST
436returns the first element in the list or NULL if the list is empty.
437.Pp
438The macro
439.Nm SLIST_FOREACH
440traverses the list referenced by
441.Fa head
442in the forward direction, assigning each element in
443turn to
444.Fa var .
445.Pp
446The macro
447.Nm SLIST_FOREACH_FROM
448behaves identically to
449.Nm SLIST_FOREACH
450when
451.Fa var
452is NULL, else it treats
453.Fa var
454as a previously found SLIST element and begins the loop at
455.Fa var
456instead of the first element in the SLIST referenced by
457.Fa head .
458.Pp
459The macro
460.Nm SLIST_FOREACH_SAFE
461traverses the list referenced by
462.Fa head
463in the forward direction, assigning each element in
464turn to
465.Fa var .
466However, unlike
467.Fn SLIST_FOREACH
468here it is permitted to both remove
469.Fa var
470as well as free it from within the loop safely without interfering with the
471traversal.
472.Pp
473The macro
474.Nm SLIST_FOREACH_FROM_SAFE
475behaves identically to
476.Nm SLIST_FOREACH_SAFE
477when
478.Fa var
479is NULL, else it treats
480.Fa var
481as a previously found SLIST element and begins the loop at
482.Fa var
483instead of the first element in the SLIST referenced by
484.Fa head .
485.Pp
486The macro
487.Nm SLIST_INIT
488initializes the list referenced by
489.Fa head .
490.Pp
491The macro
492.Nm SLIST_INSERT_HEAD
493inserts the new element
494.Fa elm
495at the head of the list.
496.Pp
497The macro
498.Nm SLIST_INSERT_AFTER
499inserts the new element
500.Fa elm
501after the element
502.Fa listelm .
503.Pp
504The macro
505.Nm SLIST_NEXT
506returns the next element in the list.
507.Pp
508The macro
509.Nm SLIST_REMOVE_AFTER
510removes the element after
511.Fa elm
512from the list.
513Unlike
514.Fa SLIST_REMOVE ,
515this macro does not traverse the entire list.
516.Pp
517The macro
518.Nm SLIST_REMOVE_HEAD
519removes the element
520.Fa elm
521from the head of the list.
522For optimum efficiency,
523elements being removed from the head of the list should explicitly use
524this macro instead of the generic
525.Fa SLIST_REMOVE
526macro.
527.Pp
528The macro
529.Nm SLIST_REMOVE
530removes the element
531.Fa elm
532from the list.
533Use of this macro should be avoided as it traverses the entire list.
534A doubly-linked list should be used if this macro is needed in
535high-usage code paths or to operate on long lists.
536.Pp
537The macro
538.Nm SLIST_SWAP
539swaps the contents of
540.Fa head1
541and
542.Fa head2 .
543.Sh SINGLY-LINKED LIST EXAMPLE
544.Bd -literal
545SLIST_HEAD(slisthead, entry) head =
546    SLIST_HEAD_INITIALIZER(head);
547struct slisthead *headp;		/* Singly-linked List head. */
548struct entry {
549	...
550	SLIST_ENTRY(entry) entries;	/* Singly-linked List. */
551	...
552} *n1, *n2, *n3, *np;
553
554SLIST_INIT(&head);			/* Initialize the list. */
555
556n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
557SLIST_INSERT_HEAD(&head, n1, entries);
558
559n2 = malloc(sizeof(struct entry));	/* Insert after. */
560SLIST_INSERT_AFTER(n1, n2, entries);
561
562SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */
563free(n2);
564
565n3 = SLIST_FIRST(&head);
566SLIST_REMOVE_HEAD(&head, entries);	/* Deletion from the head. */
567free(n3);
568					/* Forward traversal. */
569SLIST_FOREACH(np, &head, entries)
570	np-> ...
571					/* Safe forward traversal. */
572SLIST_FOREACH_SAFE(np, &head, entries, np_temp) {
573	np->do_stuff();
574	...
575	SLIST_REMOVE(&head, np, entry, entries);
576	free(np);
577}
578
579while (!SLIST_EMPTY(&head)) {		/* List Deletion. */
580	n1 = SLIST_FIRST(&head);
581	SLIST_REMOVE_HEAD(&head, entries);
582	free(n1);
583}
584.Ed
585.Sh SINGLY-LINKED TAIL QUEUES
586A singly-linked tail queue is headed by a structure defined by the
587.Nm STAILQ_HEAD
588macro.
589This structure contains a pair of pointers,
590one to the first element in the tail queue and the other to
591the last element in the tail queue.
592The elements are singly linked for minimum space and pointer
593manipulation overhead at the expense of O(n) removal for arbitrary
594elements.
595New elements can be added to the tail queue after an existing element,
596at the head of the tail queue, or at the end of the tail queue.
597A
598.Fa STAILQ_HEAD
599structure is declared as follows:
600.Bd -literal -offset indent
601STAILQ_HEAD(HEADNAME, TYPE) head;
602.Ed
603.Pp
604where
605.Li HEADNAME
606is the name of the structure to be defined, and
607.Li TYPE
608is the type of the elements to be linked into the tail queue.
609A pointer to the head of the tail queue can later be declared as:
610.Bd -literal -offset indent
611struct HEADNAME *headp;
612.Ed
613.Pp
614(The names
615.Li head
616and
617.Li headp
618are user selectable.)
619.Pp
620The macro
621.Nm STAILQ_HEAD_INITIALIZER
622evaluates to an initializer for the tail queue
623.Fa head .
624.Pp
625The macro
626.Nm STAILQ_CONCAT
627concatenates the tail queue headed by
628.Fa head2
629onto the end of the one headed by
630.Fa head1
631removing all entries from the former.
632.Pp
633The macro
634.Nm STAILQ_EMPTY
635evaluates to true if there are no items on the tail queue.
636.Pp
637The macro
638.Nm STAILQ_ENTRY
639declares a structure that connects the elements in
640the tail queue.
641.Pp
642The macro
643.Nm STAILQ_FIRST
644returns the first item on the tail queue or NULL if the tail queue
645is empty.
646.Pp
647The macro
648.Nm STAILQ_FOREACH
649traverses the tail queue referenced by
650.Fa head
651in the forward direction, assigning each element
652in turn to
653.Fa var .
654.Pp
655The macro
656.Nm STAILQ_FOREACH_FROM
657behaves identically to
658.Nm STAILQ_FOREACH
659when
660.Fa var
661is NULL, else it treats
662.Fa var
663as a previously found STAILQ element and begins the loop at
664.Fa var
665instead of the first element in the STAILQ referenced by
666.Fa head .
667.Pp
668The macro
669.Nm STAILQ_FOREACH_SAFE
670traverses the tail queue referenced by
671.Fa head
672in the forward direction, assigning each element
673in turn to
674.Fa var .
675However, unlike
676.Fn STAILQ_FOREACH
677here it is permitted to both remove
678.Fa var
679as well as free it from within the loop safely without interfering with the
680traversal.
681.Pp
682The macro
683.Nm STAILQ_FOREACH_FROM_SAFE
684behaves identically to
685.Nm STAILQ_FOREACH_SAFE
686when
687.Fa var
688is NULL, else it treats
689.Fa var
690as a previously found STAILQ element and begins the loop at
691.Fa var
692instead of the first element in the STAILQ referenced by
693.Fa head .
694.Pp
695The macro
696.Nm STAILQ_INIT
697initializes the tail queue referenced by
698.Fa head .
699.Pp
700The macro
701.Nm STAILQ_INSERT_HEAD
702inserts the new element
703.Fa elm
704at the head of the tail queue.
705.Pp
706The macro
707.Nm STAILQ_INSERT_TAIL
708inserts the new element
709.Fa elm
710at the end of the tail queue.
711.Pp
712The macro
713.Nm STAILQ_INSERT_AFTER
714inserts the new element
715.Fa elm
716after the element
717.Fa listelm .
718.Pp
719The macro
720.Nm STAILQ_LAST
721returns the last item on the tail queue.
722If the tail queue is empty the return value is
723.Dv NULL .
724.Pp
725The macro
726.Nm STAILQ_NEXT
727returns the next item on the tail queue, or NULL this item is the last.
728.Pp
729The macro
730.Nm STAILQ_REMOVE_AFTER
731removes the element after
732.Fa elm
733from the tail queue.
734Unlike
735.Fa STAILQ_REMOVE ,
736this macro does not traverse the entire tail queue.
737.Pp
738The macro
739.Nm STAILQ_REMOVE_HEAD
740removes the element at the head of the tail queue.
741For optimum efficiency,
742elements being removed from the head of the tail queue should
743use this macro explicitly rather than the generic
744.Fa STAILQ_REMOVE
745macro.
746.Pp
747The macro
748.Nm STAILQ_REMOVE
749removes the element
750.Fa elm
751from the tail queue.
752Use of this macro should be avoided as it traverses the entire list.
753A doubly-linked tail queue should be used if this macro is needed in
754high-usage code paths or to operate on long tail queues.
755.Pp
756The macro
757.Nm STAILQ_SWAP
758swaps the contents of
759.Fa head1
760and
761.Fa head2 .
762.Sh SINGLY-LINKED TAIL QUEUE EXAMPLE
763.Bd -literal
764STAILQ_HEAD(stailhead, entry) head =
765    STAILQ_HEAD_INITIALIZER(head);
766struct stailhead *headp;		/* Singly-linked tail queue head. */
767struct entry {
768	...
769	STAILQ_ENTRY(entry) entries;	/* Tail queue. */
770	...
771} *n1, *n2, *n3, *np;
772
773STAILQ_INIT(&head);			/* Initialize the queue. */
774
775n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
776STAILQ_INSERT_HEAD(&head, n1, entries);
777
778n1 = malloc(sizeof(struct entry));	/* Insert at the tail. */
779STAILQ_INSERT_TAIL(&head, n1, entries);
780
781n2 = malloc(sizeof(struct entry));	/* Insert after. */
782STAILQ_INSERT_AFTER(&head, n1, n2, entries);
783					/* Deletion. */
784STAILQ_REMOVE(&head, n2, entry, entries);
785free(n2);
786					/* Deletion from the head. */
787n3 = STAILQ_FIRST(&head);
788STAILQ_REMOVE_HEAD(&head, entries);
789free(n3);
790					/* Forward traversal. */
791STAILQ_FOREACH(np, &head, entries)
792	np-> ...
793					/* Safe forward traversal. */
794STAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
795	np->do_stuff();
796	...
797	STAILQ_REMOVE(&head, np, entry, entries);
798	free(np);
799}
800					/* TailQ Deletion. */
801while (!STAILQ_EMPTY(&head)) {
802	n1 = STAILQ_FIRST(&head);
803	STAILQ_REMOVE_HEAD(&head, entries);
804	free(n1);
805}
806					/* Faster TailQ Deletion. */
807n1 = STAILQ_FIRST(&head);
808while (n1 != NULL) {
809	n2 = STAILQ_NEXT(n1, entries);
810	free(n1);
811	n1 = n2;
812}
813STAILQ_INIT(&head);
814.Ed
815.Sh LISTS
816A list is headed by a structure defined by the
817.Nm LIST_HEAD
818macro.
819This structure contains a single pointer to the first element
820on the list.
821The elements are doubly linked so that an arbitrary element can be
822removed without traversing the list.
823New elements can be added to the list after an existing element,
824before an existing element, or at the head of the list.
825A
826.Fa LIST_HEAD
827structure is declared as follows:
828.Bd -literal -offset indent
829LIST_HEAD(HEADNAME, TYPE) head;
830.Ed
831.Pp
832where
833.Fa HEADNAME
834is the name of the structure to be defined, and
835.Fa TYPE
836is the type of the elements to be linked into the list.
837A pointer to the head of the list can later be declared as:
838.Bd -literal -offset indent
839struct HEADNAME *headp;
840.Ed
841.Pp
842(The names
843.Li head
844and
845.Li headp
846are user selectable.)
847.Pp
848The macro
849.Nm LIST_HEAD_INITIALIZER
850evaluates to an initializer for the list
851.Fa head .
852.Pp
853The macro
854.Nm LIST_CONCAT
855concatenates the list headed by
856.Fa head2
857onto the end of the one headed by
858.Fa head1
859removing all entries from the former.
860Use of this macro should be avoided as it traverses the entirety of the
861.Fa head1
862list.
863A tail queue should be used if this macro is needed in
864high-usage code paths or to operate on long lists.
865.Pp
866The macro
867.Nm LIST_EMPTY
868evaluates to true if there are no elements in the list.
869.Pp
870The macro
871.Nm LIST_ENTRY
872declares a structure that connects the elements in
873the list.
874.Pp
875The macro
876.Nm LIST_FIRST
877returns the first element in the list or NULL if the list
878is empty.
879.Pp
880The macro
881.Nm LIST_FOREACH
882traverses the list referenced by
883.Fa head
884in the forward direction, assigning each element in turn to
885.Fa var .
886.Pp
887The macro
888.Nm LIST_FOREACH_FROM
889behaves identically to
890.Nm LIST_FOREACH
891when
892.Fa var
893is NULL, else it treats
894.Fa var
895as a previously found LIST element and begins the loop at
896.Fa var
897instead of the first element in the LIST referenced by
898.Fa head .
899.Pp
900The macro
901.Nm LIST_FOREACH_SAFE
902traverses the list referenced by
903.Fa head
904in the forward direction, assigning each element in turn to
905.Fa var .
906However, unlike
907.Fn LIST_FOREACH
908here it is permitted to both remove
909.Fa var
910as well as free it from within the loop safely without interfering with the
911traversal.
912.Pp
913The macro
914.Nm LIST_FOREACH_FROM_SAFE
915behaves identically to
916.Nm LIST_FOREACH_SAFE
917when
918.Fa var
919is NULL, else it treats
920.Fa var
921as a previously found LIST element and begins the loop at
922.Fa var
923instead of the first element in the LIST referenced by
924.Fa head .
925.Pp
926The macro
927.Nm LIST_INIT
928initializes the list referenced by
929.Fa head .
930.Pp
931The macro
932.Nm LIST_INSERT_HEAD
933inserts the new element
934.Fa elm
935at the head of the list.
936.Pp
937The macro
938.Nm LIST_INSERT_AFTER
939inserts the new element
940.Fa elm
941after the element
942.Fa listelm .
943.Pp
944The macro
945.Nm LIST_INSERT_BEFORE
946inserts the new element
947.Fa elm
948before the element
949.Fa listelm .
950.Pp
951The macro
952.Nm LIST_NEXT
953returns the next element in the list, or NULL if this is the last.
954.Pp
955The macro
956.Nm LIST_PREV
957returns the previous element in the list, or NULL if this is the first.
958List
959.Fa head
960must contain element
961.Fa elm .
962.Pp
963The macro
964.Nm LIST_REMOVE
965removes the element
966.Fa elm
967from the list.
968.Pp
969The macro
970.Fn LIST_REPLACE
971replaces the element
972.Fa elm
973with
974.Fa new
975in the list.
976The element
977.Fa new
978must not already be on a list.
979.Pp
980The macro
981.Nm LIST_SWAP
982swaps the contents of
983.Fa head1
984and
985.Fa head2 .
986.Sh LIST EXAMPLE
987.Bd -literal
988LIST_HEAD(listhead, entry) head =
989    LIST_HEAD_INITIALIZER(head);
990struct listhead *headp;			/* List head. */
991struct entry {
992	...
993	LIST_ENTRY(entry) entries;	/* List. */
994	...
995} *n1, *n2, *n3, *np, *np_temp;
996
997LIST_INIT(&head);			/* Initialize the list. */
998
999n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
1000LIST_INSERT_HEAD(&head, n1, entries);
1001
1002n2 = malloc(sizeof(struct entry));	/* Insert after. */
1003LIST_INSERT_AFTER(n1, n2, entries);
1004
1005n3 = malloc(sizeof(struct entry));	/* Insert before. */
1006LIST_INSERT_BEFORE(n2, n3, entries);
1007
1008LIST_REMOVE(n2, entries);		/* Deletion. */
1009free(n2);
1010					/* Forward traversal. */
1011LIST_FOREACH(np, &head, entries)
1012	np-> ...
1013
1014					/* Safe forward traversal. */
1015LIST_FOREACH_SAFE(np, &head, entries, np_temp) {
1016	np->do_stuff();
1017	...
1018	LIST_REMOVE(np, entries);
1019	free(np);
1020}
1021
1022while (!LIST_EMPTY(&head)) {		/* List Deletion. */
1023	n1 = LIST_FIRST(&head);
1024	LIST_REMOVE(n1, entries);
1025	free(n1);
1026}
1027
1028n1 = LIST_FIRST(&head);			/* Faster List Deletion. */
1029while (n1 != NULL) {
1030	n2 = LIST_NEXT(n1, entries);
1031	free(n1);
1032	n1 = n2;
1033}
1034LIST_INIT(&head);
1035.Ed
1036.Sh TAIL QUEUES
1037A tail queue is headed by a structure defined by the
1038.Nm TAILQ_HEAD
1039macro.
1040This structure contains a pair of pointers,
1041one to the first element in the tail queue and the other to
1042the last element in the tail queue.
1043The elements are doubly linked so that an arbitrary element can be
1044removed without traversing the tail queue.
1045New elements can be added to the tail queue after an existing element,
1046before an existing element, at the head of the tail queue,
1047or at the end of the tail queue.
1048A
1049.Fa TAILQ_HEAD
1050structure is declared as follows:
1051.Bd -literal -offset indent
1052TAILQ_HEAD(HEADNAME, TYPE) head;
1053.Ed
1054.Pp
1055where
1056.Li HEADNAME
1057is the name of the structure to be defined, and
1058.Li TYPE
1059is the type of the elements to be linked into the tail queue.
1060A pointer to the head of the tail queue can later be declared as:
1061.Bd -literal -offset indent
1062struct HEADNAME *headp;
1063.Ed
1064.Pp
1065(The names
1066.Li head
1067and
1068.Li headp
1069are user selectable.)
1070.Pp
1071The macro
1072.Nm TAILQ_HEAD_INITIALIZER
1073evaluates to an initializer for the tail queue
1074.Fa head .
1075.Pp
1076The macro
1077.Nm TAILQ_CONCAT
1078concatenates the tail queue headed by
1079.Fa head2
1080onto the end of the one headed by
1081.Fa head1
1082removing all entries from the former.
1083.Pp
1084The macro
1085.Nm TAILQ_EMPTY
1086evaluates to true if there are no items on the tail queue.
1087.Pp
1088The macro
1089.Nm TAILQ_ENTRY
1090declares a structure that connects the elements in
1091the tail queue.
1092.Pp
1093The macro
1094.Nm TAILQ_FIRST
1095returns the first item on the tail queue or NULL if the tail queue
1096is empty.
1097.Pp
1098The macro
1099.Nm TAILQ_FOREACH
1100traverses the tail queue referenced by
1101.Fa head
1102in the forward direction, assigning each element in turn to
1103.Fa var .
1104.Fa var
1105is set to
1106.Dv NULL
1107if the loop completes normally, or if there were no elements.
1108.Pp
1109The macro
1110.Nm TAILQ_FOREACH_FROM
1111behaves identically to
1112.Nm TAILQ_FOREACH
1113when
1114.Fa var
1115is NULL, else it treats
1116.Fa var
1117as a previously found TAILQ element and begins the loop at
1118.Fa var
1119instead of the first element in the TAILQ referenced by
1120.Fa head .
1121.Pp
1122The macro
1123.Nm TAILQ_FOREACH_REVERSE
1124traverses the tail queue referenced by
1125.Fa head
1126in the reverse direction, assigning each element in turn to
1127.Fa var .
1128.Pp
1129The macro
1130.Nm TAILQ_FOREACH_REVERSE_FROM
1131behaves identically to
1132.Nm TAILQ_FOREACH_REVERSE
1133when
1134.Fa var
1135is NULL, else it treats
1136.Fa var
1137as a previously found TAILQ element and begins the reverse loop at
1138.Fa var
1139instead of the last element in the TAILQ referenced by
1140.Fa head .
1141.Pp
1142The macros
1143.Nm TAILQ_FOREACH_SAFE
1144and
1145.Nm TAILQ_FOREACH_REVERSE_SAFE
1146traverse the list referenced by
1147.Fa head
1148in the forward or reverse direction respectively,
1149assigning each element in turn to
1150.Fa var .
1151However, unlike their unsafe counterparts,
1152.Nm TAILQ_FOREACH
1153and
1154.Nm TAILQ_FOREACH_REVERSE
1155permit to both remove
1156.Fa var
1157as well as free it from within the loop safely without interfering with the
1158traversal.
1159.Pp
1160The macro
1161.Nm TAILQ_FOREACH_FROM_SAFE
1162behaves identically to
1163.Nm TAILQ_FOREACH_SAFE
1164when
1165.Fa var
1166is NULL, else it treats
1167.Fa var
1168as a previously found TAILQ element and begins the loop at
1169.Fa var
1170instead of the first element in the TAILQ referenced by
1171.Fa head .
1172.Pp
1173The macro
1174.Nm TAILQ_FOREACH_REVERSE_FROM_SAFE
1175behaves identically to
1176.Nm TAILQ_FOREACH_REVERSE_SAFE
1177when
1178.Fa var
1179is NULL, else it treats
1180.Fa var
1181as a previously found TAILQ element and begins the reverse loop at
1182.Fa var
1183instead of the last element in the TAILQ referenced by
1184.Fa head .
1185.Pp
1186The macro
1187.Nm TAILQ_INIT
1188initializes the tail queue referenced by
1189.Fa head .
1190.Pp
1191The macro
1192.Nm TAILQ_INSERT_HEAD
1193inserts the new element
1194.Fa elm
1195at the head of the tail queue.
1196.Pp
1197The macro
1198.Nm TAILQ_INSERT_TAIL
1199inserts the new element
1200.Fa elm
1201at the end of the tail queue.
1202.Pp
1203The macro
1204.Nm TAILQ_INSERT_AFTER
1205inserts the new element
1206.Fa elm
1207after the element
1208.Fa listelm .
1209.Pp
1210The macro
1211.Nm TAILQ_INSERT_BEFORE
1212inserts the new element
1213.Fa elm
1214before the element
1215.Fa listelm .
1216.Pp
1217The macro
1218.Nm TAILQ_LAST
1219returns the last item on the tail queue.
1220If the tail queue is empty the return value is
1221.Dv NULL .
1222.Pp
1223The macro
1224.Nm TAILQ_NEXT
1225returns the next item on the tail queue, or NULL if this item is the last.
1226.Pp
1227The macro
1228.Nm TAILQ_PREV
1229returns the previous item on the tail queue, or NULL if this item
1230is the first.
1231.Pp
1232The macro
1233.Nm TAILQ_REMOVE
1234removes the element
1235.Fa elm
1236from the tail queue.
1237.Pp
1238The macro
1239.Fn TAILQ_REPLACE
1240replaces the element
1241.Fa elm
1242with
1243.Fa new
1244in the tail queue.
1245The element
1246.Fa new
1247must not already be on a list.
1248.Pp
1249The macro
1250.Nm TAILQ_SWAP
1251swaps the contents of
1252.Fa head1
1253and
1254.Fa head2 .
1255.Sh TAIL QUEUE EXAMPLE
1256.Bd -literal
1257TAILQ_HEAD(tailhead, entry) head =
1258    TAILQ_HEAD_INITIALIZER(head);
1259struct tailhead *headp;			/* Tail queue head. */
1260struct entry {
1261	...
1262	TAILQ_ENTRY(entry) entries;	/* Tail queue. */
1263	...
1264} *n1, *n2, *n3, *n4, *np;
1265
1266TAILQ_INIT(&head);			/* Initialize the queue. */
1267
1268n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
1269TAILQ_INSERT_HEAD(&head, n1, entries);
1270
1271n1 = malloc(sizeof(struct entry));	/* Insert at the tail. */
1272TAILQ_INSERT_TAIL(&head, n1, entries);
1273
1274n2 = malloc(sizeof(struct entry));	/* Insert after. */
1275TAILQ_INSERT_AFTER(&head, n1, n2, entries);
1276
1277n3 = malloc(sizeof(struct entry));	/* Insert before. */
1278TAILQ_INSERT_BEFORE(n2, n3, entries);
1279
1280TAILQ_REMOVE(&head, n2, entries);	/* Deletion. */
1281free(n2);
1282
1283n4 = malloc(sizeof(struct entry));	/* Replacement. */
1284TAILQ_REPLACE(&head, n3, n4, entries);
1285free(n3);
1286					/* Forward traversal. */
1287TAILQ_FOREACH(np, &head, entries)
1288	np-> ...
1289					/* Safe forward traversal. */
1290TAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
1291	np->do_stuff();
1292	...
1293	TAILQ_REMOVE(&head, np, entries);
1294	free(np);
1295}
1296					/* Reverse traversal. */
1297TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries)
1298	np-> ...
1299					/* TailQ Deletion. */
1300while (!TAILQ_EMPTY(&head)) {
1301	n1 = TAILQ_FIRST(&head);
1302	TAILQ_REMOVE(&head, n1, entries);
1303	free(n1);
1304}
1305					/* Faster TailQ Deletion. */
1306n1 = TAILQ_FIRST(&head);
1307while (n1 != NULL) {
1308	n2 = TAILQ_NEXT(n1, entries);
1309	free(n1);
1310	n1 = n2;
1311}
1312TAILQ_INIT(&head);
1313.Ed
1314.Sh DIAGNOSTICS
1315When debugging
1316.Nm queue(3) ,
1317it can be useful to trace queue changes.
1318To enable tracing, define the macro
1319.Va QUEUE_MACRO_DEBUG_TRACE
1320at compile time.
1321.Pp
1322It can also be useful to trash pointers that have been unlinked from a queue,
1323to detect use after removal.
1324To enable pointer trashing, define the macro
1325.Va QUEUE_MACRO_DEBUG_TRASH
1326at compile time.
1327The macro
1328.Fn QMD_IS_TRASHED "void *ptr"
1329returns true if
1330.Fa ptr
1331has been trashed by the
1332.Va QUEUE_MACRO_DEBUG_TRASH
1333option.
1334.Pp
1335In the kernel (with
1336.Va INVARIANTS
1337enabled), the
1338.Fn SLIST_REMOVE_PREVPTR
1339macro is available to aid debugging:
1340.Bl -hang -offset indent
1341.It Fn SLIST_REMOVE_PREVPTR "TYPE **prev" "TYPE *elm" "SLIST_ENTRY NAME"
1342.Pp
1343Removes
1344.Fa elm ,
1345which must directly follow the element whose
1346.Va &SLIST_NEXT()
1347is
1348.Fa prev ,
1349from the SLIST.
1350This macro validates that
1351.Fa elm
1352follows
1353.Fa prev
1354in
1355.Va INVARIANTS
1356mode.
1357.El
1358.Sh SEE ALSO
1359.Xr arb 3 ,
1360.Xr tree 3
1361.Sh HISTORY
1362The
1363.Nm queue
1364functions first appeared in
1365.Bx 4.4 .
1366