mirror of
				https://github.com/xcat2/xNBA.git
				synced 2025-10-31 03:12:32 +00:00 
			
		
		
		
	[list] Extend list-manipulation assertions to all list-handling functions
Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
		| @@ -14,35 +14,58 @@ FILE_LICENCE ( GPL2_ONLY ); | ||||
| #include <stddef.h> | ||||
| #include <assert.h> | ||||
|  | ||||
| /* | ||||
|  * 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,						      \ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user