X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=list.h;h=66c6d91525031261ff94cd3028e672cb340c06cd;hp=db2e84908130676e22f346eedea116254786146d;hb=HEAD;hpb=7cd6e84f08240d3604ddb36ecd3c7b1ec6990446 diff --git a/list.h b/list.h index db2e8490..78c302fa 100644 --- a/list.h +++ b/list.h @@ -2,144 +2,103 @@ * Copied from the Linux kernel source tree, version 2.6.13. * * Licensed under the GPL v2 as per the whole kernel source tree. - * */ -/** \file list.h doubly linked list implementation */ +/** \file list.h Doubly linked list implementation. */ #include /* offsetof */ -/** get the struct this entry is embedded in */ +/** Get the struct this entry is embedded in. */ #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) -/** - * Non-NULL pointers that will result in page faults under normal - * circumstances, used to verify that nobody uses non-initialized list entries. - * Used for poisoning the \a next pointer of struct list_head. - */ -#define LIST_POISON1 ((void *) 0x00100100) -/** Non-null pointer, used for poisoning the \a prev pointer of struct - * list_head - */ -#define LIST_POISON2 ((void *) 0x00200200) - -/** Simple doubly linked list implementation. */ +/** A list head is just a pair of pointers. */ struct list_head { - /** pointer to the next list entry */ + /** Pointer to the next list entry. */ struct list_head *next; - /** pointer to the previous list entry */ + /** Pointer to the previous list entry. */ struct list_head *prev; }; /** Define an initialized list head. */ -#define LIST_HEAD(name) struct list_head name = { &(name), &(name) } - - -/** must be called before using any other list functions */ -#define INIT_LIST_HEAD(ptr) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while (0) - +#define INITIALIZED_LIST_HEAD(name) struct list_head name = {&(name), &(name)} -/* - * Some of the internal functions ("__xxx") are useful when - * manipulating whole lists rather than single entries, as - * sometimes we already know the next/prev entries and we can - * generate better code by using them directly rather than - * using the generic single-entry routines. - */ - - -/* - * Insert a new entry between two known consecutive entries. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_add(struct list_head *new, - struct list_head *prev, - struct list_head *next) +/** This must be called before using any other list functions. */ +static inline void init_list_head(struct list_head *head) { - next->prev = new; - new->next = next; - new->prev = prev; - prev->next = new; + head->next = head; + head->prev = head; } /** - * add a new entry + * Insert a new entry after the specified head. * - * \param new new entry to be added - * \param head list head to add it after + * \param entry The new entry to add. + * \param head The list head to add it after. * - * Insert a new entry after the specified head. * This is good for implementing stacks. */ -static inline void para_list_add(struct list_head *new, struct list_head *head) +static inline void para_list_add(struct list_head *entry, struct list_head *head) { - __list_add(new, head, head->next); + entry->prev = head; + entry->next = head->next; + head->next->prev = entry; + head->next = entry; } /** - * add a new entry + * Insert a new entry before the specified head. * - * \param new new entry to be added - * \param head list head to add it before + * \param entry The new entry to add. + * \param head list head to add it before. * - * Insert a new entry before the specified head. * This is useful for implementing queues. */ -static inline void list_add_tail(struct list_head *new, struct list_head *head) +static inline void list_add_tail(struct list_head *entry, struct list_head *head) { - __list_add(new, head->prev, head); -} - -/* - * Delete a list entry by making the prev/next entries - * point to each other. - * - * This is only for internal list manipulation where we know - * the prev/next entries already! - */ -static inline void __list_del(struct list_head * prev, struct list_head * next) -{ - next->prev = prev; - prev->next = next; + entry->prev = head->prev; + entry->next = head; + head->prev->next = entry; + head->prev = entry; } /** - * Delete entry from list. + * Delete an entry from a list. * - * \param entry the element to delete from the list. + * \param entry The element to delete. * - * Note: list_empty on entry does not return true after this, the entry is - * in an undefined state. + * The list entry is in an undefined state after this and \ref list_empty() + * does not return true. */ static inline void list_del(struct list_head *entry) { - __list_del(entry->prev, entry->next); - entry->next = LIST_POISON1; - entry->prev = LIST_POISON2; + entry->prev->next = entry->next; + entry->next->prev = entry->prev; + /* + * These non-NULL pointers result in page faults when dereferenced. + * This helps to catch bugs resulting from using deleted list heads. + */ + entry->next = (void *)0x00100100; + entry->prev = (void *)0x00200200; } /** - * delete from one list and add as another's head + * Delete an entry from one list and add it as another list's head. * - * \param list: the entry to move - * \param head: the head that will precede our entry + * \param entry The entry to move. + * \param head The head that will precede our entry. */ -static inline void list_move(struct list_head *list, struct list_head *head) +static inline void list_move(struct list_head *entry, struct list_head *head) { - __list_del(list->prev, list->next); - para_list_add(list, head); + list_del(entry); + para_list_add(entry, head); } /** - * test whether a list is empty + * Test whether a list contains no entries. * - * \param head the list to test. + * \param head The list to test. */ static inline int list_empty(const struct list_head *head) { @@ -147,32 +106,30 @@ static inline int list_empty(const struct list_head *head) } /** - * get the struct for this entry + * Test whether a list has just one entry. * - * \param ptr the &struct list_head pointer. - * \param type the type of the struct this is embedded in. - * \param member the name of the list_struct within the struct. + * \param head The list to test. */ -#define list_entry(ptr, type, member) \ - container_of(ptr, type, member) +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} /** - * iterate over a list safe against removal of list entry + * Get the struct in which this entry is embedded in. * - * \param pos the &struct list_head to use as a loop counter. - * \param n another &struct list_head to use as temporary storage - * \param head the head for your list. + * \param ptr The list head pointer. + * \param type The type of containing structure. + * \param member The name of the list head member within the structure. */ -#define list_for_each_safe(pos, n, head) \ - for (pos = (head)->next, n = pos->next; pos != (head); \ - pos = n, n = pos->next) +#define list_entry(ptr, type, member) container_of(ptr, type, member) /** - * iterate over list of given type + * Iterate over a list. * - * \param pos the type * to use as a loop counter. - * \param head the head for your list. - * \param member the name of the list_struct within the struct. + * \param pos A struct pointer which serves as the iterator. + * \param head The head of the list. + * \param member The name of the list head member within the structure. */ #define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ @@ -180,27 +137,27 @@ static inline int list_empty(const struct list_head *head) pos = list_entry(pos->member.next, typeof(*pos), member)) /** - * iterate over list of given type safe against removal of list entry + * Iterate over list, safe against removal of list entry. * - * \param pos the type * to use as a loop counter. - * \param n another type * to use as temporary storage - * \param head the head for your list. - * \param member the name of the list_struct within the struct. + * \param pos The iterator struct pointer. + * \param n A second struct pointer which is used as temporary storage. + * \param head The head of the list. + * \param member The name of the list head member within the structure. */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member), \ n = list_entry(pos->member.next, typeof(*pos), member); \ &pos->member != (head); \ pos = n, n = list_entry(n->member.next, typeof(*n), member)) + /** - * iterate backwards over list of given type safe against removal of list entry - * \param pos the type * to use as a loop counter. - * \param n another type * to use as temporary storage - * \param head the head for your list. - * \param member the name of the list_struct within the struct. + * Get the first element of a list. + * + * \param ptr The list head to take the element from. + * \param type The type of the struct this is embedded in. + * \param member The name of the list_struct within the struct. + * + * Note that the list is expected to be non-empty. */ -#define list_for_each_entry_safe_reverse(pos, n, head, member) \ - for (pos = list_entry((head)->prev, typeof(*pos), member), \ - n = list_entry(pos->member.prev, typeof(*pos), member); \ - &pos->member != (head); \ - pos = n, n = list_entry(n->member.prev, typeof(*n), member)) +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member)