List Heads
The previous section shows how easy it is to take an existing structure—such as our
struct fox example—and turn it into a linked list.With simple code changes, our struc-ture is now manageable by the kernel’s linked list routines. But before we can use those routines, we need a canonical pointer to refer to the list as a whole—a head pointer.
One nice aspect of the kernel’s linked list implementation is that our fox nodes are indistinguishable. Each contains a list_head, and we can iterate from any one node to the next, until we have seen every node.This approach is elegant, but you will generally want a special pointer that refers to your linked list, without being a list node itself. Inter-estingly, this special node is in fact a normal list_head:
static LIST_HEAD(fox_list);
This defines and initializes a list_head named fox_list.The majority of the linked list routines accept one or two parameters: the head node or the head node plus an actual list node. Let’s look at those routines.
Manipulating Linked Lists
The kernel provides a family of functions to manipulate linked lists.They all take point-ers to one or more list_head structures.The functions are implemented as inline func-tions in generic C and can be found in <linux/list.h>.
Interestingly, all these functions are O(1).1 This means they execute in constant time, regardless of the size of the list or any other inputs. For example, it takes the same amount of time to add or remove an entry to or from a list whether that list has 3 or 3,000 entries.This is perhaps not surprising, but still good to know.
Adding a Node to a Linked List To add a node to a linked list:
list_add(struct list_head *new, struct list_head *head)
1 See the section “Algorithmic Complexity,” later in this chapter, for a discussion on O(1).
ptg Linked Lists 91
This function adds the new node to the given list immediately after the head node.
Because the list is circular and generally has no concept of first or last nodes, you can pass any element for head. If you do pass the “last” element, however, this function can be used to implement a stack.
Returning to our fox example, assume we had a new struct fox that we wanted to add to the fox_list list.We’d do this:
list_add(&f->list, &fox_list);
To add a node to the end of a linked list:
list_add_tail(struct list_head *new, struct list_head *head)
This function adds the new node to the given list immediately before the head node. As with list_add(), because the lists are circular, you can generally pass any element for
head.This function can be used to implement a queue, however, if you pass the “first”
element.
Deleting a Node from a Linked List
After adding a node to a linked list, deleting a node from a list is the next most important operation.To delete a node from a linked list, use list_del():
list_del(struct list_head *entry)
This function removes the element entry from the list. Note that it does not free any memory belonging to entry or the data structure in which it is embedded; this function merely removes the element from the list. After calling this, you would typically destroy your data structure and the list_head inside it.
For example, to delete the fox node we previous added to fox_list:
list_del(&f->list);
Note the function does not receive as input fox_list. It simply receives a specific node and modifies the pointers of the previous and subsequent nodes such that the given node is no longer part of the list.The implementation is instructive:
static inline void __list_del(struct list_head *prev, struct list_head *next) {
next->prev = prev;
prev->next = next;
}
static inline void list_del(struct list_head *entry) {
__list_del(entry->prev, entry->next);
}
ptg To delete a node from a linked list and reinitialize it, the kernel provides
list_del_init():
list_del_init(struct list_head *entry)
This function behaves the same as list_del(), except it also reinitializes the given
list_head with the rationale that you no longer want the entry in the list, but you can reuse the data structure itself.
Moving and Splicing Linked List Nodes To move a node from one list to another
list_move(struct list_head *list, struct list_head *head)
This function removes the list entry from its linked list and adds it to the given list after the head element.
To move a node from one list to the end of another
list_move_tail(struct list_head *list, struct list_head *head)
This function does the same as list_move(), but inserts the list element before the
head entry.
To check whether a list is empty
list_empty(struct list_head *head)
This returns nonzero if the given list is empty; otherwise, it returns zero.
To splice two unconnected lists together
list_splice(struct list_head *list, struct list_head *head)
This function splices together two lists by inserting the list pointed to by list to the given list after the element head.
To splice two unconnected lists together and reinitialize the old list
list_splice_init(struct list_head *list, struct list_head *head)
This function works the same as list_splice(), except that the emptied list pointed to by list is reinitialized.
Saving a Couple Dereferences
If you happen to already have the next and prev pointers available, you can save a couple cycles (specifically, the dereferences to get the pointers) by calling the internal list functions directly. Every previously discussed function actually does nothing except find the next and prev pointers and then call the internal functions. The internal functions generally have the same name as their wrappers, except they are prefixed by double underscores. For exam-ple, rather than call list_del(list), you can call __list_del(prev, next). This is useful only if the next and previous pointers are already dereferenced. Otherwise, you are just writing ugly code. See the header <linux/list.h> for the exact interfaces.
ptg Linked Lists 93