xref: /netbsd-src/share/man/man3/queue.3 (revision a5a68ff5f29de57339ca14f6c671c0a87714f1f8)
1.\"	$NetBSD: queue.3,v 1.7 1997/09/30 16:49:20 christos Exp $
2.\"
3.\" Copyright (c) 1993 The Regents of the University of California.
4.\" All rights reserved.
5.\"
6.\" Redistribution and use in source and binary forms, with or without
7.\" modification, are permitted provided that the following conditions
8.\" are met:
9.\" 1. Redistributions of source code must retain the above copyright
10.\"    notice, this list of conditions and the following disclaimer.
11.\" 2. Redistributions in binary form must reproduce the above copyright
12.\"    notice, this list of conditions and the following disclaimer in the
13.\"    documentation and/or other materials provided with the distribution.
14.\" 3. All advertising materials mentioning features or use of this software
15.\"    must display the following acknowledgement:
16.\"	This product includes software developed by the University of
17.\"	California, Berkeley and its contributors.
18.\" 4. Neither the name of the University nor the names of its contributors
19.\"    may be used to endorse or promote products derived from this software
20.\"    without specific prior written permission.
21.\"
22.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25.\" ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32.\" SUCH DAMAGE.
33.\"
34.\"	@(#)queue.3	8.1 (Berkeley) 12/13/93
35.\"
36.Dd June 30, 1997
37.Dt QUEUE 3
38.Os BSD 4
39.Sh NAME
40.Nm LIST_ENTRY ,
41.Nm LIST_HEAD ,
42.Nm LIST_HEAD_INITIALIZER ,
43.Nm LIST_INIT ,
44.Nm LIST_INSERT_AFTER ,
45.Nm LIST_INSERT_BEFORE ,
46.Nm LIST_INSERT_HEAD ,
47.Nm LIST_REMOVE ,
48.Nm SIMPLEQ_ENTRY ,
49.Nm SIMPLEQ_HEAD ,
50.Nm SIMPLEQ_HEAD_INITIALIZER ,
51.Nm SIMPLEQ_INIT ,
52.Nm SIMPLEQ_INSERT_HEAD ,
53.Nm SIMPLEQ_INSERT_TAIL ,
54.Nm SIMPLEQ_INSERT_AFTER ,
55.Nm SIMPLEQ_REMOVE_HEAD ,
56.Nm TAILQ_ENTRY ,
57.Nm TAILQ_HEAD ,
58.Nm TAILQ_HEAD_INITIALIZER ,
59.Nm TAILQ_INIT ,
60.Nm TAILQ_INSERT_AFTER ,
61.Nm TAILQ_INSERT_BEFORE ,
62.Nm TAILQ_INSERT_HEAD ,
63.Nm TAILQ_INSERT_TAIL ,
64.Nm TAILQ_REMOVE ,
65.Nm CIRCLEQ_ENTRY ,
66.Nm CIRCLEQ_HEAD ,
67.Nm CIRCLEQ_HEAD_INITIALIZER ,
68.Nm CIRCLEQ_INIT ,
69.Nm CIRCLEQ_INSERT_AFTER ,
70.Nm CIRCLEQ_INSERT_BEFORE ,
71.Nm CIRCLEQ_INSERT_HEAD ,
72.Nm CIRCLEQ_INSERT_TAIL ,
73.Nm CIRCLEQ_REMOVE
74.Nd implementations of lists, tail queues, and circular queues
75.Sh SYNOPSIS
76.Fd #include <sys/queue.h>
77.sp
78.Fn LIST_ENTRY "TYPE"
79.Fn LIST_HEAD "HEADNAME" "TYPE"
80.Fn LIST_HEAD_INITIALIZER "head"
81.Fn LIST_INIT "LIST_HEAD *head"
82.Fn LIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
83.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
84.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
85.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
86.sp
87.Fn SIMPLEQ_ENTRY "TYPE"
88.Fn SIMPLEQ_HEAD "HEADNAME" "TYPE"
89.Fn SIMPLEQ_HEAD_INITIALIZER "head"
90.Fn SIMPLEQ_INIT "SIMPLEQ_HEAD *head"
91.Fn SIMPLEQ_INSERT_AFTER "SIMPLEQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "SIMPLEQ_ENTRY NAME"
92.Fn SIMPLEQ_INSERT_HEAD "SIMPLEQ_HEAD *head" "TYPE *elm" "SIMPLEQ_ENTRY NAME"
93.Fn SIMPLEQ_INSERT_TAIL "SIMPLEQ_HEAD *head" "TYPE *elm" "SIMPLEQ_ENTRY NAME"
94.Fn SIMPLEQ_REMOVE_HEAD "SIMPLEQ_HEAD *head" "TYPE *elm" "SIMPLEQ_ENTRY NAME"
95.sp
96.Fn TAILQ_ENTRY "TYPE"
97.Fn TAILQ_HEAD "HEADNAME" "TYPE"
98.Fn TAILQ_HEAD_INITIALIZER "head"
99.Fn TAILQ_INIT "TAILQ_HEAD *head"
100.Fn TAILQ_INSERT_AFTER "TAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
101.Fn TAILQ_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
102.Fn TAILQ_INSERT_HEAD "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
103.Fn TAILQ_INSERT_TAIL "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
104.Fn TAILQ_REMOVE "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
105.sp
106.Fn CIRCLEQ_ENTRY "TYPE"
107.Fn CIRCLEQ_HEAD "HEADNAME" "TYPE"
108.Fn CIRCLEQ_HEAD_INITIALIZER "head"
109.Fn CIRCLEQ_INIT "CIRCLEQ_HEAD *head"
110.Fn CIRCLEQ_INSERT_AFTER "CIRCLEQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "CIRCLEQ_ENTRY NAME"
111.Fn CIRCLEQ_INSERT_BEFORE "CIRCLEQ_HEAD *head" "TYPE *listelm" "TYPE *elm" "CIRCLEQ_ENTRY NAME"
112.Fn CIRCLEQ_INSERT_HEAD "CIRCLEQ_HEAD *head" "TYPE *elm" "CIRCLEQ_ENTRY NAME"
113.Fn CIRCLEQ_INSERT_TAIL "CIRCLEQ_HEAD *head" "TYPE *elm" "CIRCLEQ_ENTRY NAME"
114.Fn CIRCLEQ_REMOVE "CIRCLEQ_HEAD *head" "TYPE *elm" "CIRCLEQ_ENTRY NAME"
115.Sh DESCRIPTION
116These macros define and operate on four types of data structures:
117lists, simple queues, tail queues, and circular queues.
118All four structures support the following functionality:
119.Bl -enum -compact -offset indent
120.It
121Insertion of a new entry at the head of the list.
122.It
123Insertion of a new entry before or after any element in the list.
124.It
125Removal of any entry in the list.
126.It
127Forward traversal through the list.
128.El
129.Pp
130Lists are the simplest of the four data structures and support
131only the above functionality.
132.Pp
133Simple queues add the following functionality:
134.Bl -enum -compact -offset indent
135.It
136Entries can be added at the end of a list.
137.El
138However:
139.Bl -enum -compact -offset indent
140.It
141Entries may not be added before any element in the list.
142.It
143Only the first entry in the list may be removed.
144.It
145All list insertions and removals must specify the head of the list.
146.It
147Each head entry requires two pointers rather than one.
148.El
149.Pp
150Tail queues add the following functionality:
151.Bl -enum -compact -offset indent
152.It
153Entries can be added at the end of a list.
154.El
155However:
156.Bl -enum -compact -offset indent
157.It
158All list insertions and removals, except insertion before another element, must
159specify the head of the list.
160.It
161Each head entry requires two pointers rather than one.
162.It
163Code size is about 15% greater and operations run about 20% slower
164than lists.
165.El
166.Pp
167Circular queues add the following functionality:
168.Bl -enum -compact -offset indent
169.It
170Entries can be added at the end of a list.
171.It
172They may be traversed backwards, from tail to head.
173.El
174However:
175.Bl -enum -compact -offset indent
176.It
177All list insertions and removals must specify the head of the list.
178.It
179Each head entry requires two pointers rather than one.
180.It
181The termination condition for traversal is more complex.
182.It
183Code size is about 40% greater and operations run about 45% slower
184than lists.
185.El
186.Pp
187In the macro definitions,
188.Fa TYPE
189is the name of a user defined structure,
190that must contain a field of type
191.Li LIST_ENTRY ,
192.Li SIMPLEQ_ENTRY ,
193.Li TAILQ_ENTRY ,
194or
195.Li CIRCLEQ_ENTRY ,
196named
197.Fa NAME .
198The argument
199.Fa HEADNAME
200is the name of a user defined structure that must be declared
201using the macros
202.Li LIST_HEAD ,
203.Li SIMPLEQ_HEAD ,
204.Li TAILQ_HEAD ,
205or
206.Li CIRCLEQ_HEAD .
207See the examples below for further explanation of how these
208macros are used.
209.Sh LISTS
210A list is headed by a structure defined by the
211.Nm LIST_HEAD
212macro.
213This structure contains a single pointer to the first element
214on the list.
215The elements are doubly linked so that an arbitrary element can be
216removed without traversing the list.
217New elements can be added to the list after an existing element,
218before an existing element, or at the head of the list.
219A
220.Fa LIST_HEAD
221structure is declared as follows:
222.Bd -literal -offset indent
223LIST_HEAD(HEADNAME, TYPE) head;
224.Ed
225.sp
226where
227.Fa HEADNAME
228is the name of the structure to be defined, and
229.Fa TYPE
230is the type of the elements to be linked into the list.
231A pointer to the head of the list can later be declared as:
232.Bd -literal -offset indent
233struct HEADNAME *headp;
234.Ed
235.sp
236(The names
237.Li head
238and
239.Li headp
240are user selectable.)
241.Pp
242The macro
243.Nm LIST_ENTRY
244declares a structure that connects the elements in
245the list.
246.Pp
247The macro
248.Nm LIST_HEAD_INITIALIZER
249provides a value which can be used to initialize a list head at
250compile time, and is used at the point that the list head
251variable is declared, like:
252.Bd -literal -offset indent
253struct HEADNAME head = LIST_HEAD_INITIALIZER(head);
254.Ed
255.Pp
256The macro
257.Nm LIST_INIT
258initializes the list referenced by
259.Fa head .
260.Pp
261The macro
262.Nm LIST_INSERT_HEAD
263inserts the new element
264.Fa elm
265at the head of the list.
266.Pp
267The macro
268.Nm LIST_INSERT_AFTER
269inserts the new element
270.Fa elm
271after the element
272.Fa listelm .
273.Pp
274The macro
275.Nm LIST_INSERT_BEFORE
276inserts the new element
277.Fa elm
278before the element
279.Fa listelm .
280.Pp
281The macro
282.Nm LIST_REMOVE
283removes the element
284.Fa elm
285from the list.
286.Sh LIST EXAMPLE
287.Bd -literal
288LIST_HEAD(listhead, entry) head;
289struct listhead *headp;		/* List head. */
290struct entry {
291	...
292	LIST_ENTRY(entry) entries;	/* List. */
293	...
294} *n1, *n2, *np;
295
296LIST_INIT(&head);			/* Initialize the list. */
297
298n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
299LIST_INSERT_HEAD(&head, n1, entries);
300
301n2 = malloc(sizeof(struct entry));	/* Insert after. */
302LIST_INSERT_AFTER(n1, n2, entries);
303
304n2 = malloc(sizeof(struct entry));	/* Insert before. */
305LIST_INSERT_BEFORE(n1, n2, entries);
306					/* Forward traversal. */
307for (np = head.lh_first; np != NULL; np = np->entries.le_next)
308	np-> ...
309
310while (head.lh_first != NULL)		/* Delete. */
311	LIST_REMOVE(head.lh_first, entries);
312.Ed
313.Sh SIMPLE QUEUES
314A simple queue is headed by a structure defined by the
315.Nm SIMPLEQ_HEAD
316macro.
317This structure contains a pair of pointers,
318one to the first element in the simple queue and the other to
319the last element in the simple queue.
320The elements are doubly linked so that an arbitrary element can be
321removed without traversing the simple queue.
322New elements can be added to the queue after an existing element,
323before an existing element, at the head of the queue, or at the end
324the queue.
325A
326.Fa SIMPLEQ_HEAD
327structure is declared as follows:
328.Bd -literal -offset indent
329SIMPLEQ_HEAD(HEADNAME, TYPE) head;
330.Ed
331.sp
332where
333.Li HEADNAME
334is the name of the structure to be defined, and
335.Li TYPE
336is the type of the elements to be linked into the simple queue.
337A pointer to the head of the simple queue can later be declared as:
338.Bd -literal -offset indent
339struct HEADNAME *headp;
340.Ed
341.sp
342(The names
343.Li head
344and
345.Li headp
346are user selectable.)
347.Pp
348The macro
349.Nm SIMPLEQ_ENTRY
350declares a structure that connects the elements in
351the simple queue.
352.Pp
353The macro
354.Nm SIMPLEQ_HEAD_INITIALIZER
355provides a value which can be used to initialize a simple queue head at
356compile time, and is used at the point that the simple queue head
357variable is declared, like:
358.Bd -literal -offset indent
359struct HEADNAME head = SIMPLEQ_HEAD_INITIALIZER(head);
360.Ed
361.Pp
362The macro
363.Nm SIMPLEQ_INIT
364initializes the simple queue referenced by
365.Fa head .
366.Pp
367The macro
368.Nm SIMPLEQ_INSERT_HEAD
369inserts the new element
370.Fa elm
371at the head of the simple queue.
372.Pp
373The macro
374.Nm SIMPLEQ_INSERT_TAIL
375inserts the new element
376.Fa elm
377at the end of the simple queue.
378.Pp
379The macro
380.Nm SIMPLEQ_INSERT_AFTER
381inserts the new element
382.Fa elm
383after the element
384.Fa listelm .
385.Pp
386The macro
387.Nm SIMPLEQ_REMOVE_HEAD
388removes the first element from the simple queue.
389.Sh SIMPLE QUEUE EXAMPLE
390.Bd -literal
391SIMPLEQ_HEAD(simplehead, entry) head;
392struct simplehead *headp;		/* Simple queue head. */
393struct entry {
394	...
395	SIMPLEQ_ENTRY(entry) entries;	/* Simple queue. */
396	...
397} *n1, *n2, *np;
398
399SIMPLEQ_INIT(&head);			/* Initialize the queue. */
400
401n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
402SIMPLEQ_INSERT_HEAD(&head, n1, entries);
403
404n1 = malloc(sizeof(struct entry));	/* Insert at the tail. */
405SIMPLEQ_INSERT_TAIL(&head, n1, entries);
406
407n2 = malloc(sizeof(struct entry));	/* Insert after. */
408SIMPLEQ_INSERT_AFTER(&head, n1, n2, entries);
409
410					/* Forward traversal. */
411for (np = head.sqh_first; np != NULL; np = np->entries.sqe_next)
412	np-> ...
413					/* Delete. */
414while (head.sqh_first != NULL)
415	SIMPLEQ_REMOVE_HEAD(&head, head.sqh_first, entries);
416.Ed
417.Sh TAIL QUEUES
418A tail queue is headed by a structure defined by the
419.Nm TAILQ_HEAD
420macro.
421This structure contains a pair of pointers,
422one to the first element in the tail queue and the other to
423the last element in the tail queue.
424The elements are doubly linked so that an arbitrary element can be
425removed without traversing the tail queue.
426New elements can be added to the queue after an existing element,
427before an existing element, at the head of the queue, or at the end
428the queue.
429A
430.Fa TAILQ_HEAD
431structure is declared as follows:
432.Bd -literal -offset indent
433TAILQ_HEAD(HEADNAME, TYPE) head;
434.Ed
435.sp
436where
437.Li HEADNAME
438is the name of the structure to be defined, and
439.Li TYPE
440is the type of the elements to be linked into the tail queue.
441A pointer to the head of the tail queue can later be declared as:
442.Bd -literal -offset indent
443struct HEADNAME *headp;
444.Ed
445.sp
446(The names
447.Li head
448and
449.Li headp
450are user selectable.)
451.Pp
452The macro
453.Nm TAILQ_ENTRY
454declares a structure that connects the elements in
455the tail queue.
456.Pp
457The macro
458.Nm TAILQ_HEAD_INITIALIZER
459provides a value which can be used to initialize a tail queue head at
460compile time, and is used at the point that the tail queue head
461variable is declared, like:
462.Bd -literal -offset indent
463struct HEADNAME head = TAILQ_HEAD_INITIALIZER(head);
464.Ed
465.Pp
466The macro
467.Nm TAILQ_INIT
468initializes the tail queue referenced by
469.Fa head .
470.Pp
471The macro
472.Nm TAILQ_INSERT_HEAD
473inserts the new element
474.Fa elm
475at the head of the tail queue.
476.Pp
477The macro
478.Nm TAILQ_INSERT_TAIL
479inserts the new element
480.Fa elm
481at the end of the tail queue.
482.Pp
483The macro
484.Nm TAILQ_INSERT_AFTER
485inserts the new element
486.Fa elm
487after the element
488.Fa listelm .
489.Pp
490The macro
491.Nm TAILQ_INSERT_BEFORE
492inserts the new element
493.Fa elm
494before the element
495.Fa listelm .
496.Pp
497The macro
498.Nm TAILQ_REMOVE
499removes the element
500.Fa elm
501from the tail queue.
502.Sh TAIL QUEUE EXAMPLE
503.Bd -literal
504TAILQ_HEAD(tailhead, entry) head;
505struct tailhead *headp;		/* Tail queue head. */
506struct entry {
507	...
508	TAILQ_ENTRY(entry) entries;	/* Tail queue. */
509	...
510} *n1, *n2, *np;
511
512TAILQ_INIT(&head);			/* Initialize the queue. */
513
514n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
515TAILQ_INSERT_HEAD(&head, n1, entries);
516
517n1 = malloc(sizeof(struct entry));	/* Insert at the tail. */
518TAILQ_INSERT_TAIL(&head, n1, entries);
519
520n2 = malloc(sizeof(struct entry));	/* Insert after. */
521TAILQ_INSERT_AFTER(&head, n1, n2, entries);
522
523n2 = malloc(sizeof(struct entry));	/* Insert before. */
524TAILQ_INSERT_BEFORE(n1, n2, entries);
525					/* Forward traversal. */
526for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next)
527	np-> ...
528					/* Delete. */
529while (head.tqh_first != NULL)
530	TAILQ_REMOVE(&head, head.tqh_first, entries);
531.Ed
532.Sh CIRCULAR QUEUES
533A circular queue is headed by a structure defined by the
534.Nm CIRCLEQ_HEAD
535macro.
536This structure contains a pair of pointers,
537one to the first element in the circular queue and the other to the
538last element in the circular queue.
539The elements are doubly linked so that an arbitrary element can be
540removed without traversing the queue.
541New elements can be added to the queue after an existing element,
542before an existing element, at the head of the queue, or at the end
543of the queue.
544A
545.Fa CIRCLEQ_HEAD
546structure is declared as follows:
547.Bd -literal -offset indent
548CIRCLEQ_HEAD(HEADNAME, TYPE) head;
549.Ed
550.sp
551where
552.Li HEADNAME
553is the name of the structure to be defined, and
554.Li TYPE
555is the type of the elements to be linked into the circular queue.
556A pointer to the head of the circular queue can later be declared as:
557.Bd -literal -offset indent
558struct HEADNAME *headp;
559.Ed
560.sp
561(The names
562.Li head
563and
564.Li headp
565are user selectable.)
566.Pp
567The macro
568.Nm CIRCLEQ_ENTRY
569declares a structure that connects the elements in
570the circular queue.
571.Pp
572The macro
573.Nm CIRCLEQ_HEAD_INITIALIZER
574provides a value which can be used to initialize a circular queue head at
575compile time, and is used at the point that the circular queue head
576variable is declared, like:
577.Bd -literal -offset indent
578struct HEADNAME head = CIRCLEQ_HEAD_INITIALIZER(head);
579.Ed
580.Pp
581The macro
582.Nm CIRCLEQ_INIT
583initializes the circular queue referenced by
584.Fa head .
585.Pp
586The macro
587.Nm CIRCLEQ_INSERT_HEAD
588inserts the new element
589.Fa elm
590at the head of the circular queue.
591.Pp
592The macro
593.Nm CIRCLEQ_INSERT_TAIL
594inserts the new element
595.Fa elm
596at the end of the circular queue.
597.Pp
598The macro
599.Nm CIRCLEQ_INSERT_AFTER
600inserts the new element
601.Fa elm
602after the element
603.Fa listelm .
604.Pp
605The macro
606.Nm CIRCLEQ_INSERT_BEFORE
607inserts the new element
608.Fa elm
609before the element
610.Fa listelm .
611.Pp
612The macro
613.Nm CIRCLEQ_REMOVE
614removes the element
615.Fa elm
616from the circular queue.
617.Sh CIRCULAR QUEUE EXAMPLE
618.Bd -literal
619CIRCLEQ_HEAD(circleq, entry) head;
620struct circleq *headp;			/* Circular queue head. */
621struct entry {
622	...
623	CIRCLEQ_ENTRY entries;		/* Circular queue. */
624	...
625} *n1, *n2, *np;
626
627CIRCLEQ_INIT(&head);			/* Initialize the circular queue. */
628
629n1 = malloc(sizeof(struct entry));	/* Insert at the head. */
630CIRCLEQ_INSERT_HEAD(&head, n1, entries);
631
632n1 = malloc(sizeof(struct entry));	/* Insert at the tail. */
633CIRCLEQ_INSERT_TAIL(&head, n1, entries);
634
635n2 = malloc(sizeof(struct entry));	/* Insert after. */
636CIRCLEQ_INSERT_AFTER(&head, n1, n2, entries);
637
638n2 = malloc(sizeof(struct entry));	/* Insert before. */
639CIRCLEQ_INSERT_BEFORE(&head, n1, n2, entries);
640					/* Forward traversal. */
641for (np = head.cqh_first; np != (void *)&head; np = np->entries.cqe_next)
642	np-> ...
643					/* Reverse traversal. */
644for (np = head.cqh_last; np != (void *)&head; np = np->entries.cqe_prev)
645	np-> ...
646					/* Delete. */
647while (head.cqh_first != (void *)&head)
648	CIRCLEQ_REMOVE(&head, head.cqh_first, entries);
649.Ed
650.Sh HISTORY
651The
652.Nm queue
653functions first appeared in 4.4BSD.
654The
655.Nm SIMPLEQ
656functions first appeared in
657.Nx 1.2 .
658