Browse Source

[list] Extend list-manipulation assertions to all list-handling functions

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 14 years ago
parent
commit
295ba15bd6
1 changed files with 92 additions and 82 deletions
  1. 92
    82
      src/include/ipxe/list.h

+ 92
- 82
src/include/ipxe/list.h View File

14
 #include <stddef.h>
14
 #include <stddef.h>
15
 #include <assert.h>
15
 #include <assert.h>
16
 
16
 
17
-/*
18
- * Simple doubly linked list implementation.
19
- *
20
- * Some of the internal functions ("__xxx") are useful when
21
- * manipulating whole lists rather than single entries, as
22
- * sometimes we already know the next/prev entries and we can
23
- * generate better code by using them directly rather than
24
- * using the generic single-entry routines.
25
- */
26
-
17
+/** A doubly-linked list entry (or list head) */
27
 struct list_head {
18
 struct list_head {
19
+	/** Next list entry */
28
 	struct list_head *next;
20
 	struct list_head *next;
21
+	/** Previous list entry */
29
 	struct list_head *prev;
22
 	struct list_head *prev;
30
 };
23
 };
31
 
24
 
32
-#define LIST_HEAD_INIT( name ) { &(name), &(name) }
25
+/**
26
+ * Initialise a static list head
27
+ *
28
+ * @v list		List head
29
+ */
30
+#define LIST_HEAD_INIT( list ) { &(list), &(list) }
33
 
31
 
34
-#define LIST_HEAD( name ) \
35
-	struct list_head name = LIST_HEAD_INIT ( name )
32
+/**
33
+ * Declare a static list head
34
+ *
35
+ * @v list		List head
36
+ */
37
+#define LIST_HEAD( list ) \
38
+	struct list_head list = LIST_HEAD_INIT ( list )
36
 
39
 
37
-#define INIT_LIST_HEAD( ptr ) do { \
38
-	(ptr)->next = (ptr); (ptr)->prev = (ptr); \
39
-} while ( 0 )
40
+/**
41
+ * Initialise a list head
42
+ *
43
+ * @v list		List head
44
+ */
45
+#define INIT_LIST_HEAD( list ) do {			\
46
+	(list)->next = (list);				\
47
+	(list)->prev = (list);				\
48
+	} while ( 0 )
40
 
49
 
41
-/*
42
- * Insert a new entry between two known consecutive entries.
50
+/**
51
+ * Check a list entry or list head is valid
43
  *
52
  *
44
- * This is only for internal list manipulation where we know
45
- * the prev/next entries already!
53
+ * @v list		List entry or head
54
+ */
55
+#define list_check( list ) ( {				\
56
+	assert ( (list) != NULL );			\
57
+	assert ( (list)->prev != NULL );		\
58
+	assert ( (list)->next != NULL );		\
59
+	assert ( (list)->next->prev == (list) );	\
60
+	assert ( (list)->prev->next == (list) );	\
61
+	} )
62
+
63
+/**
64
+ * Insert a list entry between two known consecutive entries
65
+ *
66
+ * @v new		New list entry
67
+ * @v prev		Previous list entry
68
+ * @v next		Next list entry
46
  */
69
  */
47
 static inline void __list_add ( struct list_head *new,
70
 static inline void __list_add ( struct list_head *new,
48
 				struct list_head *prev,
71
 				struct list_head *prev,
56
 /**
79
 /**
57
  * Add a new entry to the head of a list
80
  * Add a new entry to the head of a list
58
  *
81
  *
59
- * @v new	New entry to be added
60
- * @v head	List head to add it after
61
- *
62
- * Insert a new entry after the specified head.  This is good for
63
- * implementing stacks.
82
+ * @v new		New entry to be added
83
+ * @v head		List head, or entry after which to add the new entry
64
  */
84
  */
65
 static inline void list_add ( struct list_head *new, struct list_head *head ) {
85
 static inline void list_add ( struct list_head *new, struct list_head *head ) {
66
 	__list_add ( new, head, head->next );
86
 	__list_add ( new, head, head->next );
67
 }
87
 }
68
 #define list_add( new, head ) do {			\
88
 #define list_add( new, head ) do {			\
69
-	assert ( (head)->next->prev == (head) );	\
70
-	assert ( (head)->prev->next == (head) );	\
89
+	list_check ( (head) );				\
71
 	list_add ( (new), (head) );			\
90
 	list_add ( (new), (head) );			\
72
 	} while ( 0 )
91
 	} while ( 0 )
73
 
92
 
74
 /**
93
 /**
75
  * Add a new entry to the tail of a list
94
  * Add a new entry to the tail of a list
76
  *
95
  *
77
- * @v new	New entry to be added
78
- * @v head	List head to add it before
79
- *
80
- * Insert a new entry before the specified head.  This is useful for
81
- * implementing queues.
96
+ * @v new		New entry to be added
97
+ * @v head		List head, or entry before which to add the new entry
82
  */
98
  */
83
 static inline void list_add_tail ( struct list_head *new,
99
 static inline void list_add_tail ( struct list_head *new,
84
 				   struct list_head *head ) {
100
 				   struct list_head *head ) {
85
 	__list_add ( new, head->prev, head );
101
 	__list_add ( new, head->prev, head );
86
 }
102
 }
87
 #define list_add_tail( new, head ) do {			\
103
 #define list_add_tail( new, head ) do {			\
88
-	assert ( (head)->next->prev == (head) );	\
89
-	assert ( (head)->prev->next == (head) );	\
104
+	list_check ( (head) );				\
90
 	list_add_tail ( (new), (head) );		\
105
 	list_add_tail ( (new), (head) );		\
91
 	} while ( 0 )
106
 	} while ( 0 )
92
 
107
 
93
-/*
94
- * Delete a list entry by making the prev/next entries
95
- * point to each other.
108
+/**
109
+ * Delete a list entry between two known consecutive entries
96
  *
110
  *
97
- * This is only for internal list manipulation where we know
98
- * the prev/next entries already!
111
+ * @v prev		Previous list entry
112
+ * @v next		Next list entry
99
  */
113
  */
100
-static inline void __list_del ( struct list_head * prev,
101
-				struct list_head * next ) {
114
+static inline void __list_del ( struct list_head *prev,
115
+				struct list_head *next ) {
102
 	next->prev = prev;
116
 	next->prev = prev;
103
 	prev->next = next;
117
 	prev->next = next;
104
 }
118
 }
106
 /**
120
 /**
107
  * Delete an entry from a list
121
  * Delete an entry from a list
108
  *
122
  *
109
- * @v entry	Element to delete from the list
123
+ * @v list		List entry
110
  *
124
  *
111
  * Note that list_empty() on entry does not return true after this;
125
  * Note that list_empty() on entry does not return true after this;
112
  * the entry is in an undefined state.
126
  * the entry is in an undefined state.
113
  */
127
  */
114
-static inline void list_del ( struct list_head *entry ) {
115
-	__list_del ( entry->prev, entry->next );
128
+static inline void list_del ( struct list_head *list ) {
129
+	__list_del ( list->prev, list->next );
116
 }
130
 }
117
-#define list_del( entry ) do {				\
118
-	assert ( (entry)->prev != NULL );		\
119
-	assert ( (entry)->next != NULL );		\
120
-	assert ( (entry)->next->prev == (entry) );	\
121
-	assert ( (entry)->prev->next == (entry) );	\
122
-	list_del ( (entry) );				\
131
+#define list_del( list ) do {				\
132
+	list_check ( (list) );				\
133
+	list_del ( (list) );				\
123
 	} while ( 0 )
134
 	} while ( 0 )
124
 
135
 
125
 /**
136
 /**
126
  * Test whether a list is empty
137
  * Test whether a list is empty
127
  *
138
  *
128
- * @v head	List to test.
139
+ * @v list		List head
129
  */
140
  */
130
-static inline int list_empty ( const struct list_head *head ) {
131
-	return head->next == head;
141
+static inline int list_empty ( const struct list_head *list ) {
142
+	return ( list->next == list );
132
 }
143
 }
144
+#define list_empty( list ) ( {				\
145
+	list_check ( (list) );				\
146
+	list_empty ( (list) ); } )
133
 
147
 
134
 /**
148
 /**
135
- * Get the containing struct for this entry
136
- *
137
- * @v ptr	The struct list_head pointer
138
- * @v type	The type of the struct this is embedded in
139
- * @v member	The name of the list_struct within the struct
140
- */
141
-#define list_entry( ptr, type, member ) \
142
-	container_of ( ptr, type, member )
143
-
144
-/**
145
- * Iterate over a list
149
+ * Get the container of a list entry
146
  *
150
  *
147
- * @v pos	The &struct list_head to use as a loop counter
148
- * @v head	The head for your list
151
+ * @v list		List entry
152
+ * @v type		Containing type
153
+ * @v member		Name of list field within containing type
154
+ * @ret container	Containing object
149
  */
155
  */
150
-#define list_for_each( pos, head ) \
151
-	for ( pos = (head)->next; pos != (head); pos = pos->next )
156
+#define list_entry( list, type, member ) ( {		\
157
+	list_check ( (list) );				\
158
+	container_of ( list, type, member ); } )
152
 
159
 
153
 /**
160
 /**
154
  * Iterate over entries in a list
161
  * Iterate over entries in a list
155
  *
162
  *
156
- * @v pos	The type * to use as a loop counter
157
- * @v head	The head for your list
158
- * @v member	The name of the list_struct within the struct
163
+ * @v pos		Iterator
164
+ * @v head		List head
165
+ * @v member		Name of list field within iterator's type
159
  */
166
  */
160
 #define list_for_each_entry( pos, head, member )			      \
167
 #define list_for_each_entry( pos, head, member )			      \
161
-	for ( pos = list_entry ( (head)->next, typeof ( *pos ), member );     \
168
+	for ( list_check ( (head) ),					      \
169
+	      pos = list_entry ( (head)->next, typeof ( *pos ), member );     \
162
 	      &pos->member != (head);					      \
170
 	      &pos->member != (head);					      \
163
 	      pos = list_entry ( pos->member.next, typeof ( *pos ), member ) )
171
 	      pos = list_entry ( pos->member.next, typeof ( *pos ), member ) )
164
 
172
 
165
 /**
173
 /**
166
  * Iterate over entries in a list in reverse order
174
  * Iterate over entries in a list in reverse order
167
  *
175
  *
168
- * @v pos	The type * to use as a loop counter
169
- * @v head	The head for your list
170
- * @v member	The name of the list_struct within the struct
176
+ * @v pos		Iterator
177
+ * @v head		List head
178
+ * @v member		Name of list field within iterator's type
171
  */
179
  */
172
 #define list_for_each_entry_reverse( pos, head, member )		      \
180
 #define list_for_each_entry_reverse( pos, head, member )		      \
173
-	for ( pos = list_entry ( (head)->prev, typeof ( *pos ), member );     \
181
+	for ( list_check ( (head) ),					      \
182
+	      pos = list_entry ( (head)->prev, typeof ( *pos ), member );     \
174
 	      &pos->member != (head);					      \
183
 	      &pos->member != (head);					      \
175
 	      pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) )
184
 	      pos = list_entry ( pos->member.prev, typeof ( *pos ), member ) )
176
 
185
 
177
 /**
186
 /**
178
- * Iterate over entries in a list, safe against deletion of entries
187
+ * Iterate over entries in a list, safe against deletion of the current entry
179
  *
188
  *
180
- * @v pos	The type * to use as a loop counter
181
- * @v tmp	Another type * to use for temporary storage
182
- * @v head	The head for your list
183
- * @v member	The name of the list_struct within the struct
189
+ * @v pos		Iterator
190
+ * @v tmp		Temporary value (of same type as iterator)
191
+ * @v head		List head
192
+ * @v member		Name of list field within iterator's type
184
  */
193
  */
185
 #define list_for_each_entry_safe( pos, tmp, head, member )		      \
194
 #define list_for_each_entry_safe( pos, tmp, head, member )		      \
186
-	for ( pos = list_entry ( (head)->next, typeof ( *pos ), member ),     \
195
+	for ( list_check ( (head) ),					      \
196
+	      pos = list_entry ( (head)->next, typeof ( *pos ), member ),     \
187
 	      tmp = list_entry ( pos->member.next, typeof ( *tmp ), member ); \
197
 	      tmp = list_entry ( pos->member.next, typeof ( *tmp ), member ); \
188
 	      &pos->member != (head);					      \
198
 	      &pos->member != (head);					      \
189
 	      pos = tmp,						      \
199
 	      pos = tmp,						      \

Loading…
Cancel
Save