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