Linux Kernel Architecture

(Jacob Rumans) #1
Mauerer app03.tex V1 - 09/04/2008 6:11pm Page 1211

Appendix C: Notes on C


* the prev/next entries already!
*/
static inline void __list_del(struct list_head * prev, struct list_head * next)
{
next->prev = prev;
prev->next = next;
}

/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is
* in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = LIST_POISON1;
entry->prev = LIST_POISON2;
}

The twoLIST_POISONvalues in thenextandprevpointers of the deleted entry are used for debugging
purposes in order to detect removed list elements in memory.


The most interesting aspects of list implementationare revealed by two questions: How is it possible to
iterate over the list elements, and how are entries removed from the list? In other words, how is their
data extracted, and how is the full structure that was saved — not only the list element — reconstructed?
Note this isnottalking aboutdeletingelements from the list.


The kernel provides the following macro to iterate over a list:


<list.h>
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop cursor.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeof(*pos), member); \
prefetch(pos->member.next), &pos->member != (head); \
pos = list_entry(pos->member.next, typeof(*pos), member))

All the preceding code resides in the loop head of theforloop. The body is not added until the macro
is used. The purpose of the list is to save, one after the other, pointers to all list elements of the
typeof(*pos)type inpos, and to make these available to the loop body.

A sample use of this routine is to iterate over all files (represented bystruct file) that are associated
with a superblock (struct super_block) and are therefore included in a doubly linked list starting at the
superblock, as shown here:


struct super_block *sb = get_some_sb();
struct file *f;
Free download pdf