LIST_CREATE(9F)         Kernel Functions for Drivers         LIST_CREATE(9F)
NAME
     list_create, 
list_destroy, 
list_insert_after, 
list_insert_before,     
list_insert_head, 
list_insert_tail, 
list_remove, 
list_remove_head,     
list_remove_tail, 
list_head, 
list_tail, 
list_next, 
list_prev,     
list_is_empty,, 
list_link_init, 
list_link_active, 
list_move_tail,     
list_link_replace - list functions
SYNOPSIS
     #include <sys/list.h>     void     list_create(
list_t *list, 
size_t size, 
size_t offset);     
void     list_destroy(
list_t *list);     
void     list_insert_after(
list_t *list, 
void *reference_item, 
void *new_item);     
void     list_insert_before(
list_t *list, 
void *reference_item, 
void *new_item);     
void     list_insert_head(
list_t *list*, 
void *new_item);     
void     list_insert_tail(
list_t *list, 
void *new_item);     
void     list_remove(
list_t *list, 
void *item);     
void *     list_remove_head(
list_t *list);     
void *     list_remove_tail(
list_t *list);     
void *     list_head(
list_t *list);     
void *     list_tail(
list_t *list);     
void *     list_next(
list_t *list, 
void *reference_item);     
void *     list_prev(
list_t *list, 
void *reference_item);     
int     list_is_empty(
list_t *list);     
void     list_link_init(
list_node_t *node);     
int     list_link_active(
list_node_t *node);     
void     list_move_tail(
list_t *dst, 
list_t *src);     
void     list_link_replace(
list_node_t *lold, 
list_node_t *lnew);
DESCRIPTION
     These functions provide a generic doubly-linked list implementation.
     To utilize it, simply embed a 
list_node_t field in the structures that
     will constitute the linked list elements and pass the 
list_node_t field
     offset to 
list_create() in the appropriate parameter (see below).  A
     single 
list_node_t field can only be used in a single list
     simultaneously, so to add a structure to multiple lists, embed multiple     
list_node_t fields in your user structure.
     Please note that a 
list_node_t contains pointers back to its parent     
list_t so you cannot copy the 
list_t around once it has been
     initialized.  In particular, this kind of construct will not work:
           struct { list_t l; } a, b;
           list_create(&a.l, ...);
           b = a;    <= This will break the list in `b', as the `l' element
                        in `a' got copied to a different memory address.
     To do this you must move the list items to the new list using functions
     such as 
list_move_tail().
     The 
list_create() function initializes a new list.  The driver supplies
     the storage for the list handle, the size of an individual element, and
     the offset of a 
list_node_t within the element to use for the links of
     the list.
     The 
list_destroy() function destroys the list handle, including freeing
     any resources that may have been internally allocated for the list.
     The list must be empty when this function is called.
     The 
list_insert_after() and 
list_insert_before() functions insert     
new_item into the linked list at a location after or before the
     reference item, which must already be on the list.
     The 
list_insert_head() and 
list_insert_tail() functions insert the     
new_item on the list at either the head or tail of the list.  The head
     is the first item, the tail is the last item.
     The 
list_remove() function removes the item from the list.
     The 
list_remove_head() and 
list_remove_tail() functions remove the head
     (first) or tail (last) item from the list.  The item removed is
     returned to the caller.  If the list is empty when these functions are
     called, then no change is made and NULL is returned to the caller.
     The 
list_head() and 
list_tail() functions simply return the head
     (first) or tail (last) item on the list.  NULL is returned if the list
     is empty.
     The 
list_next() and 
list_prev() functions return the next or previous
     item in the list, relative to the named reference item which must be
     linked on the list.  If the referenced item is either the last entry in
     the list for 
list_next() or the first entry in the list for     
list_prev(), then the functions will return NULL.  This is useful for
     iterating over a list with the following pattern:
           list_t list_t;
           ...
           for (foo_t *foo = list_head(&list_t); foo != NULL;
               foo = list_next(&list_t, foo)) {
                   /* Process each entry of the list */
           }
           for (foo_t *foo = list_tail(&list_t); foo != NULL;
               foo = list_prev(&list_t, foo)) {
                   /* Same thing, but in reverse */
           }
     The 
list_is_empty() function returns 0 if the list has items in it, or
     non-zero otherwise.
     The 
list_link_init() function initializes the 
list_node_t.  It is
     functionally equivalent to 
bzero(
node, 
sizeof (*node));.
     The 
list_link_active() function returns non-zero if the node is on an
     active list.
     The 
list_move_tail() function is used to append the items on the 
src     list to the end of the 
dst list.  It is mandatory that the two lists
     were initialized using identical size and offset parameters.  Upon
     completion, the 
src list will be empty.
     The 
list_link_replace() function replaces 
lold node on an active list
     with the 
lnew node.  When the function is called the 
lnew node must not
     be linked on any list.  Upon completion the 
lold node will be left
     unlinked from any list.
INTERFACE STABILITY
     Committedillumos                       January 16, 2022                       illumos