Browse Source

[list] Add list functions required by ath9k driver

Originally-implemented-by: Scott K Logan <logans@cottsay.net>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
c28053027b
2 changed files with 326 additions and 0 deletions
  1. 154
    0
      src/include/ipxe/list.h
  2. 172
    0
      src/tests/list_test.c

+ 154
- 0
src/include/ipxe/list.h View File

@@ -145,6 +145,160 @@ static inline int list_empty ( const struct list_head *list ) {
145 145
 	list_check ( (list) );				\
146 146
 	list_empty ( (list) ); } )
147 147
 
148
+/**
149
+ * Test whether a list has just one entry
150
+ *
151
+ * @v list		List to test
152
+ */
153
+static inline int list_is_singular ( const struct list_head *list ) {
154
+	return ( ( ! list_empty ( list ) ) && ( list->next == list->prev ) );
155
+}
156
+#define list_is_singular( list ) ( {			\
157
+	list_check ( (list) );				\
158
+	list_is_singular ( (list) ); } )
159
+
160
+/**
161
+ * Test whether an entry is the last entry in list
162
+ *
163
+ * @v list		List entry to test
164
+ * @v head		List head
165
+ */
166
+static inline int list_is_last ( const struct list_head *list,
167
+				 const struct list_head *head ) {
168
+	return ( list->next == head );
169
+}
170
+#define list_is_last( list, head ) ( {			\
171
+	list_check ( (list) );				\
172
+	list_check ( (head) );				\
173
+	list_is_last ( (list), (head) ); } )
174
+
175
+/**
176
+ * Cut a list into two
177
+ *
178
+ * @v new		A new list to contain all removed entries
179
+ * @v list		An existing list
180
+ * @v entry		An entry within the existing list
181
+ *
182
+ * All entries from @c list up to and including @c entry are moved to
183
+ * @c new, which should be an empty list.  @c entry may be equal to @c
184
+ * list, in which case no entries are moved.
185
+ */
186
+static inline void list_cut_position ( struct list_head *new,
187
+				       struct list_head *list,
188
+				       struct list_head *entry ) {
189
+	struct list_head *first = entry->next;
190
+
191
+	if ( list != entry ) {
192
+		new->next = list->next;
193
+		new->next->prev = new;
194
+		new->prev = entry;
195
+		new->prev->next = new;
196
+		list->next = first;
197
+		list->next->prev = list;
198
+	}
199
+}
200
+#define list_cut_position( new, list, entry ) do {	\
201
+	list_check ( (new) );				\
202
+	assert ( list_empty ( (new) ) );		\
203
+	list_check ( (list) );				\
204
+	list_check ( (entry) );				\
205
+	list_cut_position ( (new), (list), (entry) );	\
206
+	} while ( 0 )
207
+
208
+/**
209
+ * Move all entries from one list into another list
210
+ *
211
+ * @v list		List of entries to add
212
+ * @v entry		Entry after which to add the new entries
213
+ *
214
+ * All entries from @c list are inserted after @c entry.  Note that @c
215
+ * list is left in an undefined state; use @c list_splice_init() if
216
+ * you want @c list to become an empty list.
217
+ */
218
+static inline void list_splice ( const struct list_head *list,
219
+				 struct list_head *entry ) {
220
+	struct list_head *first = list->next;
221
+	struct list_head *last = list->prev;
222
+
223
+	if ( ! list_empty ( list ) ) {
224
+		last->next = entry->next;
225
+		last->next->prev = last;
226
+		first->prev = entry;
227
+		first->prev->next = first;
228
+	}
229
+}
230
+#define list_splice( list, entry ) do {			\
231
+	list_check ( (list) );				\
232
+	list_check ( (entry) );				\
233
+	list_splice ( (list), (entry) );		\
234
+	} while ( 0 )
235
+
236
+/**
237
+ * Move all entries from one list into another list
238
+ *
239
+ * @v list		List of entries to add
240
+ * @v entry		Entry before which to add the new entries
241
+ *
242
+ * All entries from @c list are inserted before @c entry.  Note that @c
243
+ * list is left in an undefined state; use @c list_splice_tail_init() if
244
+ * you want @c list to become an empty list.
245
+ */
246
+static inline void list_splice_tail ( const struct list_head *list,
247
+				      struct list_head *entry ) {
248
+	struct list_head *first = list->next;
249
+	struct list_head *last = list->prev;
250
+
251
+	if ( ! list_empty ( list ) ) {
252
+		first->prev = entry->prev;
253
+		first->prev->next = first;
254
+		last->next = entry;
255
+		last->next->prev = last;
256
+	}
257
+}
258
+#define list_splice_tail( list, entry ) do {		\
259
+	list_check ( (list) );				\
260
+	list_check ( (entry) );				\
261
+	list_splice_tail ( (list), (entry) );		\
262
+	} while ( 0 )
263
+
264
+/**
265
+ * Move all entries from one list into another list and reinitialise empty list
266
+ *
267
+ * @v list		List of entries to add
268
+ * @v entry		Entry after which to add the new entries
269
+ *
270
+ * All entries from @c list are inserted after @c entry.
271
+ */
272
+static inline void list_splice_init ( struct list_head *list,
273
+				      struct list_head *entry ) {
274
+	list_splice ( list, entry );
275
+	INIT_LIST_HEAD ( list );
276
+}
277
+#define list_splice_init( list, entry ) do {			\
278
+	list_check ( (list) );				\
279
+	list_check ( (entry) );				\
280
+	list_splice_init ( (list), (entry) );		\
281
+	} while ( 0 )
282
+
283
+/**
284
+ * Move all entries from one list into another list and reinitialise empty list
285
+ *
286
+ * @v list		List of entries to add
287
+ * @v entry		Entry before which to add the new entries
288
+ *
289
+ * All entries from @c list are inserted before @c entry.
290
+ */
291
+static inline void list_splice_tail_init ( struct list_head *list,
292
+					   struct list_head *entry ) {
293
+	list_splice_tail ( list, entry );
294
+	INIT_LIST_HEAD ( list );
295
+}
296
+#define list_splice_tail_init( list, entry ) do {	\
297
+	list_check ( (list) );				\
298
+	list_check ( (entry) );				\
299
+	list_splice_tail_init ( (list), (entry) );	\
300
+	} while ( 0 )
301
+
148 302
 /**
149 303
  * Get the container of a list entry
150 304
  *

+ 172
- 0
src/tests/list_test.c View File

@@ -124,6 +124,8 @@ static int list_check_contents ( struct list_head *list,
124 124
  */
125 125
 static void list_test_exec ( void ) {
126 126
 	struct list_head *list = &test_list;
127
+	struct list_head target_list;
128
+	struct list_head *target = &target_list;
127 129
 
128 130
 	/* Test initialiser and list_empty() */
129 131
 	ok ( list_empty ( list ) );
@@ -153,6 +155,176 @@ static void list_test_exec ( void ) {
153 155
 	list_contents_ok ( list, "" );
154 156
 	ok ( list_empty ( list ) );
155 157
 
158
+	/* Test list_is_singular() */
159
+	INIT_LIST_HEAD ( list );
160
+	ok ( ! list_is_singular ( list ) );
161
+	list_add ( &list_tests[1].list, list );
162
+	ok ( list_is_singular ( list ) );
163
+	list_add ( &list_tests[3].list, list );
164
+	ok ( ! list_is_singular ( list ) );
165
+	list_del ( &list_tests[1].list );
166
+	ok ( list_is_singular ( list ) );
167
+
168
+	/* Test list_is_last() */
169
+	INIT_LIST_HEAD ( list );
170
+	list_add_tail ( &list_tests[6].list, list );
171
+	ok ( list_is_last ( &list_tests[6].list, list ) );
172
+	list_add_tail ( &list_tests[4].list, list );
173
+	ok ( list_is_last ( &list_tests[4].list, list ) );
174
+	ok ( ! list_is_last ( &list_tests[6].list, list ) );
175
+
176
+	/* Test list_cut_position() - empty list */
177
+	INIT_LIST_HEAD ( list );
178
+	INIT_LIST_HEAD ( target );
179
+	list_cut_position ( target, list, list );
180
+	list_contents_ok ( list, "" );
181
+	list_contents_ok ( target, "" );
182
+
183
+	/* Test list_cut_position() - singular list, move nothing */
184
+	INIT_LIST_HEAD ( list );
185
+	INIT_LIST_HEAD ( target );
186
+	list_add_tail ( &list_tests[4].list, list );
187
+	list_cut_position ( target, list, list );
188
+	list_contents_ok ( list, "4" );
189
+	list_contents_ok ( target, "" );
190
+
191
+	/* Test list_cut_position() - singular list, move singular entry */
192
+	INIT_LIST_HEAD ( list );
193
+	INIT_LIST_HEAD ( target );
194
+	list_add_tail ( &list_tests[9].list, list );
195
+	list_cut_position ( target, list, &list_tests[9].list );
196
+	list_contents_ok ( list, "" );
197
+	list_contents_ok ( target, "9" );
198
+
199
+	/* Test list_cut_position() - multi-entry list, move nothing */
200
+	INIT_LIST_HEAD ( list );
201
+	list_add_tail ( &list_tests[3].list, list );
202
+	list_add_tail ( &list_tests[2].list, list );
203
+	list_add_tail ( &list_tests[7].list, list );
204
+	INIT_LIST_HEAD ( target );
205
+	list_cut_position ( target, list, list );
206
+	list_contents_ok ( list, "327" );
207
+	list_contents_ok ( target, "" );
208
+
209
+	/* Test list_cut_position() - multi-entry list, move some */
210
+	INIT_LIST_HEAD ( list );
211
+	INIT_LIST_HEAD ( target );
212
+	list_add_tail ( &list_tests[8].list, list );
213
+	list_add_tail ( &list_tests[0].list, list );
214
+	list_add_tail ( &list_tests[9].list, list );
215
+	list_add_tail ( &list_tests[3].list, list );
216
+	list_add_tail ( &list_tests[2].list, list );
217
+	list_cut_position ( target, list, &list_tests[0].list );
218
+	list_contents_ok ( list, "932" );
219
+	list_contents_ok ( target, "80" );
220
+
221
+	/* Test list_cut_position() - multi-entry list, move everything */
222
+	INIT_LIST_HEAD ( list );
223
+	INIT_LIST_HEAD ( target );
224
+	list_add_tail ( &list_tests[3].list, list );
225
+	list_add_tail ( &list_tests[5].list, list );
226
+	list_add_tail ( &list_tests[4].list, list );
227
+	list_add_tail ( &list_tests[7].list, list );
228
+	list_add_tail ( &list_tests[1].list, list );
229
+	list_cut_position ( target, list, &list_tests[1].list );
230
+	list_contents_ok ( list, "" );
231
+	list_contents_ok ( target, "35471" );
232
+
233
+	/* Test list_splice() - empty list */
234
+	INIT_LIST_HEAD ( list );
235
+	INIT_LIST_HEAD ( target );
236
+	list_splice ( list, target );
237
+	list_contents_ok ( list, "" );
238
+	list_contents_ok ( target, "" );
239
+
240
+	/* Test list_splice() - both lists empty */
241
+	INIT_LIST_HEAD ( list );
242
+	INIT_LIST_HEAD ( target );
243
+	list_splice ( list, target );
244
+	list_contents_ok ( target, "" );
245
+
246
+	/* Test list_splice() - source list empty */
247
+	INIT_LIST_HEAD ( list );
248
+	INIT_LIST_HEAD ( target );
249
+	list_add_tail ( &list_tests[1].list, target );
250
+	list_add_tail ( &list_tests[3].list, target );
251
+	list_splice ( list, &list_tests[1].list );
252
+	list_contents_ok ( target, "13" );
253
+
254
+	/* Test list_splice() - destination list empty */
255
+	INIT_LIST_HEAD ( list );
256
+	INIT_LIST_HEAD ( target );
257
+	list_add_tail ( &list_tests[6].list, list );
258
+	list_add_tail ( &list_tests[5].list, list );
259
+	list_add_tail ( &list_tests[2].list, list );
260
+	list_splice ( list, target );
261
+	list_contents_ok ( target, "652" );
262
+
263
+	/* Test list_splice() - both lists non-empty */
264
+	INIT_LIST_HEAD ( list );
265
+	INIT_LIST_HEAD ( target );
266
+	list_add_tail ( &list_tests[8].list, list );
267
+	list_add_tail ( &list_tests[4].list, list );
268
+	list_add_tail ( &list_tests[5].list, list );
269
+	list_add_tail ( &list_tests[1].list, target );
270
+	list_add_tail ( &list_tests[9].list, target );
271
+	list_splice ( list, &list_tests[1].list );
272
+	list_contents_ok ( target, "18459" );
273
+
274
+	/* Test list_splice_tail() - both lists empty */
275
+	INIT_LIST_HEAD ( list );
276
+	INIT_LIST_HEAD ( target );
277
+	list_splice_tail ( list, target );
278
+	list_contents_ok ( target, "" );
279
+
280
+	/* Test list_splice_tail() - source list empty */
281
+	INIT_LIST_HEAD ( list );
282
+	INIT_LIST_HEAD ( target );
283
+	list_add_tail ( &list_tests[5].list, target );
284
+	list_splice_tail ( list, &list_tests[5].list );
285
+	list_contents_ok ( target, "5" );
286
+
287
+	/* Test list_splice_tail() - destination list empty */
288
+	INIT_LIST_HEAD ( list );
289
+	INIT_LIST_HEAD ( target );
290
+	list_add_tail ( &list_tests[2].list, list );
291
+	list_add_tail ( &list_tests[1].list, list );
292
+	list_add_tail ( &list_tests[0].list, list );
293
+	list_splice_tail ( list, target );
294
+	list_contents_ok ( target, "210" );
295
+
296
+	/* Test list_splice_tail() - both lists non-empty */
297
+	INIT_LIST_HEAD ( list );
298
+	INIT_LIST_HEAD ( target );
299
+	list_add_tail ( &list_tests[9].list, list );
300
+	list_add_tail ( &list_tests[5].list, list );
301
+	list_add_tail ( &list_tests[7].list, list );
302
+	list_add_tail ( &list_tests[2].list, target );
303
+	list_add_tail ( &list_tests[4].list, target );
304
+	list_splice_tail ( list, &list_tests[2].list );
305
+	list_contents_ok ( target, "95724" );
306
+
307
+	/* Test list_splice_init() */
308
+	INIT_LIST_HEAD ( list );
309
+	INIT_LIST_HEAD ( target );
310
+	list_add_tail ( &list_tests[4].list, list );
311
+	list_add_tail ( &list_tests[1].list, target );
312
+	list_splice_init ( list, target );
313
+	ok ( list_empty ( list ) );
314
+	list_contents_ok ( list, "" );
315
+	list_contents_ok ( target, "41" );
316
+
317
+	/* Test list_splice_tail_init() */
318
+	INIT_LIST_HEAD ( list );
319
+	INIT_LIST_HEAD ( target );
320
+	list_add_tail ( &list_tests[3].list, list );
321
+	list_add_tail ( &list_tests[2].list, list );
322
+	list_add_tail ( &list_tests[5].list, target );
323
+	list_splice_tail_init ( list, &list_tests[5].list );
324
+	ok ( list_empty ( list ) );
325
+	list_contents_ok ( list, "" );
326
+	list_contents_ok ( target, "325" );
327
+
156 328
 	/* Test list_entry() */
157 329
 	INIT_LIST_HEAD ( &list_tests[3].list );  // for list_check()
158 330
 	ok ( list_entry ( &list_tests[3].list, struct list_test, list )

Loading…
Cancel
Save