david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

[list] Reduce overall code size by externalising many list functions

Typical saving is 10-20 bytes in each file using list functions.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
Michael Brown 2012-11-02 16:12:56 +00:00
parent f68b4069b1
commit 54a861a7bd
2 changed files with 215 additions and 122 deletions

84
src/core/list.c Normal file
View File

@ -0,0 +1,84 @@
/*
* Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
FILE_LICENCE ( GPL2_OR_LATER );
/** @file
*
* Linked lists
*
*/
#include <ipxe/list.h>
void extern_list_add ( struct list_head *new, struct list_head *head ) {
inline_list_add ( new, head );
}
void extern_list_add_tail ( struct list_head *new, struct list_head *head ) {
inline_list_add_tail ( new, head );
}
void extern_list_del ( struct list_head *list ) {
inline_list_del ( list );
}
int extern_list_empty ( const struct list_head *list ) {
return inline_list_empty ( list );
}
int extern_list_is_singular ( const struct list_head *list ) {
return inline_list_is_singular ( list );
}
int extern_list_is_last ( const struct list_head *list,
const struct list_head *head ) {
return inline_list_is_last ( list, head );
}
void extern_list_cut_position ( struct list_head *new,
struct list_head *list,
struct list_head *entry ) {
inline_list_cut_position ( new, list, entry );
}
void extern_list_splice ( const struct list_head *list,
struct list_head *entry ) {
inline_list_splice ( list, entry );
}
void extern_list_splice_tail ( const struct list_head *list,
struct list_head *entry ) {
inline_list_splice_tail ( list, entry );
}
void extern_list_splice_init ( struct list_head *list,
struct list_head *entry ) {
inline_list_splice_init ( list, entry );
}
void extern_list_splice_tail_init ( struct list_head *list,
struct list_head *entry ) {
inline_list_splice_tail_init ( list, entry );
}
int extern_list_contains ( struct list_head *entry,
struct list_head *head ) {
return inline_list_contains ( entry, head );
}

View File

@ -42,9 +42,9 @@ struct list_head {
* *
* @v list List head * @v list List head
*/ */
#define INIT_LIST_HEAD( list ) do { \ #define INIT_LIST_HEAD( list ) do { \
(list)->next = (list); \ (list)->next = (list); \
(list)->prev = (list); \ (list)->prev = (list); \
} while ( 0 ) } while ( 0 )
/** /**
@ -52,43 +52,35 @@ struct list_head {
* *
* @v list List entry or head * @v list List entry or head
*/ */
#define list_check( list ) ( { \ #define list_check( list ) ( { \
assert ( (list) != NULL ); \ assert ( (list) != NULL ); \
assert ( (list)->prev != NULL ); \ assert ( (list)->prev != NULL ); \
assert ( (list)->next != NULL ); \ assert ( (list)->next != NULL ); \
assert ( (list)->next->prev == (list) ); \ assert ( (list)->next->prev == (list) ); \
assert ( (list)->prev->next == (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,
struct list_head *next ) {
next->prev = new;
new->next = next;
new->prev = prev;
prev->next = new;
}
/** /**
* Add a new entry to the head of a list * Add a new entry to the head of a list
* *
* @v new New entry to be added * @v new New entry to be added
* @v head List head, or entry after which to add the new entry * @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 ) { #define list_add( new, head ) do { \
__list_add ( new, head, head->next ); list_check ( (head) ); \
} extern_list_add ( (new), (head) ); \
#define list_add( new, head ) do { \
list_check ( (head) ); \
list_add ( (new), (head) ); \
} while ( 0 ) } while ( 0 )
static inline void inline_list_add ( struct list_head *new,
struct list_head *head ) {
struct list_head *prev = head;
struct list_head *next = head->next;
next->prev = (new);
(new)->next = next;
(new)->prev = prev;
prev->next = (new);
}
extern void extern_list_add ( struct list_head *new,
struct list_head *head );
/** /**
* Add a new entry to the tail of a list * Add a new entry to the tail of a list
@ -96,26 +88,21 @@ static inline void list_add ( struct list_head *new, struct list_head *head ) {
* @v new New entry to be added * @v new New entry to be added
* @v head List head, or entry before which to add the new entry * @v head List head, or entry before which to add the new entry
*/ */
static inline void list_add_tail ( struct list_head *new, #define list_add_tail( new, head ) do { \
struct list_head *head ) { list_check ( (head) ); \
__list_add ( new, head->prev, head ); extern_list_add_tail ( (new), (head) ); \
}
#define list_add_tail( new, head ) do { \
list_check ( (head) ); \
list_add_tail ( (new), (head) ); \
} while ( 0 ) } while ( 0 )
static inline void inline_list_add_tail ( struct list_head *new,
/** struct list_head *head ) {
* Delete a list entry between two known consecutive entries struct list_head *prev = head->prev;
* struct list_head *next = head;
* @v prev Previous list entry next->prev = (new);
* @v next Next list entry (new)->next = next;
*/ (new)->prev = prev;
static inline void __list_del ( struct list_head *prev, prev->next = (new);
struct list_head *next ) {
next->prev = prev;
prev->next = next;
} }
extern void extern_list_add_tail ( struct list_head *new,
struct list_head *head );
/** /**
* Delete an entry from a list * Delete an entry from a list
@ -125,37 +112,43 @@ static inline void __list_del ( struct list_head *prev,
* Note that list_empty() on entry does not return true after this; * Note that list_empty() on entry does not return true after this;
* the entry is in an undefined state. * the entry is in an undefined state.
*/ */
static inline void list_del ( struct list_head *list ) { #define list_del( list ) do { \
__list_del ( list->prev, list->next ); list_check ( (list) ); \
} inline_list_del ( (list) ); \
#define list_del( list ) do { \
list_check ( (list) ); \
list_del ( (list) ); \
} while ( 0 ) } while ( 0 )
static inline void inline_list_del ( struct list_head *list ) {
struct list_head *next = (list)->next;
struct list_head *prev = (list)->prev;
next->prev = prev;
prev->next = next;
}
extern void extern_list_del ( struct list_head *list );
/** /**
* Test whether a list is empty * Test whether a list is empty
* *
* @v list List head * @v list List head
*/ */
static inline int list_empty ( const struct list_head *list ) { #define list_empty( list ) ( { \
list_check ( (list) ); \
inline_list_empty ( (list) ); } )
static inline int inline_list_empty ( const struct list_head *list ) {
return ( list->next == list ); return ( list->next == list );
} }
#define list_empty( list ) ( { \ extern int extern_list_empty ( const struct list_head *list );
list_check ( (list) ); \
list_empty ( (list) ); } )
/** /**
* Test whether a list has just one entry * Test whether a list has just one entry
* *
* @v list List to test * @v list List to test
*/ */
static inline int list_is_singular ( const struct list_head *list ) { #define list_is_singular( list ) ( { \
list_check ( (list) ); \
inline_list_is_singular ( (list) ); } )
static inline int inline_list_is_singular ( const struct list_head *list ) {
return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) ); return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) );
} }
#define list_is_singular( list ) ( { \ extern int extern_list_is_singular ( const struct list_head *list );
list_check ( (list) ); \
list_is_singular ( (list) ); } )
/** /**
* Test whether an entry is the last entry in list * Test whether an entry is the last entry in list
@ -163,14 +156,16 @@ static inline int list_is_singular ( const struct list_head *list ) {
* @v list List entry to test * @v list List entry to test
* @v head List head * @v head List head
*/ */
static inline int list_is_last ( const struct list_head *list, #define list_is_last( list, head ) ( { \
const struct list_head *head ) { list_check ( (list) ); \
list_check ( (head) ); \
inline_list_is_last ( (list), (head) ); } )
static inline int inline_list_is_last ( const struct list_head *list,
const struct list_head *head ) {
return ( list->next == head ); return ( list->next == head );
} }
#define list_is_last( list, head ) ( { \ extern int extern_list_is_last ( const struct list_head *list,
list_check ( (list) ); \ const struct list_head *head );
list_check ( (head) ); \
list_is_last ( (list), (head) ); } )
/** /**
* Cut a list into two * Cut a list into two
@ -183,9 +178,16 @@ static inline int list_is_last ( const struct list_head *list,
* @c new, which should be an empty list. @c entry may be equal to @c * @c new, which should be an empty list. @c entry may be equal to @c
* list, in which case no entries are moved. * list, in which case no entries are moved.
*/ */
static inline void list_cut_position ( struct list_head *new, #define list_cut_position( new, list, entry ) do { \
struct list_head *list, list_check ( (new) ); \
struct list_head *entry ) { assert ( list_empty ( (new) ) ); \
list_check ( (list) ); \
list_check ( (entry) ); \
extern_list_cut_position ( (new), (list), (entry) ); \
} while ( 0 )
static inline void inline_list_cut_position ( struct list_head *new,
struct list_head *list,
struct list_head *entry ) {
struct list_head *first = entry->next; struct list_head *first = entry->next;
if ( list != entry ) { if ( list != entry ) {
@ -197,13 +199,9 @@ static inline void list_cut_position ( struct list_head *new,
list->next->prev = list; list->next->prev = list;
} }
} }
#define list_cut_position( new, list, entry ) do { \ extern void extern_list_cut_position ( struct list_head *new,
list_check ( (new) ); \ struct list_head *list,
assert ( list_empty ( (new) ) ); \ struct list_head *entry );
list_check ( (list) ); \
list_check ( (entry) ); \
list_cut_position ( (new), (list), (entry) ); \
} while ( 0 )
/** /**
* Move all entries from one list into another list * Move all entries from one list into another list
@ -215,8 +213,13 @@ static inline void list_cut_position ( struct list_head *new,
* list is left in an undefined state; use @c list_splice_init() if * list is left in an undefined state; use @c list_splice_init() if
* you want @c list to become an empty list. * you want @c list to become an empty list.
*/ */
static inline void list_splice ( const struct list_head *list, #define list_splice( list, entry ) do { \
struct list_head *entry ) { list_check ( (list) ); \
list_check ( (entry) ); \
extern_list_splice ( (list), (entry) ); \
} while ( 0 )
static inline void inline_list_splice ( const struct list_head *list,
struct list_head *entry ) {
struct list_head *first = list->next; struct list_head *first = list->next;
struct list_head *last = list->prev; struct list_head *last = list->prev;
@ -227,11 +230,8 @@ static inline void list_splice ( const struct list_head *list,
first->prev->next = first; first->prev->next = first;
} }
} }
#define list_splice( list, entry ) do { \ extern void extern_list_splice ( const struct list_head *list,
list_check ( (list) ); \ struct list_head *entry );
list_check ( (entry) ); \
list_splice ( (list), (entry) ); \
} while ( 0 )
/** /**
* Move all entries from one list into another list * Move all entries from one list into another list
@ -243,8 +243,13 @@ static inline void list_splice ( const struct list_head *list,
* list is left in an undefined state; use @c list_splice_tail_init() if * list is left in an undefined state; use @c list_splice_tail_init() if
* you want @c list to become an empty list. * you want @c list to become an empty list.
*/ */
static inline void list_splice_tail ( const struct list_head *list, #define list_splice_tail( list, entry ) do { \
struct list_head *entry ) { list_check ( (list) ); \
list_check ( (entry) ); \
extern_list_splice_tail ( (list), (entry) ); \
} while ( 0 )
static inline void inline_list_splice_tail ( const struct list_head *list,
struct list_head *entry ) {
struct list_head *first = list->next; struct list_head *first = list->next;
struct list_head *last = list->prev; struct list_head *last = list->prev;
@ -255,11 +260,8 @@ static inline void list_splice_tail ( const struct list_head *list,
last->next->prev = last; last->next->prev = last;
} }
} }
#define list_splice_tail( list, entry ) do { \ extern void extern_list_splice_tail ( const struct list_head *list,
list_check ( (list) ); \ struct list_head *entry );
list_check ( (entry) ); \
list_splice_tail ( (list), (entry) ); \
} while ( 0 )
/** /**
* Move all entries from one list into another list and reinitialise empty list * Move all entries from one list into another list and reinitialise empty list
@ -269,16 +271,18 @@ static inline void list_splice_tail ( const struct list_head *list,
* *
* All entries from @c list are inserted after @c entry. * All entries from @c list are inserted after @c entry.
*/ */
static inline void list_splice_init ( struct list_head *list, #define list_splice_init( list, entry ) do { \
struct list_head *entry ) { list_check ( (list) ); \
list_check ( (entry) ); \
extern_list_splice_init ( (list), (entry) ); \
} while ( 0 )
static inline void inline_list_splice_init ( struct list_head *list,
struct list_head *entry ) {
list_splice ( list, entry ); list_splice ( list, entry );
INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( list );
} }
#define list_splice_init( list, entry ) do { \ extern void extern_list_splice_init ( struct list_head *list,
list_check ( (list) ); \ struct list_head *entry );
list_check ( (entry) ); \
list_splice_init ( (list), (entry) ); \
} while ( 0 )
/** /**
* Move all entries from one list into another list and reinitialise empty list * Move all entries from one list into another list and reinitialise empty list
@ -288,16 +292,19 @@ static inline void list_splice_init ( struct list_head *list,
* *
* All entries from @c list are inserted before @c entry. * All entries from @c list are inserted before @c entry.
*/ */
static inline void list_splice_tail_init ( struct list_head *list, #define list_splice_tail_init( list, entry ) do { \
struct list_head *entry ) { list_check ( (list) ); \
list_check ( (entry) ); \
extern_list_splice_tail_init ( (list), (entry) ); \
} while ( 0 )
static inline void inline_list_splice_tail_init ( struct list_head *list,
struct list_head *entry ) {
list_splice_tail ( list, entry ); list_splice_tail ( list, entry );
INIT_LIST_HEAD ( list ); INIT_LIST_HEAD ( list );
} }
#define list_splice_tail_init( list, entry ) do { \ extern void extern_list_splice_tail_init ( struct list_head *list,
list_check ( (list) ); \ struct list_head *entry );
list_check ( (entry) ); \
list_splice_tail_init ( (list), (entry) ); \
} while ( 0 )
/** /**
* Get the container of a list entry * Get the container of a list entry
@ -307,8 +314,8 @@ static inline void list_splice_tail_init ( struct list_head *list,
* @v member Name of list field within containing type * @v member Name of list field within containing type
* @ret container Containing object * @ret container Containing object
*/ */
#define list_entry( list, type, member ) ( { \ #define list_entry( list, type, member ) ( { \
list_check ( (list) ); \ list_check ( (list) ); \
container_of ( list, type, member ); } ) container_of ( list, type, member ); } )
/** /**
@ -319,9 +326,9 @@ static inline void list_splice_tail_init ( struct list_head *list,
* @v member Name of list field within containing type * @v member Name of list field within containing type
* @ret first First list entry, or NULL * @ret first First list entry, or NULL
*/ */
#define list_first_entry( list, type, member ) \ #define list_first_entry( list, type, member ) \
( list_empty ( (list) ) ? \ ( list_empty ( (list) ) ? \
( type * ) NULL : \ ( type * ) NULL : \
list_entry ( (list)->next, type, member ) ) list_entry ( (list)->next, type, member ) )
/** /**
@ -332,9 +339,9 @@ static inline void list_splice_tail_init ( struct list_head *list,
* @v member Name of list field within containing type * @v member Name of list field within containing type
* @ret first First list entry, or NULL * @ret first First list entry, or NULL
*/ */
#define list_last_entry( list, type, member ) \ #define list_last_entry( list, type, member ) \
( list_empty ( (list) ) ? \ ( list_empty ( (list) ) ? \
( type * ) NULL : \ ( type * ) NULL : \
list_entry ( (list)->prev, type, member ) ) list_entry ( (list)->prev, type, member ) )
/** /**
@ -424,8 +431,12 @@ static inline void list_splice_tail_init ( struct list_head *list,
* @v head List head * @v head List head
* @ret present List contains specified entry * @ret present List contains specified entry
*/ */
static inline int list_contains ( struct list_head *entry, #define list_contains( entry, head ) ( { \
struct list_head *head ) { list_check ( (head) ); \
list_check ( (entry) ); \
extern_list_contains ( (entry), (head) ); } )
static inline int inline_list_contains ( struct list_head *entry,
struct list_head *head ) {
struct list_head *tmp; struct list_head *tmp;
list_for_each ( tmp, head ) { list_for_each ( tmp, head ) {
@ -434,10 +445,8 @@ static inline int list_contains ( struct list_head *entry,
} }
return 0; return 0;
} }
#define list_contains( entry, head ) ( { \ extern int extern_list_contains ( struct list_head *entry,
list_check ( (head) ); \ struct list_head *head );
list_check ( (entry) ); \
list_contains ( (entry), (head) ); } )
/** /**
* Test if list contains a specified entry * Test if list contains a specified entry
@ -446,7 +455,7 @@ static inline int list_contains ( struct list_head *entry,
* @v head List head * @v head List head
* @ret present List contains specified entry * @ret present List contains specified entry
*/ */
#define list_contains_entry( entry, head, member ) \ #define list_contains_entry( entry, head, member ) \
list_contains ( &(entry)->member, (head) ) list_contains ( &(entry)->member, (head) )
/** /**