From 295ba15bd670038e1f22d3c72151036337298a1c Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 5 Nov 2010 23:49:12 +0000 Subject: [PATCH] [list] Extend list-manipulation assertions to all list-handling functions Signed-off-by: Michael Brown --- src/include/ipxe/list.h | 180 +++++++++++++++++++++------------------- 1 file changed, 95 insertions(+), 85 deletions(-) diff --git a/src/include/ipxe/list.h b/src/include/ipxe/list.h index a40fb681..fb00bc53 100644 --- a/src/include/ipxe/list.h +++ b/src/include/ipxe/list.h @@ -14,35 +14,58 @@ FILE_LICENCE ( GPL2_ONLY ); #include #include -/* - * Simple doubly linked list implementation. - * - * 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. - */ - +/** A doubly-linked list entry (or list head) */ struct list_head { + /** Next list entry */ struct list_head *next; + /** Previous list entry */ struct list_head *prev; }; -#define LIST_HEAD_INIT( name ) { &(name), &(name) } - -#define LIST_HEAD( name ) \ - struct list_head name = LIST_HEAD_INIT ( name ) - -#define INIT_LIST_HEAD( ptr ) do { \ - (ptr)->next = (ptr); (ptr)->prev = (ptr); \ -} while ( 0 ) - -/* - * Insert a new entry between two known consecutive entries. +/** + * Initialise a static list head * - * This is only for internal list manipulation where we know - * the prev/next entries already! + * @v list List head + */ +#define LIST_HEAD_INIT( list ) { &(list), &(list) } + +/** + * Declare a static list head + * + * @v list List head + */ +#define LIST_HEAD( list ) \ + struct list_head list = LIST_HEAD_INIT ( list ) + +/** + * Initialise a list head + * + * @v list List head + */ +#define INIT_LIST_HEAD( list ) do { \ + (list)->next = (list); \ + (list)->prev = (list); \ + } while ( 0 ) + +/** + * Check a list entry or list head is valid + * + * @v list List entry or head + */ +#define list_check( list ) ( { \ + assert ( (list) != NULL ); \ + assert ( (list)->prev != NULL ); \ + assert ( (list)->next != NULL ); \ + assert ( (list)->next->prev == (list) ); \ + assert ( (list)->prev->next == (list) ); \ + } ) + +/** + * Insert a list entry between two known consecutive entries + * + * @v new New list entry + * @v prev Previous list entry + * @v next Next list entry */ static inline void __list_add ( struct list_head *new, struct list_head *prev, @@ -56,49 +79,40 @@ static inline void __list_add ( struct list_head *new, /** * Add a new entry to the head of a list * - * @v new New entry to be added - * @v head List head to add it after - * - * Insert a new entry after the specified head. This is good for - * implementing stacks. + * @v new New entry to be added + * @v head List head, or entry after which to add the new entry */ static inline void list_add ( struct list_head *new, struct list_head *head ) { __list_add ( new, head, head->next ); } #define list_add( new, head ) do { \ - assert ( (head)->next->prev == (head) ); \ - assert ( (head)->prev->next == (head) ); \ + list_check ( (head) ); \ list_add ( (new), (head) ); \ } while ( 0 ) /** * Add a new entry to the tail of a list * - * @v new New entry to be added - * @v head List head to add it before - * - * Insert a new entry before the specified head. This is useful for - * implementing queues. + * @v new New entry to be added + * @v head List head, or entry before which to add the new entry */ static inline void list_add_tail ( struct list_head *new, struct list_head *head ) { __list_add ( new, head->prev, head ); } #define list_add_tail( new, head ) do { \ - assert ( (head)->next->prev == (head) ); \ - assert ( (head)->prev->next == (head) ); \ + list_check ( (head) ); \ list_add_tail ( (new), (head) ); \ } while ( 0 ) -/* - * Delete a list entry by making the prev/next entries - * point to each other. +/** + * Delete a list entry between two known consecutive entries * - * This is only for internal list manipulation where we know - * the prev/next entries already! + * @v prev Previous list entry + * @v next Next list entry */ -static inline void __list_del ( struct list_head * prev, - struct list_head * next ) { +static inline void __list_del ( struct list_head *prev, + struct list_head *next ) { next->prev = prev; prev->next = next; } @@ -106,84 +120,80 @@ static inline void __list_del ( struct list_head * prev, /** * Delete an entry from a list * - * @v entry Element to delete from the list + * @v list List entry * * Note that 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 ); +static inline void list_del ( struct list_head *list ) { + __list_del ( list->prev, list->next ); } -#define list_del( entry ) do { \ - assert ( (entry)->prev != NULL ); \ - assert ( (entry)->next != NULL ); \ - assert ( (entry)->next->prev == (entry) ); \ - assert ( (entry)->prev->next == (entry) ); \ - list_del ( (entry) ); \ +#define list_del( list ) do { \ + list_check ( (list) ); \ + list_del ( (list) ); \ } while ( 0 ) /** * Test whether a list is empty * - * @v head List to test. + * @v list List head */ -static inline int list_empty ( const struct list_head *head ) { - return head->next == head; +static inline int list_empty ( const struct list_head *list ) { + return ( list->next == list ); } +#define list_empty( list ) ( { \ + list_check ( (list) ); \ + list_empty ( (list) ); } ) /** - * Get the containing struct for this entry + * Get the container of a list entry * - * @v ptr The struct list_head pointer - * @v type The type of the struct this is embedded in - * @v member The name of the list_struct within the struct + * @v list List entry + * @v type Containing type + * @v member Name of list field within containing type + * @ret container Containing object */ -#define list_entry( ptr, type, member ) \ - container_of ( ptr, type, member ) - -/** - * Iterate over a list - * - * @v pos The &struct list_head to use as a loop counter - * @v head The head for your list - */ -#define list_for_each( pos, head ) \ - for ( pos = (head)->next; pos != (head); pos = pos->next ) +#define list_entry( list, type, member ) ( { \ + list_check ( (list) ); \ + container_of ( list, type, member ); } ) /** * Iterate over entries in a list * - * @v pos The type * to use as a loop counter - * @v head The head for your list - * @v member The name of the list_struct within the struct + * @v pos Iterator + * @v head List head + * @v member Name of list field within iterator's type */ #define list_for_each_entry( pos, head, member ) \ - for ( pos = list_entry ( (head)->next, typeof ( *pos ), member ); \ + for ( list_check ( (head) ), \ + pos = list_entry ( (head)->next, typeof ( *pos ), member ); \ &pos->member != (head); \ pos = list_entry ( pos->member.next, typeof ( *pos ), member ) ) /** * Iterate over entries in a list in reverse order * - * @v pos The type * to use as a loop counter - * @v head The head for your list - * @v member The name of the list_struct within the struct + * @v pos Iterator + * @v head List head + * @v member Name of list field within iterator's type */ #define list_for_each_entry_reverse( pos, head, member ) \ - for ( pos = list_entry ( (head)->prev, typeof ( *pos ), member ); \ + for ( list_check ( (head) ), \ + pos = list_entry ( (head)->prev, typeof ( *pos ), member ); \ &pos->member != (head); \ pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) ) /** - * Iterate over entries in a list, safe against deletion of entries + * Iterate over entries in a list, safe against deletion of the current entry * - * @v pos The type * to use as a loop counter - * @v tmp Another type * to use for temporary storage - * @v head The head for your list - * @v member The name of the list_struct within the struct + * @v pos Iterator + * @v tmp Temporary value (of same type as iterator) + * @v head List head + * @v member Name of list field within iterator's type */ #define list_for_each_entry_safe( pos, tmp, head, member ) \ - for ( pos = list_entry ( (head)->next, typeof ( *pos ), member ), \ + for ( list_check ( (head) ), \ + pos = list_entry ( (head)->next, typeof ( *pos ), member ), \ tmp = list_entry ( pos->member.next, typeof ( *tmp ), member ); \ &pos->member != (head); \ pos = tmp, \