| LIST_CREATE(9F) | Kernel Functions for Drivers | LIST_CREATE(9F) | 
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
#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);
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.
| January 16, 2022 | OmniOS |