2011/10/25 Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx>:
> We would like some linked list macros which are (a) well known to be
> sane and (b) typesafe. BSD's queue.h meets these criteria.
>
> The files in this changeset were obtained with:
> svn co -r 221843 svn://svn.freebsd.org/base/head/sys/sys/
> svn co -r 221843 svn://svn.freebsd.org/base/head/share/man/man3
>
> We also provide some simple perlery to arrange to add the libxl_
> namespace prefix to the macros. This will allow us to #include our
> modified queue.h in our public header file without clashing with
> anyone else who is also using another version of queue.h.
>
> Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
>
> ---
> tools/libxl/Makefile | 5 +-
> tools/libxl/bsd-queue.3 | 1044
> +++++++++++++++++++++++++++++++++++
> tools/libxl/bsd-sys-queue-h-seddery | 67 +++
> tools/libxl/bsd-sys-queue.h | 637 +++++++++++++++++++++
> 4 files changed, 1752 insertions(+), 1 deletions(-)
>
> diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
> index 51e5132..5d7e0f5 100644
> --- a/tools/libxl/Makefile
> +++ b/tools/libxl/Makefile
> @@ -42,7 +42,7 @@ LIBXL_OBJS += _libxl_types.o libxl_flask.o
> _libxl_types_internal.o
>
> $(LIBXL_OBJS): CFLAGS += $(CFLAGS_libxenctrl) $(CFLAGS_libxenguest)
> $(CFLAGS_libxenstore) $(CFLAGS_libblktapctl)
>
> -AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h
> +AUTOINCS= libxlu_cfg_y.h libxlu_cfg_l.h _libxl_list.h
> AUTOSRCS= libxlu_cfg_y.c libxlu_cfg_l.c
> LIBXLU_OBJS = libxlu_cfg_y.o libxlu_cfg_l.o libxlu_cfg.o \
> libxlu_disk_l.o libxlu_disk.o
> @@ -81,6 +81,9 @@ _libxl_paths.h: genpath
> rm -f $@.tmp
> $(call move-if-changed,$@.2.tmp,$@)
>
> +_libxl_list.h: bsd-sys-queue-h-seddery bsd-sys-queue.h
> + ./$^ --prefix=libxl >$@.new && mv -f $@.new $@
> +
> libxl_paths.c: _libxl_paths.h
>
> libxl.h: _libxl_types.h
> diff --git a/tools/libxl/bsd-queue.3 b/tools/libxl/bsd-queue.3
> new file mode 100644
> index 0000000..007ca5c
> --- /dev/null
> +++ b/tools/libxl/bsd-queue.3
> @@ -0,0 +1,1044 @@
> +.\" Copyright (c) 1993
> +.\" The Regents of the University of California. All rights reserved.
> +.\"
> +.\" Redistribution and use in source and binary forms, with or without
> +.\" modification, are permitted provided that the following conditions
> +.\" are met:
> +.\" 1. Redistributions of source code must retain the above copyright
> +.\" notice, this list of conditions and the following disclaimer.
> +.\" 2. Redistributions in binary form must reproduce the above copyright
> +.\" notice, this list of conditions and the following disclaimer in the
> +.\" documentation and/or other materials provided with the distribution.
> +.\" 3. All advertising materials mentioning features or use of this software
> +.\" must display the following acknowledgement:
> +.\" This product includes software developed by the University of
> +.\" California, Berkeley and its contributors.
> +.\" 4. Neither the name of the University nor the names of its contributors
> +.\" may be used to endorse or promote products derived from this software
> +.\" without specific prior written permission.
> +.\"
> +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
> PURPOSE
> +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
> CONSEQUENTIAL
> +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
> STRICT
> +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> +.\" SUCH DAMAGE.
> +.\"
> +.\" @(#)queue.3 8.2 (Berkeley) 1/24/94
> +.\" $FreeBSD$
> +.\"
> +.Dd May 13, 2011
> +.Dt QUEUE 3
> +.Os
> +.Sh NAME
> +.Nm SLIST_EMPTY ,
> +.Nm SLIST_ENTRY ,
> +.Nm SLIST_FIRST ,
> +.Nm SLIST_FOREACH ,
> +.Nm SLIST_FOREACH_SAFE ,
> +.Nm SLIST_HEAD ,
> +.Nm SLIST_HEAD_INITIALIZER ,
> +.Nm SLIST_INIT ,
> +.Nm SLIST_INSERT_AFTER ,
> +.Nm SLIST_INSERT_HEAD ,
> +.Nm SLIST_NEXT ,
> +.Nm SLIST_REMOVE_AFTER ,
> +.Nm SLIST_REMOVE_HEAD ,
> +.Nm SLIST_REMOVE ,
> +.Nm SLIST_SWAP ,
> +.Nm STAILQ_CONCAT ,
> +.Nm STAILQ_EMPTY ,
> +.Nm STAILQ_ENTRY ,
> +.Nm STAILQ_FIRST ,
> +.Nm STAILQ_FOREACH ,
> +.Nm STAILQ_FOREACH_SAFE ,
> +.Nm STAILQ_HEAD ,
> +.Nm STAILQ_HEAD_INITIALIZER ,
> +.Nm STAILQ_INIT ,
> +.Nm STAILQ_INSERT_AFTER ,
> +.Nm STAILQ_INSERT_HEAD ,
> +.Nm STAILQ_INSERT_TAIL ,
> +.Nm STAILQ_LAST ,
> +.Nm STAILQ_NEXT ,
> +.Nm STAILQ_REMOVE_AFTER ,
> +.Nm STAILQ_REMOVE_HEAD ,
> +.Nm STAILQ_REMOVE ,
> +.Nm STAILQ_SWAP ,
> +.Nm LIST_EMPTY ,
> +.Nm LIST_ENTRY ,
> +.Nm LIST_FIRST ,
> +.Nm LIST_FOREACH ,
> +.Nm LIST_FOREACH_SAFE ,
> +.Nm LIST_HEAD ,
> +.Nm LIST_HEAD_INITIALIZER ,
> +.Nm LIST_INIT ,
> +.Nm LIST_INSERT_AFTER ,
> +.Nm LIST_INSERT_BEFORE ,
> +.Nm LIST_INSERT_HEAD ,
> +.Nm LIST_NEXT ,
> +.Nm LIST_REMOVE ,
> +.Nm LIST_SWAP ,
> +.Nm TAILQ_CONCAT ,
> +.Nm TAILQ_EMPTY ,
> +.Nm TAILQ_ENTRY ,
> +.Nm TAILQ_FIRST ,
> +.Nm TAILQ_FOREACH ,
> +.Nm TAILQ_FOREACH_SAFE ,
> +.Nm TAILQ_FOREACH_REVERSE ,
> +.Nm TAILQ_FOREACH_REVERSE_SAFE ,
> +.Nm TAILQ_HEAD ,
> +.Nm TAILQ_HEAD_INITIALIZER ,
> +.Nm TAILQ_INIT ,
> +.Nm TAILQ_INSERT_AFTER ,
> +.Nm TAILQ_INSERT_BEFORE ,
> +.Nm TAILQ_INSERT_HEAD ,
> +.Nm TAILQ_INSERT_TAIL ,
> +.Nm TAILQ_LAST ,
> +.Nm TAILQ_NEXT ,
> +.Nm TAILQ_PREV ,
> +.Nm TAILQ_REMOVE ,
> +.Nm TAILQ_SWAP
> +.Nd implementations of singly-linked lists, singly-linked tail queues,
> +lists and tail queues
> +.Sh SYNOPSIS
> +.In sys/queue.h
> +.\"
> +.Fn SLIST_EMPTY "SLIST_HEAD *head"
> +.Fn SLIST_ENTRY "TYPE"
> +.Fn SLIST_FIRST "SLIST_HEAD *head"
> +.Fn SLIST_FOREACH "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
> +.Fn SLIST_FOREACH_SAFE "TYPE *var" "SLIST_HEAD *head" "SLIST_ENTRY NAME"
> "TYPE *temp_var"
> +.Fn SLIST_HEAD "HEADNAME" "TYPE"
> +.Fn SLIST_HEAD_INITIALIZER "SLIST_HEAD head"
> +.Fn SLIST_INIT "SLIST_HEAD *head"
> +.Fn SLIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "SLIST_ENTRY NAME"
> +.Fn SLIST_INSERT_HEAD "SLIST_HEAD *head" "TYPE *elm" "SLIST_ENTRY NAME"
> +.Fn SLIST_NEXT "TYPE *elm" "SLIST_ENTRY NAME"
> +.Fn SLIST_REMOVE_AFTER "TYPE *elm" "SLIST_ENTRY NAME"
> +.Fn SLIST_REMOVE_HEAD "SLIST_HEAD *head" "SLIST_ENTRY NAME"
> +.Fn SLIST_REMOVE "SLIST_HEAD *head" "TYPE *elm" "TYPE" "SLIST_ENTRY NAME"
> +.Fn SLIST_SWAP "SLIST_HEAD *head1" "SLIST_HEAD *head2" "SLIST_ENTRY NAME"
> +.\"
> +.Fn STAILQ_CONCAT "STAILQ_HEAD *head1" "STAILQ_HEAD *head2"
> +.Fn STAILQ_EMPTY "STAILQ_HEAD *head"
> +.Fn STAILQ_ENTRY "TYPE"
> +.Fn STAILQ_FIRST "STAILQ_HEAD *head"
> +.Fn STAILQ_FOREACH "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_FOREACH_SAFE "TYPE *var" "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
> "TYPE *temp_var"
> +.Fn STAILQ_HEAD "HEADNAME" "TYPE"
> +.Fn STAILQ_HEAD_INITIALIZER "STAILQ_HEAD head"
> +.Fn STAILQ_INIT "STAILQ_HEAD *head"
> +.Fn STAILQ_INSERT_AFTER "STAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm"
> "STAILQ_ENTRY NAME"
> +.Fn STAILQ_INSERT_HEAD "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_INSERT_TAIL "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_LAST "STAILQ_HEAD *head" "TYPE" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_NEXT "TYPE *elm" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_REMOVE_AFTER "STAILQ_HEAD *head" "TYPE *elm" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_REMOVE_HEAD "STAILQ_HEAD *head" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_REMOVE "STAILQ_HEAD *head" "TYPE *elm" "TYPE" "STAILQ_ENTRY NAME"
> +.Fn STAILQ_SWAP "STAILQ_HEAD *head1" "STAILQ_HEAD *head2" "STAILQ_ENTRY NAME"
> +.\"
> +.Fn LIST_EMPTY "LIST_HEAD *head"
> +.Fn LIST_ENTRY "TYPE"
> +.Fn LIST_FIRST "LIST_HEAD *head"
> +.Fn LIST_FOREACH "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME"
> +.Fn LIST_FOREACH_SAFE "TYPE *var" "LIST_HEAD *head" "LIST_ENTRY NAME" "TYPE
> *temp_var"
> +.Fn LIST_HEAD "HEADNAME" "TYPE"
> +.Fn LIST_HEAD_INITIALIZER "LIST_HEAD head"
> +.Fn LIST_INIT "LIST_HEAD *head"
> +.Fn LIST_INSERT_AFTER "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
> +.Fn LIST_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "LIST_ENTRY NAME"
> +.Fn LIST_INSERT_HEAD "LIST_HEAD *head" "TYPE *elm" "LIST_ENTRY NAME"
> +.Fn LIST_NEXT "TYPE *elm" "LIST_ENTRY NAME"
> +.Fn LIST_REMOVE "TYPE *elm" "LIST_ENTRY NAME"
> +.Fn LIST_SWAP "LIST_HEAD *head1" "LIST_HEAD *head2" "TYPE" "LIST_ENTRY NAME"
> +.\"
> +.Fn TAILQ_CONCAT "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_EMPTY "TAILQ_HEAD *head"
> +.Fn TAILQ_ENTRY "TYPE"
> +.Fn TAILQ_FIRST "TAILQ_HEAD *head"
> +.Fn TAILQ_FOREACH "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_FOREACH_SAFE "TYPE *var" "TAILQ_HEAD *head" "TAILQ_ENTRY NAME"
> "TYPE *temp_var"
> +.Fn TAILQ_FOREACH_REVERSE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME"
> "TAILQ_ENTRY NAME"
> +.Fn TAILQ_FOREACH_REVERSE_SAFE "TYPE *var" "TAILQ_HEAD *head" "HEADNAME"
> "TAILQ_ENTRY NAME" "TYPE *temp_var"
> +.Fn TAILQ_HEAD "HEADNAME" "TYPE"
> +.Fn TAILQ_HEAD_INITIALIZER "TAILQ_HEAD head"
> +.Fn TAILQ_INIT "TAILQ_HEAD *head"
> +.Fn TAILQ_INSERT_AFTER "TAILQ_HEAD *head" "TYPE *listelm" "TYPE *elm"
> "TAILQ_ENTRY NAME"
> +.Fn TAILQ_INSERT_BEFORE "TYPE *listelm" "TYPE *elm" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_INSERT_HEAD "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_INSERT_TAIL "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_LAST "TAILQ_HEAD *head" "HEADNAME"
> +.Fn TAILQ_NEXT "TYPE *elm" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_PREV "TYPE *elm" "HEADNAME" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_REMOVE "TAILQ_HEAD *head" "TYPE *elm" "TAILQ_ENTRY NAME"
> +.Fn TAILQ_SWAP "TAILQ_HEAD *head1" "TAILQ_HEAD *head2" "TYPE" "TAILQ_ENTRY
> NAME"
> +.\"
> +.Sh DESCRIPTION
> +These macros define and operate on four types of data structures:
> +singly-linked lists, singly-linked tail queues, lists, and tail queues.
> +All four structures support the following functionality:
> +.Bl -enum -compact -offset indent
> +.It
> +Insertion of a new entry at the head of the list.
> +.It
> +Insertion of a new entry after any element in the list.
> +.It
> +O(1) removal of an entry from the head of the list.
> +.It
> +Forward traversal through the list.
> +.It
> +Swawpping the contents of two lists.
> +.El
> +.Pp
> +Singly-linked lists are the simplest of the four data structures
> +and support only the above functionality.
> +Singly-linked lists are ideal for applications with large datasets
> +and few or no removals,
> +or for implementing a LIFO queue.
> +Singly-linked lists add the following functionality:
> +.Bl -enum -compact -offset indent
> +.It
> +O(n) removal of any entry in the list.
> +.El
> +.Pp
> +Singly-linked tail queues add the following functionality:
> +.Bl -enum -compact -offset indent
> +.It
> +Entries can be added at the end of a list.
> +.It
> +O(n) removal of any entry in the list.
> +.It
> +They may be concatenated.
> +.El
> +However:
> +.Bl -enum -compact -offset indent
> +.It
> +All list insertions must specify the head of the list.
> +.It
> +Each head entry requires two pointers rather than one.
> +.It
> +Code size is about 15% greater and operations run about 20% slower
> +than singly-linked lists.
> +.El
> +.Pp
> +Singly-linked tailqs are ideal for applications with large datasets and
> +few or no removals,
> +or for implementing a FIFO queue.
> +.Pp
> +All doubly linked types of data structures (lists and tail queues)
> +additionally allow:
> +.Bl -enum -compact -offset indent
> +.It
> +Insertion of a new entry before any element in the list.
> +.It
> +O(1) removal of any entry in the list.
> +.El
> +However:
> +.Bl -enum -compact -offset indent
> +.It
> +Each element requires two pointers rather than one.
> +.It
> +Code size and execution time of operations (except for removal) is about
> +twice that of the singly-linked data-structures.
> +.El
> +.Pp
> +Linked lists are the simplest of the doubly linked data structures and
> support
> +only the above functionality over singly-linked lists.
> +.Pp
> +Tail queues add the following functionality:
> +.Bl -enum -compact -offset indent
> +.It
> +Entries can be added at the end of a list.
> +.It
> +They may be traversed backwards, from tail to head.
> +.It
> +They may be concatenated.
> +.El
> +However:
> +.Bl -enum -compact -offset indent
> +.It
> +All list insertions and removals must specify the head of the list.
> +.It
> +Each head entry requires two pointers rather than one.
> +.It
> +Code size is about 15% greater and operations run about 20% slower
> +than singly-linked lists.
> +.El
> +.Pp
> +In the macro definitions,
> +.Fa TYPE
> +is the name of a user defined structure,
> +that must contain a field of type
> +.Li SLIST_ENTRY ,
> +.Li STAILQ_ENTRY ,
> +.Li LIST_ENTRY ,
> +or
> +.Li TAILQ_ENTRY ,
> +named
> +.Fa NAME .
> +The argument
> +.Fa HEADNAME
> +is the name of a user defined structure that must be declared
> +using the macros
> +.Li SLIST_HEAD ,
> +.Li STAILQ_HEAD ,
> +.Li LIST_HEAD ,
> +or
> +.Li TAILQ_HEAD .
> +See the examples below for further explanation of how these
> +macros are used.
> +.Sh SINGLY-LINKED LISTS
> +A singly-linked list is headed by a structure defined by the
> +.Nm SLIST_HEAD
> +macro.
> +This structure contains a single pointer to the first element
> +on the list.
> +The elements are singly linked for minimum space and pointer manipulation
> +overhead at the expense of O(n) removal for arbitrary elements.
> +New elements can be added to the list after an existing element or
> +at the head of the list.
> +An
> +.Fa SLIST_HEAD
> +structure is declared as follows:
> +.Bd -literal -offset indent
> +SLIST_HEAD(HEADNAME, TYPE) head;
> +.Ed
> +.Pp
> +where
> +.Fa HEADNAME
> +is the name of the structure to be defined, and
> +.Fa TYPE
> +is the type of the elements to be linked into the list.
> +A pointer to the head of the list can later be declared as:
> +.Bd -literal -offset indent
> +struct HEADNAME *headp;
> +.Ed
> +.Pp
> +(The names
> +.Li head
> +and
> +.Li headp
> +are user selectable.)
> +.Pp
> +The macro
> +.Nm SLIST_HEAD_INITIALIZER
> +evaluates to an initializer for the list
> +.Fa head .
> +.Pp
> +The macro
> +.Nm SLIST_EMPTY
> +evaluates to true if there are no elements in the list.
> +.Pp
> +The macro
> +.Nm SLIST_ENTRY
> +declares a structure that connects the elements in
> +the list.
> +.Pp
> +The macro
> +.Nm SLIST_FIRST
> +returns the first element in the list or NULL if the list is empty.
> +.Pp
> +The macro
> +.Nm SLIST_FOREACH
> +traverses the list referenced by
> +.Fa head
> +in the forward direction, assigning each element in
> +turn to
> +.Fa var .
> +.Pp
> +The macro
> +.Nm SLIST_FOREACH_SAFE
> +traverses the list referenced by
> +.Fa head
> +in the forward direction, assigning each element in
> +turn to
> +.Fa var .
> +However, unlike
> +.Fn SLIST_FOREACH
> +here it is permitted to both remove
> +.Fa var
> +as well as free it from within the loop safely without interfering with the
> +traversal.
> +.Pp
> +The macro
> +.Nm SLIST_INIT
> +initializes the list referenced by
> +.Fa head .
> +.Pp
> +The macro
> +.Nm SLIST_INSERT_HEAD
> +inserts the new element
> +.Fa elm
> +at the head of the list.
> +.Pp
> +The macro
> +.Nm SLIST_INSERT_AFTER
> +inserts the new element
> +.Fa elm
> +after the element
> +.Fa listelm .
> +.Pp
> +The macro
> +.Nm SLIST_NEXT
> +returns the next element in the list.
> +.Pp
> +The macro
> +.Nm SLIST_REMOVE_AFTER
> +removes the element after
> +.Fa elm
> +from the list. Unlike
> +.Fa SLIST_REMOVE ,
> +this macro does not traverse the entire list.
> +.Pp
> +The macro
> +.Nm SLIST_REMOVE_HEAD
> +removes the element
> +.Fa elm
> +from the head of the list.
> +For optimum efficiency,
> +elements being removed from the head of the list should explicitly use
> +this macro instead of the generic
> +.Fa SLIST_REMOVE
> +macro.
> +.Pp
> +The macro
> +.Nm SLIST_REMOVE
> +removes the element
> +.Fa elm
> +from the list.
> +.Pp
> +The macro
> +.Nm SLIST_SWAP
> +swaps the contents of
> +.Fa head1
> +and
> +.Fa head2 .
> +.Sh SINGLY-LINKED LIST EXAMPLE
> +.Bd -literal
> +SLIST_HEAD(slisthead, entry) head =
> + SLIST_HEAD_INITIALIZER(head);
> +struct slisthead *headp; /* Singly-linked List head. */
> +struct entry {
> + ...
> + SLIST_ENTRY(entry) entries; /* Singly-linked List. */
> + ...
> +} *n1, *n2, *n3, *np;
> +
> +SLIST_INIT(&head); /* Initialize the list. */
> +
> +n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
> +SLIST_INSERT_HEAD(&head, n1, entries);
> +
> +n2 = malloc(sizeof(struct entry)); /* Insert after. */
> +SLIST_INSERT_AFTER(n1, n2, entries);
> +
> +SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */
> +free(n2);
> +
> +n3 = SLIST_FIRST(&head);
> +SLIST_REMOVE_HEAD(&head, entries); /* Deletion from the head. */
> +free(n3);
> + /* Forward traversal. */
> +SLIST_FOREACH(np, &head, entries)
> + np-> ...
> + /* Safe forward traversal. */
> +SLIST_FOREACH_SAFE(np, &head, entries, np_temp) {
> + np->do_stuff();
> + ...
> + SLIST_REMOVE(&head, np, entry, entries);
> + free(np);
> +}
> +
> +while (!SLIST_EMPTY(&head)) { /* List Deletion. */
> + n1 = SLIST_FIRST(&head);
> + SLIST_REMOVE_HEAD(&head, entries);
> + free(n1);
> +}
> +.Ed
> +.Sh SINGLY-LINKED TAIL QUEUES
> +A singly-linked tail queue is headed by a structure defined by the
> +.Nm STAILQ_HEAD
> +macro.
> +This structure contains a pair of pointers,
> +one to the first element in the tail queue and the other to
> +the last element in the tail queue.
> +The elements are singly linked for minimum space and pointer
> +manipulation overhead at the expense of O(n) removal for arbitrary
> +elements.
> +New elements can be added to the tail queue after an existing element,
> +at the head of the tail queue, or at the end of the tail queue.
> +A
> +.Fa STAILQ_HEAD
> +structure is declared as follows:
> +.Bd -literal -offset indent
> +STAILQ_HEAD(HEADNAME, TYPE) head;
> +.Ed
> +.Pp
> +where
> +.Li HEADNAME
> +is the name of the structure to be defined, and
> +.Li TYPE
> +is the type of the elements to be linked into the tail queue.
> +A pointer to the head of the tail queue can later be declared as:
> +.Bd -literal -offset indent
> +struct HEADNAME *headp;
> +.Ed
> +.Pp
> +(The names
> +.Li head
> +and
> +.Li headp
> +are user selectable.)
> +.Pp
> +The macro
> +.Nm STAILQ_HEAD_INITIALIZER
> +evaluates to an initializer for the tail queue
> +.Fa head .
> +.Pp
> +The macro
> +.Nm STAILQ_CONCAT
> +concatenates the tail queue headed by
> +.Fa head2
> +onto the end of the one headed by
> +.Fa head1
> +removing all entries from the former.
> +.Pp
> +The macro
> +.Nm STAILQ_EMPTY
> +evaluates to true if there are no items on the tail queue.
> +.Pp
> +The macro
> +.Nm STAILQ_ENTRY
> +declares a structure that connects the elements in
> +the tail queue.
> +.Pp
> +The macro
> +.Nm STAILQ_FIRST
> +returns the first item on the tail queue or NULL if the tail queue
> +is empty.
> +.Pp
> +The macro
> +.Nm STAILQ_FOREACH
> +traverses the tail queue referenced by
> +.Fa head
> +in the forward direction, assigning each element
> +in turn to
> +.Fa var .
> +.Pp
> +The macro
> +.Nm STAILQ_FOREACH_SAFE
> +traverses the tail queue referenced by
> +.Fa head
> +in the forward direction, assigning each element
> +in turn to
> +.Fa var .
> +However, unlike
> +.Fn STAILQ_FOREACH
> +here it is permitted to both remove
> +.Fa var
> +as well as free it from within the loop safely without interfering with the
> +traversal.
> +.Pp
> +The macro
> +.Nm STAILQ_INIT
> +initializes the tail queue referenced by
> +.Fa head .
> +.Pp
> +The macro
> +.Nm STAILQ_INSERT_HEAD
> +inserts the new element
> +.Fa elm
> +at the head of the tail queue.
> +.Pp
> +The macro
> +.Nm STAILQ_INSERT_TAIL
> +inserts the new element
> +.Fa elm
> +at the end of the tail queue.
> +.Pp
> +The macro
> +.Nm STAILQ_INSERT_AFTER
> +inserts the new element
> +.Fa elm
> +after the element
> +.Fa listelm .
> +.Pp
> +The macro
> +.Nm STAILQ_LAST
> +returns the last item on the tail queue.
> +If the tail queue is empty the return value is
> +.Dv NULL .
> +.Pp
> +The macro
> +.Nm STAILQ_NEXT
> +returns the next item on the tail queue, or NULL this item is the last.
> +.Pp
> +The macro
> +.Nm STAILQ_REMOVE_AFTER
> +removes the element after
> +.Fa elm
> +from the tail queue. Unlike
> +.Fa STAILQ_REMOVE ,
> +this macro does not traverse the entire tail queue.
> +.Pp
> +The macro
> +.Nm STAILQ_REMOVE_HEAD
> +removes the element at the head of the tail queue.
> +For optimum efficiency,
> +elements being removed from the head of the tail queue should
> +use this macro explicitly rather than the generic
> +.Fa STAILQ_REMOVE
> +macro.
> +.Pp
> +The macro
> +.Nm STAILQ_REMOVE
> +removes the element
> +.Fa elm
> +from the tail queue.
> +.Pp
> +The macro
> +.Nm STAILQ_SWAP
> +swaps the contents of
> +.Fa head1
> +and
> +.Fa head2 .
> +.Sh SINGLY-LINKED TAIL QUEUE EXAMPLE
> +.Bd -literal
> +STAILQ_HEAD(stailhead, entry) head =
> + STAILQ_HEAD_INITIALIZER(head);
> +struct stailhead *headp; /* Singly-linked tail queue head. */
> +struct entry {
> + ...
> + STAILQ_ENTRY(entry) entries; /* Tail queue. */
> + ...
> +} *n1, *n2, *n3, *np;
> +
> +STAILQ_INIT(&head); /* Initialize the queue. */
> +
> +n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
> +STAILQ_INSERT_HEAD(&head, n1, entries);
> +
> +n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
> +STAILQ_INSERT_TAIL(&head, n1, entries);
> +
> +n2 = malloc(sizeof(struct entry)); /* Insert after. */
> +STAILQ_INSERT_AFTER(&head, n1, n2, entries);
> + /* Deletion. */
> +STAILQ_REMOVE(&head, n2, entry, entries);
> +free(n2);
> + /* Deletion from the head. */
> +n3 = STAILQ_FIRST(&head);
> +STAILQ_REMOVE_HEAD(&head, entries);
> +free(n3);
> + /* Forward traversal. */
> +STAILQ_FOREACH(np, &head, entries)
> + np-> ...
> + /* Safe forward traversal. */
> +STAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
> + np->do_stuff();
> + ...
> + STAILQ_REMOVE(&head, np, entry, entries);
> + free(np);
> +}
> + /* TailQ Deletion. */
> +while (!STAILQ_EMPTY(&head)) {
> + n1 = STAILQ_FIRST(&head);
> + STAILQ_REMOVE_HEAD(&head, entries);
> + free(n1);
> +}
> + /* Faster TailQ Deletion. */
> +n1 = STAILQ_FIRST(&head);
> +while (n1 != NULL) {
> + n2 = STAILQ_NEXT(n1, entries);
> + free(n1);
> + n1 = n2;
> +}
> +STAILQ_INIT(&head);
> +.Ed
> +.Sh LISTS
> +A list is headed by a structure defined by the
> +.Nm LIST_HEAD
> +macro.
> +This structure contains a single pointer to the first element
> +on the list.
> +The elements are doubly linked so that an arbitrary element can be
> +removed without traversing the list.
> +New elements can be added to the list after an existing element,
> +before an existing element, or at the head of the list.
> +A
> +.Fa LIST_HEAD
> +structure is declared as follows:
> +.Bd -literal -offset indent
> +LIST_HEAD(HEADNAME, TYPE) head;
> +.Ed
> +.Pp
> +where
> +.Fa HEADNAME
> +is the name of the structure to be defined, and
> +.Fa TYPE
> +is the type of the elements to be linked into the list.
> +A pointer to the head of the list can later be declared as:
> +.Bd -literal -offset indent
> +struct HEADNAME *headp;
> +.Ed
> +.Pp
> +(The names
> +.Li head
> +and
> +.Li headp
> +are user selectable.)
> +.Pp
> +The macro
> +.Nm LIST_HEAD_INITIALIZER
> +evaluates to an initializer for the list
> +.Fa head .
> +.Pp
> +The macro
> +.Nm LIST_EMPTY
> +evaluates to true if there are no elements in the list.
> +.Pp
> +The macro
> +.Nm LIST_ENTRY
> +declares a structure that connects the elements in
> +the list.
> +.Pp
> +The macro
> +.Nm LIST_FIRST
> +returns the first element in the list or NULL if the list
> +is empty.
> +.Pp
> +The macro
> +.Nm LIST_FOREACH
> +traverses the list referenced by
> +.Fa head
> +in the forward direction, assigning each element in turn to
> +.Fa var .
> +.Pp
> +The macro
> +.Nm LIST_FOREACH_SAFE
> +traverses the list referenced by
> +.Fa head
> +in the forward direction, assigning each element in turn to
> +.Fa var .
> +However, unlike
> +.Fn LIST_FOREACH
> +here it is permitted to both remove
> +.Fa var
> +as well as free it from within the loop safely without interfering with the
> +traversal.
> +.Pp
> +The macro
> +.Nm LIST_INIT
> +initializes the list referenced by
> +.Fa head .
> +.Pp
> +The macro
> +.Nm LIST_INSERT_HEAD
> +inserts the new element
> +.Fa elm
> +at the head of the list.
> +.Pp
> +The macro
> +.Nm LIST_INSERT_AFTER
> +inserts the new element
> +.Fa elm
> +after the element
> +.Fa listelm .
> +.Pp
> +The macro
> +.Nm LIST_INSERT_BEFORE
> +inserts the new element
> +.Fa elm
> +before the element
> +.Fa listelm .
> +.Pp
> +The macro
> +.Nm LIST_NEXT
> +returns the next element in the list, or NULL if this is the last.
> +.Pp
> +The macro
> +.Nm LIST_REMOVE
> +removes the element
> +.Fa elm
> +from the list.
> +.Pp
> +The macro
> +.Nm LIST_SWAP
> +swaps the contents of
> +.Fa head1
> +and
> +.Fa head2 .
> +.Sh LIST EXAMPLE
> +.Bd -literal
> +LIST_HEAD(listhead, entry) head =
> + LIST_HEAD_INITIALIZER(head);
> +struct listhead *headp; /* List head. */
> +struct entry {
> + ...
> + LIST_ENTRY(entry) entries; /* List. */
> + ...
> +} *n1, *n2, *n3, *np, *np_temp;
> +
> +LIST_INIT(&head); /* Initialize the list. */
> +
> +n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
> +LIST_INSERT_HEAD(&head, n1, entries);
> +
> +n2 = malloc(sizeof(struct entry)); /* Insert after. */
> +LIST_INSERT_AFTER(n1, n2, entries);
> +
> +n3 = malloc(sizeof(struct entry)); /* Insert before. */
> +LIST_INSERT_BEFORE(n2, n3, entries);
> +
> +LIST_REMOVE(n2, entries); /* Deletion. */
> +free(n2);
> + /* Forward traversal. */
> +LIST_FOREACH(np, &head, entries)
> + np-> ...
> +
> + /* Safe forward traversal. */
> +LIST_FOREACH_SAFE(np, &head, entries, np_temp) {
> + np->do_stuff();
> + ...
> + LIST_REMOVE(np, entries);
> + free(np);
> +}
> +
> +while (!LIST_EMPTY(&head)) { /* List Deletion. */
> + n1 = LIST_FIRST(&head);
> + LIST_REMOVE(n1, entries);
> + free(n1);
> +}
> +
> +n1 = LIST_FIRST(&head); /* Faster List Deletion. */
> +while (n1 != NULL) {
> + n2 = LIST_NEXT(n1, entries);
> + free(n1);
> + n1 = n2;
> +}
> +LIST_INIT(&head);
> +.Ed
> +.Sh TAIL QUEUES
> +A tail queue is headed by a structure defined by the
> +.Nm TAILQ_HEAD
> +macro.
> +This structure contains a pair of pointers,
> +one to the first element in the tail queue and the other to
> +the last element in the tail queue.
> +The elements are doubly linked so that an arbitrary element can be
> +removed without traversing the tail queue.
> +New elements can be added to the tail queue after an existing element,
> +before an existing element, at the head of the tail queue,
> +or at the end of the tail queue.
> +A
> +.Fa TAILQ_HEAD
> +structure is declared as follows:
> +.Bd -literal -offset indent
> +TAILQ_HEAD(HEADNAME, TYPE) head;
> +.Ed
> +.Pp
> +where
> +.Li HEADNAME
> +is the name of the structure to be defined, and
> +.Li TYPE
> +is the type of the elements to be linked into the tail queue.
> +A pointer to the head of the tail queue can later be declared as:
> +.Bd -literal -offset indent
> +struct HEADNAME *headp;
> +.Ed
> +.Pp
> +(The names
> +.Li head
> +and
> +.Li headp
> +are user selectable.)
> +.Pp
> +The macro
> +.Nm TAILQ_HEAD_INITIALIZER
> +evaluates to an initializer for the tail queue
> +.Fa head .
> +.Pp
> +The macro
> +.Nm TAILQ_CONCAT
> +concatenates the tail queue headed by
> +.Fa head2
> +onto the end of the one headed by
> +.Fa head1
> +removing all entries from the former.
> +.Pp
> +The macro
> +.Nm TAILQ_EMPTY
> +evaluates to true if there are no items on the tail queue.
> +.Pp
> +The macro
> +.Nm TAILQ_ENTRY
> +declares a structure that connects the elements in
> +the tail queue.
> +.Pp
> +The macro
> +.Nm TAILQ_FIRST
> +returns the first item on the tail queue or NULL if the tail queue
> +is empty.
> +.Pp
> +The macro
> +.Nm TAILQ_FOREACH
> +traverses the tail queue referenced by
> +.Fa head
> +in the forward direction, assigning each element in turn to
> +.Fa var .
> +.Fa var
> +is set to
> +.Dv NULL
> +if the loop completes normally, or if there were no elements.
> +.Pp
> +The macro
> +.Nm TAILQ_FOREACH_REVERSE
> +traverses the tail queue referenced by
> +.Fa head
> +in the reverse direction, assigning each element in turn to
> +.Fa var .
> +.Pp
> +The macros
> +.Nm TAILQ_FOREACH_SAFE
> +and
> +.Nm TAILQ_FOREACH_REVERSE_SAFE
> +traverse the list referenced by
> +.Fa head
> +in the forward or reverse direction respectively,
> +assigning each element in turn to
> +.Fa var .
> +However, unlike their unsafe counterparts,
> +.Nm TAILQ_FOREACH
> +and
> +.Nm TAILQ_FOREACH_REVERSE
> +permit to both remove
> +.Fa var
> +as well as free it from within the loop safely without interfering with the
> +traversal.
> +.Pp
> +The macro
> +.Nm TAILQ_INIT
> +initializes the tail queue referenced by
> +.Fa head .
> +.Pp
> +The macro
> +.Nm TAILQ_INSERT_HEAD
> +inserts the new element
> +.Fa elm
> +at the head of the tail queue.
> +.Pp
> +The macro
> +.Nm TAILQ_INSERT_TAIL
> +inserts the new element
> +.Fa elm
> +at the end of the tail queue.
> +.Pp
> +The macro
> +.Nm TAILQ_INSERT_AFTER
> +inserts the new element
> +.Fa elm
> +after the element
> +.Fa listelm .
> +.Pp
> +The macro
> +.Nm TAILQ_INSERT_BEFORE
> +inserts the new element
> +.Fa elm
> +before the element
> +.Fa listelm .
> +.Pp
> +The macro
> +.Nm TAILQ_LAST
> +returns the last item on the tail queue.
> +If the tail queue is empty the return value is
> +.Dv NULL .
> +.Pp
> +The macro
> +.Nm TAILQ_NEXT
> +returns the next item on the tail queue, or NULL if this item is the last.
> +.Pp
> +The macro
> +.Nm TAILQ_PREV
> +returns the previous item on the tail queue, or NULL if this item
> +is the first.
> +.Pp
> +The macro
> +.Nm TAILQ_REMOVE
> +removes the element
> +.Fa elm
> +from the tail queue.
> +.Pp
> +The macro
> +.Nm TAILQ_SWAP
> +swaps the contents of
> +.Fa head1
> +and
> +.Fa head2 .
> +.Sh TAIL QUEUE EXAMPLE
> +.Bd -literal
> +TAILQ_HEAD(tailhead, entry) head =
> + TAILQ_HEAD_INITIALIZER(head);
> +struct tailhead *headp; /* Tail queue head. */
> +struct entry {
> + ...
> + TAILQ_ENTRY(entry) entries; /* Tail queue. */
> + ...
> +} *n1, *n2, *n3, *np;
> +
> +TAILQ_INIT(&head); /* Initialize the queue. */
> +
> +n1 = malloc(sizeof(struct entry)); /* Insert at the head. */
> +TAILQ_INSERT_HEAD(&head, n1, entries);
> +
> +n1 = malloc(sizeof(struct entry)); /* Insert at the tail. */
> +TAILQ_INSERT_TAIL(&head, n1, entries);
> +
> +n2 = malloc(sizeof(struct entry)); /* Insert after. */
> +TAILQ_INSERT_AFTER(&head, n1, n2, entries);
> +
> +n3 = malloc(sizeof(struct entry)); /* Insert before. */
> +TAILQ_INSERT_BEFORE(n2, n3, entries);
> +
> +TAILQ_REMOVE(&head, n2, entries); /* Deletion. */
> +free(n2);
> + /* Forward traversal. */
> +TAILQ_FOREACH(np, &head, entries)
> + np-> ...
> + /* Safe forward traversal. */
> +TAILQ_FOREACH_SAFE(np, &head, entries, np_temp) {
> + np->do_stuff();
> + ...
> + TAILQ_REMOVE(&head, np, entries);
> + free(np);
> +}
> + /* Reverse traversal. */
> +TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries)
> + np-> ...
> + /* TailQ Deletion. */
> +while (!TAILQ_EMPTY(&head)) {
> + n1 = TAILQ_FIRST(&head);
> + TAILQ_REMOVE(&head, n1, entries);
> + free(n1);
> +}
> + /* Faster TailQ Deletion. */
> +n1 = TAILQ_FIRST(&head);
> +while (n1 != NULL) {
> + n2 = TAILQ_NEXT(n1, entries);
> + free(n1);
> + n1 = n2;
> +}
> +TAILQ_INIT(&head);
> +.Ed
> +.Sh SEE ALSO
> +.Xr tree 3
> +.Sh HISTORY
> +The
> +.Nm queue
> +functions first appeared in
> +.Bx 4.4 .
> diff --git a/tools/libxl/bsd-sys-queue-h-seddery
> b/tools/libxl/bsd-sys-queue-h-seddery
> new file mode 100755
> index 0000000..0bab8e0
> --- /dev/null
> +++ b/tools/libxl/bsd-sys-queue-h-seddery
> @@ -0,0 +1,67 @@
> +#!/usr/bin/perl -p
This should be something like:
#!/usr/bin/env perl
For this script to work on BSD systems, which usually have perl in
/usr/pkg/bin/perl or /usr/local/bin/perl
> +#
> +# This script is part of the Xen build system. It has a very
> +# permissive licence to avoid complicating the licence of the
> +# generated header file and to allow this seddery to be reused by
> +# other projects.
> +#
> +# Permission is hereby granted, free of charge, to any person
> +# obtaining a copy of this individual file (the "Software"), to deal
> +# in the Software without restriction, including without limitation
> +# the rights to use, copy, modify, merge, publish, distribute,
> +# sublicense, and/or sell copies of the Software, and to permit
> +# persons to whom the Software is furnished to do so, subject to the
> +# following conditions:
> +#
> +# The above copyright notice and this permission notice shall be
> +# included in all copies or substantial portions of the Software.
> +#
> +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
> +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> +# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> +# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> +# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> +# SOFTWARE.
> +#
> +# Copyright (C) 2011 Citrix Ltd
> +
> +our $namespace, $ucnamespace;
> +
> +BEGIN {
> + die unless @ARGV;
> + $namespace = pop @ARGV;
> + $namespace =~ s/^--prefix=// or die;
> + $ucnamespace = uc $namespace;
> +
> + print <<END or die $!;
> +/*
> + * DO NOT EDIT THIS FILE
> + *
> + * Generated automatically by bsd-sys-queue-h-seddery to
> + * - introduce ${ucnamespace}_ and ${namespace}_ namespace prefixes
> + * - turn "struct type" into "type" so that type arguments
> + * to the macros are type names not struct tags
> + *
> + * The purpose of this seddery is to allow the resulting file to be
> + * freely included by software which might also want to include other
> + * list macros, and to be used when struct tags are not being used or
> + * not known.
> + */
> +END
> +}
> +
> +s/\b( _SYS_QUEUE |
> + SLIST | LIST | STAILQ | TAILQ | QUEUE
> + )/${ucnamespace}_$1/xg;
> +
> +s/\b( TRACEBUF | TRASHIT |
> + QMD_
> + )/${ucnamespace}__$1/xg;
> +
> +s/\b(
> + qm_
> + )/${namespace}__$1/xg;
> +
> +s/\b struct \s+ type \b/type/xg;
> diff --git a/tools/libxl/bsd-sys-queue.h b/tools/libxl/bsd-sys-queue.h
> new file mode 100644
> index 0000000..274e636
> --- /dev/null
> +++ b/tools/libxl/bsd-sys-queue.h
> @@ -0,0 +1,637 @@
> +/*-
> + * Copyright (c) 1991, 1993
> + * The Regents of the University of California. All rights reserved.
> + *
> + * Redistribution and use in source and binary forms, with or without
> + * modification, are permitted provided that the following conditions
> + * are met:
> + * 1. Redistributions of source code must retain the above copyright
> + * notice, this list of conditions and the following disclaimer.
> + * 2. Redistributions in binary form must reproduce the above copyright
> + * notice, this list of conditions and the following disclaimer in the
> + * documentation and/or other materials provided with the distribution.
> + * 4. Neither the name of the University nor the names of its contributors
> + * may be used to endorse or promote products derived from this software
> + * without specific prior written permission.
> + *
> + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
> + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
> + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
> + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
> + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
> + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
> + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
> + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
> + * SUCH DAMAGE.
> + *
> + * @(#)queue.h 8.5 (Berkeley) 8/20/94
> + * $FreeBSD$
> + */
> +
> +#ifndef _SYS_QUEUE_H_
> +#define _SYS_QUEUE_H_
> +
> +#include <sys/cdefs.h>
> +
> +/*
> + * This file defines four types of data structures: singly-linked lists,
> + * singly-linked tail queues, lists and tail queues.
> + *
> + * A singly-linked list is headed by a single forward pointer. The elements
> + * are singly linked for minimum space and pointer manipulation overhead at
> + * the expense of O(n) removal for arbitrary elements. New elements can be
> + * added to the list after an existing element or at the head of the list.
> + * Elements being removed from the head of the list should use the explicit
> + * macro for this purpose for optimum efficiency. A singly-linked list may
> + * only be traversed in the forward direction. Singly-linked lists are ideal
> + * for applications with large datasets and few or no removals or for
> + * implementing a LIFO queue.
> + *
> + * A singly-linked tail queue is headed by a pair of pointers, one to the
> + * head of the list and the other to the tail of the list. The elements are
> + * singly linked for minimum space and pointer manipulation overhead at the
> + * expense of O(n) removal for arbitrary elements. New elements can be added
> + * to the list after an existing element, at the head of the list, or at the
> + * end of the list. Elements being removed from the head of the tail queue
> + * should use the explicit macro for this purpose for optimum efficiency.
> + * A singly-linked tail queue may only be traversed in the forward direction.
> + * Singly-linked tail queues are ideal for applications with large datasets
> + * and few or no removals or for implementing a FIFO queue.
> + *
> + * A list is headed by a single forward pointer (or an array of forward
> + * pointers for a hash table header). The elements are doubly linked
> + * so that an arbitrary element can be removed without a need to
> + * traverse the list. New elements can be added to the list before
> + * or after an existing element or at the head of the list. A list
> + * may only be traversed in the forward direction.
> + *
> + * A tail queue is headed by a pair of pointers, one to the head of the
> + * list and the other to the tail of the list. The elements are doubly
> + * linked so that an arbitrary element can be removed without a need to
> + * traverse the list. New elements can be added to the list before or
> + * after an existing element, at the head of the list, or at the end of
> + * the list. A tail queue may be traversed in either direction.
> + *
> + * For details on the use of these macros, see the queue(3) manual page.
> + *
> + *
> + * SLIST LIST STAILQ TAILQ
> + * _HEAD + + + +
> + * _HEAD_INITIALIZER + + + +
> + * _ENTRY + + + +
> + * _INIT + + + +
> + * _EMPTY + + + +
> + * _FIRST + + + +
> + * _NEXT + + + +
> + * _PREV - - - +
> + * _LAST - - + +
> + * _FOREACH + + + +
> + * _FOREACH_SAFE + + + +
> + * _FOREACH_REVERSE - - - +
> + * _FOREACH_REVERSE_SAFE - - - +
> + * _INSERT_HEAD + + + +
> + * _INSERT_BEFORE - + - +
> + * _INSERT_AFTER + + + +
> + * _INSERT_TAIL - - + +
> + * _CONCAT - - + +
> + * _REMOVE_AFTER + - + -
> + * _REMOVE_HEAD + - + -
> + * _REMOVE + + + +
> + * _SWAP + + + +
> + *
> + */
> +#ifdef QUEUE_MACRO_DEBUG
> +/* Store the last 2 places the queue element or head was altered */
> +struct qm_trace {
> + char * lastfile;
> + int lastline;
> + char * prevfile;
> + int prevline;
> +};
> +
> +#define TRACEBUF struct qm_trace trace;
> +#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
> +#define QMD_SAVELINK(name, link) void **name = (void *)&(link)
> +
> +#define QMD_TRACE_HEAD(head) do {
> \
> + (head)->trace.prevline = (head)->trace.lastline; \
> + (head)->trace.prevfile = (head)->trace.lastfile; \
> + (head)->trace.lastline = __LINE__; \
> + (head)->trace.lastfile = __FILE__; \
> +} while (0)
> +
> +#define QMD_TRACE_ELEM(elem) do {
> \
> + (elem)->trace.prevline = (elem)->trace.lastline; \
> + (elem)->trace.prevfile = (elem)->trace.lastfile; \
> + (elem)->trace.lastline = __LINE__; \
> + (elem)->trace.lastfile = __FILE__; \
> +} while (0)
> +
> +#else
> +#define QMD_TRACE_ELEM(elem)
> +#define QMD_TRACE_HEAD(head)
> +#define QMD_SAVELINK(name, link)
> +#define TRACEBUF
> +#define TRASHIT(x)
> +#endif /* QUEUE_MACRO_DEBUG */
> +
> +/*
> + * Singly-linked List declarations.
> + */
> +#define SLIST_HEAD(name, type)
> \
> +struct name { \
> + struct type *slh_first; /* first element */ \
> +}
> +
> +#define SLIST_HEAD_INITIALIZER(head)
> \
> + { NULL }
> +
> +#define SLIST_ENTRY(type)
> \
> +struct { \
> + struct type *sle_next; /* next element */ \
> +}
> +
> +/*
> + * Singly-linked List functions.
> + */
> +#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
> +
> +#define SLIST_FIRST(head) ((head)->slh_first)
> +
> +#define SLIST_FOREACH(var, head, field)
> \
> + for ((var) = SLIST_FIRST((head)); \
> + (var); \
> + (var) = SLIST_NEXT((var), field))
> +
> +#define SLIST_FOREACH_SAFE(var, head, field, tvar)
> \
> + for ((var) = SLIST_FIRST((head)); \
> + (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
> + (var) = (tvar))
> +
> +#define SLIST_FOREACH_PREVPTR(var, varp, head, field)
> \
> + for ((varp) = &SLIST_FIRST((head)); \
> + ((var) = *(varp)) != NULL; \
> + (varp) = &SLIST_NEXT((var), field))
> +
> +#define SLIST_INIT(head) do {
> \
> + SLIST_FIRST((head)) = NULL; \
> +} while (0)
> +
> +#define SLIST_INSERT_AFTER(slistelm, elm, field) do {
> \
> + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
> + SLIST_NEXT((slistelm), field) = (elm); \
> +} while (0)
> +
> +#define SLIST_INSERT_HEAD(head, elm, field) do {
> \
> + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
> + SLIST_FIRST((head)) = (elm); \
> +} while (0)
> +
> +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
> +
> +#define SLIST_REMOVE(head, elm, type, field) do {
> \
> + QMD_SAVELINK(oldnext, (elm)->field.sle_next); \
> + if (SLIST_FIRST((head)) == (elm)) { \
> + SLIST_REMOVE_HEAD((head), field); \
> + } \
> + else { \
> + struct type *curelm = SLIST_FIRST((head)); \
> + while (SLIST_NEXT(curelm, field) != (elm)) \
> + curelm = SLIST_NEXT(curelm, field); \
> + SLIST_REMOVE_AFTER(curelm, field); \
> + } \
> + TRASHIT(*oldnext); \
> +} while (0)
> +
> +#define SLIST_REMOVE_AFTER(elm, field) do { \
> + SLIST_NEXT(elm, field) = \
> + SLIST_NEXT(SLIST_NEXT(elm, field), field); \
> +} while (0)
> +
> +#define SLIST_REMOVE_HEAD(head, field) do {
> \
> + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
> +} while (0)
> +
> +#define SLIST_SWAP(head1, head2, type) do { \
> + struct type *swap_first = SLIST_FIRST(head1); \
> + SLIST_FIRST(head1) = SLIST_FIRST(head2); \
> + SLIST_FIRST(head2) = swap_first; \
> +} while (0)
> +
> +/*
> + * Singly-linked Tail queue declarations.
> + */
> +#define STAILQ_HEAD(name, type)
> \
> +struct name { \
> + struct type *stqh_first;/* first element */ \
> + struct type **stqh_last;/* addr of last next element */ \
> +}
> +
> +#define STAILQ_HEAD_INITIALIZER(head)
> \
> + { NULL, &(head).stqh_first }
> +
> +#define STAILQ_ENTRY(type)
> \
> +struct { \
> + struct type *stqe_next; /* next element */ \
> +}
> +
> +/*
> + * Singly-linked Tail queue functions.
> + */
> +#define STAILQ_CONCAT(head1, head2) do {
> \
> + if (!STAILQ_EMPTY((head2))) { \
> + *(head1)->stqh_last = (head2)->stqh_first; \
> + (head1)->stqh_last = (head2)->stqh_last; \
> + STAILQ_INIT((head2)); \
> + } \
> +} while (0)
> +
> +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
> +
> +#define STAILQ_FIRST(head) ((head)->stqh_first)
> +
> +#define STAILQ_FOREACH(var, head, field)
> \
> + for((var) = STAILQ_FIRST((head)); \
> + (var); \
> + (var) = STAILQ_NEXT((var), field))
> +
> +
> +#define STAILQ_FOREACH_SAFE(var, head, field, tvar)
> \
> + for ((var) = STAILQ_FIRST((head)); \
> + (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
> + (var) = (tvar))
> +
> +#define STAILQ_INIT(head) do {
> \
> + STAILQ_FIRST((head)) = NULL; \
> + (head)->stqh_last = &STAILQ_FIRST((head)); \
> +} while (0)
> +
> +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {
> \
> + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) ==
> NULL)\
> + (head)->stqh_last = &STAILQ_NEXT((elm), field); \
> + STAILQ_NEXT((tqelm), field) = (elm); \
> +} while (0)
> +
> +#define STAILQ_INSERT_HEAD(head, elm, field) do {
> \
> + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
> + (head)->stqh_last = &STAILQ_NEXT((elm), field); \
> + STAILQ_FIRST((head)) = (elm); \
> +} while (0)
> +
> +#define STAILQ_INSERT_TAIL(head, elm, field) do {
> \
> + STAILQ_NEXT((elm), field) = NULL; \
> + *(head)->stqh_last = (elm); \
> + (head)->stqh_last = &STAILQ_NEXT((elm), field); \
> +} while (0)
> +
> +#define STAILQ_LAST(head, type, field)
> \
> + (STAILQ_EMPTY((head)) ? \
> + NULL : \
> + ((struct type *)(void *) \
> + ((char *)((head)->stqh_last) - __offsetof(struct type,
> field))))
> +
> +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
> +
> +#define STAILQ_REMOVE(head, elm, type, field) do {
> \
> + QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \
> + if (STAILQ_FIRST((head)) == (elm)) { \
> + STAILQ_REMOVE_HEAD((head), field); \
> + } \
> + else { \
> + struct type *curelm = STAILQ_FIRST((head)); \
> + while (STAILQ_NEXT(curelm, field) != (elm)) \
> + curelm = STAILQ_NEXT(curelm, field); \
> + STAILQ_REMOVE_AFTER(head, curelm, field); \
> + } \
> + TRASHIT(*oldnext); \
> +} while (0)
> +
> +#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
> + if ((STAILQ_NEXT(elm, field) = \
> + STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
> + (head)->stqh_last = &STAILQ_NEXT((elm), field); \
> +} while (0)
> +
> +#define STAILQ_REMOVE_HEAD(head, field) do {
> \
> + if ((STAILQ_FIRST((head)) = \
> + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
> + (head)->stqh_last = &STAILQ_FIRST((head)); \
> +} while (0)
> +
> +#define STAILQ_SWAP(head1, head2, type) do { \
> + struct type *swap_first = STAILQ_FIRST(head1); \
> + struct type **swap_last = (head1)->stqh_last; \
> + STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
> + (head1)->stqh_last = (head2)->stqh_last; \
> + STAILQ_FIRST(head2) = swap_first; \
> + (head2)->stqh_last = swap_last; \
> + if (STAILQ_EMPTY(head1)) \
> + (head1)->stqh_last = &STAILQ_FIRST(head1); \
> + if (STAILQ_EMPTY(head2)) \
> + (head2)->stqh_last = &STAILQ_FIRST(head2); \
> +} while (0)
> +
> +
> +/*
> + * List declarations.
> + */
> +#define LIST_HEAD(name, type)
> \
> +struct name { \
> + struct type *lh_first; /* first element */ \
> +}
> +
> +#define LIST_HEAD_INITIALIZER(head)
> \
> + { NULL }
> +
> +#define LIST_ENTRY(type)
> \
> +struct { \
> + struct type *le_next; /* next element */ \
> + struct type **le_prev; /* address of previous next element */ \
> +}
> +
> +/*
> + * List functions.
> + */
> +
> +#if (defined(_KERNEL) && defined(INVARIANTS))
> +#define QMD_LIST_CHECK_HEAD(head, field) do {
> \
> + if (LIST_FIRST((head)) != NULL && \
> + LIST_FIRST((head))->field.le_prev != \
> + &LIST_FIRST((head))) \
> + panic("Bad list head %p first->prev != head", (head)); \
> +} while (0)
> +
> +#define QMD_LIST_CHECK_NEXT(elm, field) do {
> \
> + if (LIST_NEXT((elm), field) != NULL && \
> + LIST_NEXT((elm), field)->field.le_prev != \
> + &((elm)->field.le_next)) \
> + panic("Bad link elm %p next->prev != elm", (elm)); \
> +} while (0)
> +
> +#define QMD_LIST_CHECK_PREV(elm, field) do {
> \
> + if (*(elm)->field.le_prev != (elm)) \
> + panic("Bad link elm %p prev->next != elm", (elm)); \
> +} while (0)
> +#else
> +#define QMD_LIST_CHECK_HEAD(head, field)
> +#define QMD_LIST_CHECK_NEXT(elm, field)
> +#define QMD_LIST_CHECK_PREV(elm, field)
> +#endif /* (_KERNEL && INVARIANTS) */
> +
> +#define LIST_EMPTY(head) ((head)->lh_first == NULL)
> +
> +#define LIST_FIRST(head) ((head)->lh_first)
> +
> +#define LIST_FOREACH(var, head, field)
> \
> + for ((var) = LIST_FIRST((head)); \
> + (var); \
> + (var) = LIST_NEXT((var), field))
> +
> +#define LIST_FOREACH_SAFE(var, head, field, tvar)
> \
> + for ((var) = LIST_FIRST((head)); \
> + (var) && ((tvar) = LIST_NEXT((var), field), 1); \
> + (var) = (tvar))
> +
> +#define LIST_INIT(head) do {
> \
> + LIST_FIRST((head)) = NULL; \
> +} while (0)
> +
> +#define LIST_INSERT_AFTER(listelm, elm, field) do {
> \
> + QMD_LIST_CHECK_NEXT(listelm, field); \
> + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
> + LIST_NEXT((listelm), field)->field.le_prev = \
> + &LIST_NEXT((elm), field); \
> + LIST_NEXT((listelm), field) = (elm); \
> + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \
> +} while (0)
> +
> +#define LIST_INSERT_BEFORE(listelm, elm, field) do {
> \
> + QMD_LIST_CHECK_PREV(listelm, field); \
> + (elm)->field.le_prev = (listelm)->field.le_prev; \
> + LIST_NEXT((elm), field) = (listelm); \
> + *(listelm)->field.le_prev = (elm); \
> + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \
> +} while (0)
> +
> +#define LIST_INSERT_HEAD(head, elm, field) do {
> \
> + QMD_LIST_CHECK_HEAD((head), field); \
> + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \
> + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
> + LIST_FIRST((head)) = (elm); \
> + (elm)->field.le_prev = &LIST_FIRST((head)); \
> +} while (0)
> +
> +#define LIST_NEXT(elm, field) ((elm)->field.le_next)
> +
> +#define LIST_REMOVE(elm, field) do {
> \
> + QMD_SAVELINK(oldnext, (elm)->field.le_next); \
> + QMD_SAVELINK(oldprev, (elm)->field.le_prev); \
> + QMD_LIST_CHECK_NEXT(elm, field); \
> + QMD_LIST_CHECK_PREV(elm, field); \
> + if (LIST_NEXT((elm), field) != NULL) \
> + LIST_NEXT((elm), field)->field.le_prev = \
> + (elm)->field.le_prev; \
> + *(elm)->field.le_prev = LIST_NEXT((elm), field); \
> + TRASHIT(*oldnext); \
> + TRASHIT(*oldprev); \
> +} while (0)
> +
> +#define LIST_SWAP(head1, head2, type, field) do { \
> + struct type *swap_tmp = LIST_FIRST((head1)); \
> + LIST_FIRST((head1)) = LIST_FIRST((head2)); \
> + LIST_FIRST((head2)) = swap_tmp; \
> + if ((swap_tmp = LIST_FIRST((head1))) != NULL) \
> + swap_tmp->field.le_prev = &LIST_FIRST((head1)); \
> + if ((swap_tmp = LIST_FIRST((head2))) != NULL) \
> + swap_tmp->field.le_prev = &LIST_FIRST((head2)); \
> +} while (0)
> +
> +/*
> + * Tail queue declarations.
> + */
> +#define TAILQ_HEAD(name, type)
> \
> +struct name { \
> + struct type *tqh_first; /* first element */ \
> + struct type **tqh_last; /* addr of last next element */ \
> + TRACEBUF \
> +}
> +
> +#define TAILQ_HEAD_INITIALIZER(head)
> \
> + { NULL, &(head).tqh_first }
> +
> +#define TAILQ_ENTRY(type)
> \
> +struct { \
> + struct type *tqe_next; /* next element */ \
> + struct type **tqe_prev; /* address of previous next element */ \
> + TRACEBUF \
> +}
> +
> +/*
> + * Tail queue functions.
> + */
> +#if (defined(_KERNEL) && defined(INVARIANTS))
> +#define QMD_TAILQ_CHECK_HEAD(head, field) do {
> \
> + if (!TAILQ_EMPTY(head) && \
> + TAILQ_FIRST((head))->field.tqe_prev != \
> + &TAILQ_FIRST((head))) \
> + panic("Bad tailq head %p first->prev != head", (head)); \
> +} while (0)
> +
> +#define QMD_TAILQ_CHECK_TAIL(head, field) do {
> \
> + if (*(head)->tqh_last != NULL) \
> + panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
> +} while (0)
> +
> +#define QMD_TAILQ_CHECK_NEXT(elm, field) do {
> \
> + if (TAILQ_NEXT((elm), field) != NULL && \
> + TAILQ_NEXT((elm), field)->field.tqe_prev != \
> + &((elm)->field.tqe_next)) \
> + panic("Bad link elm %p next->prev != elm", (elm)); \
> +} while (0)
> +
> +#define QMD_TAILQ_CHECK_PREV(elm, field) do {
> \
> + if (*(elm)->field.tqe_prev != (elm)) \
> + panic("Bad link elm %p prev->next != elm", (elm)); \
> +} while (0)
> +#else
> +#define QMD_TAILQ_CHECK_HEAD(head, field)
> +#define QMD_TAILQ_CHECK_TAIL(head, headname)
> +#define QMD_TAILQ_CHECK_NEXT(elm, field)
> +#define QMD_TAILQ_CHECK_PREV(elm, field)
> +#endif /* (_KERNEL && INVARIANTS) */
> +
> +#define TAILQ_CONCAT(head1, head2, field) do {
> \
> + if (!TAILQ_EMPTY(head2)) { \
> + *(head1)->tqh_last = (head2)->tqh_first; \
> + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
> + (head1)->tqh_last = (head2)->tqh_last; \
> + TAILQ_INIT((head2)); \
> + QMD_TRACE_HEAD(head1); \
> + QMD_TRACE_HEAD(head2); \
> + } \
> +} while (0)
> +
> +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
> +
> +#define TAILQ_FIRST(head) ((head)->tqh_first)
> +
> +#define TAILQ_FOREACH(var, head, field)
> \
> + for ((var) = TAILQ_FIRST((head)); \
> + (var); \
> + (var) = TAILQ_NEXT((var), field))
> +
> +#define TAILQ_FOREACH_SAFE(var, head, field, tvar)
> \
> + for ((var) = TAILQ_FIRST((head)); \
> + (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
> + (var) = (tvar))
> +
> +#define TAILQ_FOREACH_REVERSE(var, head, headname, field)
> \
> + for ((var) = TAILQ_LAST((head), headname); \
> + (var); \
> + (var) = TAILQ_PREV((var), headname, field))
> +
> +#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)
> \
> + for ((var) = TAILQ_LAST((head), headname); \
> + (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
> + (var) = (tvar))
> +
> +#define TAILQ_INIT(head) do {
> \
> + TAILQ_FIRST((head)) = NULL; \
> + (head)->tqh_last = &TAILQ_FIRST((head)); \
> + QMD_TRACE_HEAD(head); \
> +} while (0)
> +
> +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {
> \
> + QMD_TAILQ_CHECK_NEXT(listelm, field); \
> + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) !=
> NULL)\
> + TAILQ_NEXT((elm), field)->field.tqe_prev = \
> + &TAILQ_NEXT((elm), field); \
> + else { \
> + (head)->tqh_last = &TAILQ_NEXT((elm), field); \
> + QMD_TRACE_HEAD(head); \
> + } \
> + TAILQ_NEXT((listelm), field) = (elm); \
> + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
> + QMD_TRACE_ELEM(&(elm)->field); \
> + QMD_TRACE_ELEM(&listelm->field); \
> +} while (0)
> +
> +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do {
> \
> + QMD_TAILQ_CHECK_PREV(listelm, field); \
> + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
> + TAILQ_NEXT((elm), field) = (listelm); \
> + *(listelm)->field.tqe_prev = (elm); \
> + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
> + QMD_TRACE_ELEM(&(elm)->field); \
> + QMD_TRACE_ELEM(&listelm->field); \
> +} while (0)
> +
> +#define TAILQ_INSERT_HEAD(head, elm, field) do {
> \
> + QMD_TAILQ_CHECK_HEAD(head, field); \
> + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
> + TAILQ_FIRST((head))->field.tqe_prev = \
> + &TAILQ_NEXT((elm), field); \
> + else \
> + (head)->tqh_last = &TAILQ_NEXT((elm), field); \
> + TAILQ_FIRST((head)) = (elm); \
> + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
> + QMD_TRACE_HEAD(head); \
> + QMD_TRACE_ELEM(&(elm)->field); \
> +} while (0)
> +
> +#define TAILQ_INSERT_TAIL(head, elm, field) do {
> \
> + QMD_TAILQ_CHECK_TAIL(head, field); \
> + TAILQ_NEXT((elm), field) = NULL; \
> + (elm)->field.tqe_prev = (head)->tqh_last; \
> + *(head)->tqh_last = (elm); \
> + (head)->tqh_last = &TAILQ_NEXT((elm), field); \
> + QMD_TRACE_HEAD(head); \
> + QMD_TRACE_ELEM(&(elm)->field); \
> +} while (0)
> +
> +#define TAILQ_LAST(head, headname)
> \
> + (*(((struct headname *)((head)->tqh_last))->tqh_last))
> +
> +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
> +
> +#define TAILQ_PREV(elm, headname, field)
> \
> + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
> +
> +#define TAILQ_REMOVE(head, elm, field) do {
> \
> + QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \
> + QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \
> + QMD_TAILQ_CHECK_NEXT(elm, field); \
> + QMD_TAILQ_CHECK_PREV(elm, field); \
> + if ((TAILQ_NEXT((elm), field)) != NULL) \
> + TAILQ_NEXT((elm), field)->field.tqe_prev = \
> + (elm)->field.tqe_prev; \
> + else { \
> + (head)->tqh_last = (elm)->field.tqe_prev; \
> + QMD_TRACE_HEAD(head); \
> + } \
> + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
> + TRASHIT(*oldnext); \
> + TRASHIT(*oldprev); \
> + QMD_TRACE_ELEM(&(elm)->field); \
> +} while (0)
> +
> +#define TAILQ_SWAP(head1, head2, type, field) do { \
> + struct type *swap_first = (head1)->tqh_first; \
> + struct type **swap_last = (head1)->tqh_last; \
> + (head1)->tqh_first = (head2)->tqh_first; \
> + (head1)->tqh_last = (head2)->tqh_last; \
> + (head2)->tqh_first = swap_first; \
> + (head2)->tqh_last = swap_last; \
> + if ((swap_first = (head1)->tqh_first) != NULL) \
> + swap_first->field.tqe_prev = &(head1)->tqh_first; \
> + else \
> + (head1)->tqh_last = &(head1)->tqh_first; \
> + if ((swap_first = (head2)->tqh_first) != NULL) \
> + swap_first->field.tqe_prev = &(head2)->tqh_first; \
> + else \
> + (head2)->tqh_last = &(head2)->tqh_first; \
> +} while (0)
> +
> +#endif /* !_SYS_QUEUE_H_ */
> --
> tg: (92a50a8..) t/xen/bsd-queue (depends on: t/xen/gitignore)
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxxxxxxxx
> http://lists.xensource.com/xen-devel
>
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|