1 /*
2 * Copyright © 2008, 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 /**
25 * \file list.h
26 * \brief Doubly-linked list abstract container type.
27 *
28 * Each doubly-linked list has a sentinel head and tail node. These nodes
29 * contain no data. The head sentinel can be identified by its \c prev
30 * pointer being \c NULL. The tail sentinel can be identified by its
31 * \c next pointer being \c NULL.
32 *
33 * A list is empty if either the head sentinel's \c next pointer points to the
34 * tail sentinel or the tail sentinel's \c prev poiner points to the head
35 * sentinel. The head sentinel and tail sentinel nodes are allocated within the
36 * list structure.
37 *
38 * Do note that this means that the list nodes will contain pointers into the
39 * list structure itself and as a result you may not \c realloc() an \c
40 * exec_list or any structure in which an \c exec_list is embedded.
41 */
42
43 #ifndef LIST_CONTAINER_H
44 #define LIST_CONTAINER_H
45
46 #ifndef __cplusplus
47 #include <stddef.h>
48 #endif
49 #include <assert.h>
50
51 #include "util/ralloc.h"
52
53 struct exec_node {
54 struct exec_node *next;
55 struct exec_node *prev;
56
57 #ifdef __cplusplus
58 DECLARE_RZALLOC_CXX_OPERATORS(exec_node)
59
exec_nodeexec_node60 exec_node() : next(NULL), prev(NULL)
61 {
62 /* empty */
63 }
64
65 const exec_node *get_next() const;
66 exec_node *get_next();
67
68 const exec_node *get_prev() const;
69 exec_node *get_prev();
70
71 void remove();
72
73 /**
74 * Link a node with itself
75 *
76 * This creates a sort of degenerate list that is occasionally useful.
77 */
78 void self_link();
79
80 /**
81 * Insert a node in the list after the current node
82 */
83 void insert_after(exec_node *after);
84
85 /**
86 * Insert another list in the list after the current node
87 */
88 void insert_after(struct exec_list *after);
89
90 /**
91 * Insert a node in the list before the current node
92 */
93 void insert_before(exec_node *before);
94
95 /**
96 * Insert another list in the list before the current node
97 */
98 void insert_before(struct exec_list *before);
99
100 /**
101 * Replace the current node with the given node.
102 */
103 void replace_with(exec_node *replacement);
104
105 /**
106 * Is this the sentinel at the tail of the list?
107 */
108 bool is_tail_sentinel() const;
109
110 /**
111 * Is this the sentinel at the head of the list?
112 */
113 bool is_head_sentinel() const;
114 #endif
115 };
116
117 static inline void
exec_node_init(struct exec_node * n)118 exec_node_init(struct exec_node *n)
119 {
120 n->next = NULL;
121 n->prev = NULL;
122 }
123
124 static inline const struct exec_node *
exec_node_get_next_const(const struct exec_node * n)125 exec_node_get_next_const(const struct exec_node *n)
126 {
127 return n->next;
128 }
129
130 static inline struct exec_node *
exec_node_get_next(struct exec_node * n)131 exec_node_get_next(struct exec_node *n)
132 {
133 return n->next;
134 }
135
136 static inline const struct exec_node *
exec_node_get_prev_const(const struct exec_node * n)137 exec_node_get_prev_const(const struct exec_node *n)
138 {
139 return n->prev;
140 }
141
142 static inline struct exec_node *
exec_node_get_prev(struct exec_node * n)143 exec_node_get_prev(struct exec_node *n)
144 {
145 return n->prev;
146 }
147
148 static inline void
exec_node_remove(struct exec_node * n)149 exec_node_remove(struct exec_node *n)
150 {
151 n->next->prev = n->prev;
152 n->prev->next = n->next;
153 n->next = NULL;
154 n->prev = NULL;
155 }
156
157 static inline void
exec_node_self_link(struct exec_node * n)158 exec_node_self_link(struct exec_node *n)
159 {
160 n->next = n;
161 n->prev = n;
162 }
163
164 static inline void
exec_node_insert_after(struct exec_node * n,struct exec_node * after)165 exec_node_insert_after(struct exec_node *n, struct exec_node *after)
166 {
167 after->next = n->next;
168 after->prev = n;
169
170 n->next->prev = after;
171 n->next = after;
172 }
173
174 static inline void
exec_node_insert_node_before(struct exec_node * n,struct exec_node * before)175 exec_node_insert_node_before(struct exec_node *n, struct exec_node *before)
176 {
177 before->next = n;
178 before->prev = n->prev;
179
180 n->prev->next = before;
181 n->prev = before;
182 }
183
184 static inline void
exec_node_replace_with(struct exec_node * n,struct exec_node * replacement)185 exec_node_replace_with(struct exec_node *n, struct exec_node *replacement)
186 {
187 replacement->prev = n->prev;
188 replacement->next = n->next;
189
190 n->prev->next = replacement;
191 n->next->prev = replacement;
192 }
193
194 static inline bool
exec_node_is_tail_sentinel(const struct exec_node * n)195 exec_node_is_tail_sentinel(const struct exec_node *n)
196 {
197 return n->next == NULL;
198 }
199
200 static inline bool
exec_node_is_head_sentinel(const struct exec_node * n)201 exec_node_is_head_sentinel(const struct exec_node *n)
202 {
203 return n->prev == NULL;
204 }
205
206 #ifdef __cplusplus
get_next()207 inline const exec_node *exec_node::get_next() const
208 {
209 return exec_node_get_next_const(this);
210 }
211
get_next()212 inline exec_node *exec_node::get_next()
213 {
214 return exec_node_get_next(this);
215 }
216
get_prev()217 inline const exec_node *exec_node::get_prev() const
218 {
219 return exec_node_get_prev_const(this);
220 }
221
get_prev()222 inline exec_node *exec_node::get_prev()
223 {
224 return exec_node_get_prev(this);
225 }
226
remove()227 inline void exec_node::remove()
228 {
229 exec_node_remove(this);
230 }
231
self_link()232 inline void exec_node::self_link()
233 {
234 exec_node_self_link(this);
235 }
236
insert_after(exec_node * after)237 inline void exec_node::insert_after(exec_node *after)
238 {
239 exec_node_insert_after(this, after);
240 }
241
insert_before(exec_node * before)242 inline void exec_node::insert_before(exec_node *before)
243 {
244 exec_node_insert_node_before(this, before);
245 }
246
replace_with(exec_node * replacement)247 inline void exec_node::replace_with(exec_node *replacement)
248 {
249 exec_node_replace_with(this, replacement);
250 }
251
is_tail_sentinel()252 inline bool exec_node::is_tail_sentinel() const
253 {
254 return exec_node_is_tail_sentinel(this);
255 }
256
is_head_sentinel()257 inline bool exec_node::is_head_sentinel() const
258 {
259 return exec_node_is_head_sentinel(this);
260 }
261 #endif
262
263 #ifdef __cplusplus
264 /* This macro will not work correctly if `t' uses virtual inheritance. */
265 #define exec_list_offsetof(t, f, p) \
266 (((char *) &((t *) p)->f) - ((char *) p))
267 #else
268 #define exec_list_offsetof(t, f, p) offsetof(t, f)
269 #endif
270
271 /**
272 * Get a pointer to the structure containing an exec_node
273 *
274 * Given a pointer to an \c exec_node embedded in a structure, get a pointer to
275 * the containing structure.
276 *
277 * \param type Base type of the structure containing the node
278 * \param node Pointer to the \c exec_node
279 * \param field Name of the field in \c type that is the embedded \c exec_node
280 */
281 #define exec_node_data(type, node, field) \
282 ((type *) (((uintptr_t) node) - exec_list_offsetof(type, field, node)))
283
284 #ifdef __cplusplus
285 struct exec_node;
286 #endif
287
288 struct exec_list {
289 struct exec_node head_sentinel;
290 struct exec_node tail_sentinel;
291
292 #ifdef __cplusplus
293 DECLARE_RALLOC_CXX_OPERATORS(exec_list)
294
exec_listexec_list295 exec_list()
296 {
297 make_empty();
298 }
299
300 void make_empty();
301
302 bool is_empty() const;
303
304 const exec_node *get_head() const;
305 exec_node *get_head();
306 const exec_node *get_head_raw() const;
307 exec_node *get_head_raw();
308
309 const exec_node *get_tail() const;
310 exec_node *get_tail();
311 const exec_node *get_tail_raw() const;
312 exec_node *get_tail_raw();
313
314 unsigned length() const;
315
316 void push_head(exec_node *n);
317 void push_tail(exec_node *n);
318 void push_degenerate_list_at_head(exec_node *n);
319
320 /**
321 * Remove the first node from a list and return it
322 *
323 * \return
324 * The first node in the list or \c NULL if the list is empty.
325 *
326 * \sa exec_list::get_head
327 */
328 exec_node *pop_head();
329
330 /**
331 * Move all of the nodes from this list to the target list
332 */
333 void move_nodes_to(exec_list *target);
334
335 /**
336 * Append all nodes from the source list to the end of the target list
337 */
338 void append_list(exec_list *source);
339
340 /**
341 * Prepend all nodes from the source list to the beginning of the target
342 * list
343 */
344 void prepend_list(exec_list *source);
345 #endif
346 };
347
348 static inline void
exec_list_make_empty(struct exec_list * list)349 exec_list_make_empty(struct exec_list *list)
350 {
351 list->head_sentinel.next = &list->tail_sentinel;
352 list->head_sentinel.prev = NULL;
353 list->tail_sentinel.next = NULL;
354 list->tail_sentinel.prev = &list->head_sentinel;
355 }
356
357 static inline bool
exec_list_is_empty(const struct exec_list * list)358 exec_list_is_empty(const struct exec_list *list)
359 {
360 /* There are three ways to test whether a list is empty or not.
361 *
362 * - Check to see if the head sentinel's \c next is the tail sentinel.
363 * - Check to see if the tail sentinel's \c prev is the head sentinel.
364 * - Check to see if the head is the sentinel node by test whether its
365 * \c next pointer is \c NULL.
366 *
367 * The first two methods tend to generate better code on modern systems
368 * because they save a pointer dereference.
369 */
370 return list->head_sentinel.next == &list->tail_sentinel;
371 }
372
373 static inline bool
exec_list_is_singular(const struct exec_list * list)374 exec_list_is_singular(const struct exec_list *list)
375 {
376 return !exec_list_is_empty(list) &&
377 list->head_sentinel.next->next == &list->tail_sentinel;
378 }
379
380 static inline const struct exec_node *
exec_list_get_head_const(const struct exec_list * list)381 exec_list_get_head_const(const struct exec_list *list)
382 {
383 return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
384 }
385
386 static inline struct exec_node *
exec_list_get_head(struct exec_list * list)387 exec_list_get_head(struct exec_list *list)
388 {
389 return !exec_list_is_empty(list) ? list->head_sentinel.next : NULL;
390 }
391
392 static inline const struct exec_node *
exec_list_get_head_raw_const(const struct exec_list * list)393 exec_list_get_head_raw_const(const struct exec_list *list)
394 {
395 return list->head_sentinel.next;
396 }
397
398 static inline struct exec_node *
exec_list_get_head_raw(struct exec_list * list)399 exec_list_get_head_raw(struct exec_list *list)
400 {
401 return list->head_sentinel.next;
402 }
403
404 static inline const struct exec_node *
exec_list_get_tail_const(const struct exec_list * list)405 exec_list_get_tail_const(const struct exec_list *list)
406 {
407 return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
408 }
409
410 static inline struct exec_node *
exec_list_get_tail(struct exec_list * list)411 exec_list_get_tail(struct exec_list *list)
412 {
413 return !exec_list_is_empty(list) ? list->tail_sentinel.prev : NULL;
414 }
415
416 static inline const struct exec_node *
exec_list_get_tail_raw_const(const struct exec_list * list)417 exec_list_get_tail_raw_const(const struct exec_list *list)
418 {
419 return list->tail_sentinel.prev;
420 }
421
422 static inline struct exec_node *
exec_list_get_tail_raw(struct exec_list * list)423 exec_list_get_tail_raw(struct exec_list *list)
424 {
425 return list->tail_sentinel.prev;
426 }
427
428 static inline unsigned
exec_list_length(const struct exec_list * list)429 exec_list_length(const struct exec_list *list)
430 {
431 unsigned size = 0;
432 struct exec_node *node;
433
434 for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
435 size++;
436 }
437
438 return size;
439 }
440
441 static inline void
exec_list_push_head(struct exec_list * list,struct exec_node * n)442 exec_list_push_head(struct exec_list *list, struct exec_node *n)
443 {
444 n->next = list->head_sentinel.next;
445 n->prev = &list->head_sentinel;
446
447 n->next->prev = n;
448 list->head_sentinel.next = n;
449 }
450
451 static inline void
exec_list_push_tail(struct exec_list * list,struct exec_node * n)452 exec_list_push_tail(struct exec_list *list, struct exec_node *n)
453 {
454 n->next = &list->tail_sentinel;
455 n->prev = list->tail_sentinel.prev;
456
457 n->prev->next = n;
458 list->tail_sentinel.prev = n;
459 }
460
461 static inline void
exec_list_push_degenerate_list_at_head(struct exec_list * list,struct exec_node * n)462 exec_list_push_degenerate_list_at_head(struct exec_list *list, struct exec_node *n)
463 {
464 assert(n->prev->next == n);
465
466 n->prev->next = list->head_sentinel.next;
467 list->head_sentinel.next->prev = n->prev;
468 n->prev = &list->head_sentinel;
469 list->head_sentinel.next = n;
470 }
471
472 static inline struct exec_node *
exec_list_pop_head(struct exec_list * list)473 exec_list_pop_head(struct exec_list *list)
474 {
475 struct exec_node *const n = exec_list_get_head(list);
476 if (n != NULL)
477 exec_node_remove(n);
478
479 return n;
480 }
481
482 static inline void
exec_list_move_nodes_to(struct exec_list * list,struct exec_list * target)483 exec_list_move_nodes_to(struct exec_list *list, struct exec_list *target)
484 {
485 if (exec_list_is_empty(list)) {
486 exec_list_make_empty(target);
487 } else {
488 target->head_sentinel.next = list->head_sentinel.next;
489 target->head_sentinel.prev = NULL;
490 target->tail_sentinel.next = NULL;
491 target->tail_sentinel.prev = list->tail_sentinel.prev;
492
493 target->head_sentinel.next->prev = &target->head_sentinel;
494 target->tail_sentinel.prev->next = &target->tail_sentinel;
495
496 exec_list_make_empty(list);
497 }
498 }
499
500 static inline void
exec_list_append(struct exec_list * list,struct exec_list * source)501 exec_list_append(struct exec_list *list, struct exec_list *source)
502 {
503 if (exec_list_is_empty(source))
504 return;
505
506 /* Link the first node of the source with the last node of the target list.
507 */
508 list->tail_sentinel.prev->next = source->head_sentinel.next;
509 source->head_sentinel.next->prev = list->tail_sentinel.prev;
510
511 /* Make the tail of the source list be the tail of the target list.
512 */
513 list->tail_sentinel.prev = source->tail_sentinel.prev;
514 list->tail_sentinel.prev->next = &list->tail_sentinel;
515
516 /* Make the source list empty for good measure.
517 */
518 exec_list_make_empty(source);
519 }
520
521 static inline void
exec_node_insert_list_after(struct exec_node * n,struct exec_list * after)522 exec_node_insert_list_after(struct exec_node *n, struct exec_list *after)
523 {
524 if (exec_list_is_empty(after))
525 return;
526
527 after->tail_sentinel.prev->next = n->next;
528 after->head_sentinel.next->prev = n;
529
530 n->next->prev = after->tail_sentinel.prev;
531 n->next = after->head_sentinel.next;
532
533 exec_list_make_empty(after);
534 }
535
536 static inline void
exec_list_prepend(struct exec_list * list,struct exec_list * source)537 exec_list_prepend(struct exec_list *list, struct exec_list *source)
538 {
539 exec_list_append(source, list);
540 exec_list_move_nodes_to(source, list);
541 }
542
543 static inline void
exec_node_insert_list_before(struct exec_node * n,struct exec_list * before)544 exec_node_insert_list_before(struct exec_node *n, struct exec_list *before)
545 {
546 if (exec_list_is_empty(before))
547 return;
548
549 before->tail_sentinel.prev->next = n;
550 before->head_sentinel.next->prev = n->prev;
551
552 n->prev->next = before->head_sentinel.next;
553 n->prev = before->tail_sentinel.prev;
554
555 exec_list_make_empty(before);
556 }
557
558 static inline void
exec_list_validate(const struct exec_list * list)559 exec_list_validate(const struct exec_list *list)
560 {
561 const struct exec_node *node;
562
563 assert(list->head_sentinel.next->prev == &list->head_sentinel);
564 assert(list->head_sentinel.prev == NULL);
565 assert(list->tail_sentinel.next == NULL);
566 assert(list->tail_sentinel.prev->next == &list->tail_sentinel);
567
568 /* We could try to use one of the interators below for this but they all
569 * either require C++ or assume the exec_node is embedded in a structure
570 * which is not the case for this function.
571 */
572 for (node = list->head_sentinel.next; node->next != NULL; node = node->next) {
573 assert(node->next->prev == node);
574 assert(node->prev->next == node);
575 }
576 }
577
578 #ifdef __cplusplus
make_empty()579 inline void exec_list::make_empty()
580 {
581 exec_list_make_empty(this);
582 }
583
is_empty()584 inline bool exec_list::is_empty() const
585 {
586 return exec_list_is_empty(this);
587 }
588
get_head()589 inline const exec_node *exec_list::get_head() const
590 {
591 return exec_list_get_head_const(this);
592 }
593
get_head()594 inline exec_node *exec_list::get_head()
595 {
596 return exec_list_get_head(this);
597 }
598
get_head_raw()599 inline const exec_node *exec_list::get_head_raw() const
600 {
601 return exec_list_get_head_raw_const(this);
602 }
603
get_head_raw()604 inline exec_node *exec_list::get_head_raw()
605 {
606 return exec_list_get_head_raw(this);
607 }
608
get_tail()609 inline const exec_node *exec_list::get_tail() const
610 {
611 return exec_list_get_tail_const(this);
612 }
613
get_tail()614 inline exec_node *exec_list::get_tail()
615 {
616 return exec_list_get_tail(this);
617 }
618
get_tail_raw()619 inline const exec_node *exec_list::get_tail_raw() const
620 {
621 return exec_list_get_tail_raw_const(this);
622 }
623
get_tail_raw()624 inline exec_node *exec_list::get_tail_raw()
625 {
626 return exec_list_get_tail_raw(this);
627 }
628
length()629 inline unsigned exec_list::length() const
630 {
631 return exec_list_length(this);
632 }
633
push_head(exec_node * n)634 inline void exec_list::push_head(exec_node *n)
635 {
636 exec_list_push_head(this, n);
637 }
638
push_tail(exec_node * n)639 inline void exec_list::push_tail(exec_node *n)
640 {
641 exec_list_push_tail(this, n);
642 }
643
push_degenerate_list_at_head(exec_node * n)644 inline void exec_list::push_degenerate_list_at_head(exec_node *n)
645 {
646 exec_list_push_degenerate_list_at_head(this, n);
647 }
648
pop_head()649 inline exec_node *exec_list::pop_head()
650 {
651 return exec_list_pop_head(this);
652 }
653
move_nodes_to(exec_list * target)654 inline void exec_list::move_nodes_to(exec_list *target)
655 {
656 exec_list_move_nodes_to(this, target);
657 }
658
append_list(exec_list * source)659 inline void exec_list::append_list(exec_list *source)
660 {
661 exec_list_append(this, source);
662 }
663
insert_after(exec_list * after)664 inline void exec_node::insert_after(exec_list *after)
665 {
666 exec_node_insert_list_after(this, after);
667 }
668
prepend_list(exec_list * source)669 inline void exec_list::prepend_list(exec_list *source)
670 {
671 exec_list_prepend(this, source);
672 }
673
insert_before(exec_list * before)674 inline void exec_node::insert_before(exec_list *before)
675 {
676 exec_node_insert_list_before(this, before);
677 }
678 #endif
679
680 #define exec_node_typed_forward(__node, __type) \
681 (!exec_node_is_tail_sentinel(__node) ? (__type) (__node) : NULL)
682
683 #define exec_node_typed_backward(__node, __type) \
684 (!exec_node_is_head_sentinel(__node) ? (__type) (__node) : NULL)
685
686 #define foreach_in_list(__type, __inst, __list) \
687 for (__type *__inst = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
688 (__inst) != NULL; \
689 (__inst) = exec_node_typed_forward((__inst)->next, __type *))
690
691 #define foreach_in_list_reverse(__type, __inst, __list) \
692 for (__type *__inst = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *); \
693 (__inst) != NULL; \
694 (__inst) = exec_node_typed_backward((__inst)->prev, __type *))
695
696 /**
697 * This version is safe even if the current node is removed.
698 */
699
700 #define foreach_in_list_safe(__type, __node, __list) \
701 for (__type *__node = exec_node_typed_forward((__list)->head_sentinel.next, __type *), \
702 *__next = (__node) ? exec_node_typed_forward((__list)->head_sentinel.next->next, __type *) : NULL; \
703 (__node) != NULL; \
704 (__node) = __next, __next = __next ? exec_node_typed_forward(__next->next, __type *) : NULL)
705
706 #define foreach_in_list_reverse_safe(__type, __node, __list) \
707 for (__type *__node = exec_node_typed_backward((__list)->tail_sentinel.prev, __type *), \
708 *__prev = (__node) ? exec_node_typed_backward((__list)->tail_sentinel.prev->prev, __type *) : NULL; \
709 (__node) != NULL; \
710 (__node) = __prev, __prev = __prev ? exec_node_typed_backward(__prev->prev, __type *) : NULL)
711
712 #define foreach_in_list_use_after(__type, __inst, __list) \
713 __type *__inst; \
714 for ((__inst) = exec_node_typed_forward((__list)->head_sentinel.next, __type *); \
715 (__inst) != NULL; \
716 (__inst) = exec_node_typed_forward((__inst)->next, __type *))
717
718 /**
719 * Iterate through two lists at once. Stops at the end of the shorter list.
720 *
721 * This is safe against either current node being removed or replaced.
722 */
723 #define foreach_two_lists(__node1, __list1, __node2, __list2) \
724 for (struct exec_node * __node1 = (__list1)->head_sentinel.next, \
725 * __node2 = (__list2)->head_sentinel.next, \
726 * __next1 = __node1->next, \
727 * __next2 = __node2->next \
728 ; __next1 != NULL && __next2 != NULL \
729 ; __node1 = __next1, \
730 __node2 = __next2, \
731 __next1 = __next1->next, \
732 __next2 = __next2->next)
733
734 #define exec_node_data_forward(type, node, field) \
735 (!exec_node_is_tail_sentinel(node) ? exec_node_data(type, node, field) : NULL)
736
737 #define exec_node_data_backward(type, node, field) \
738 (!exec_node_is_head_sentinel(node) ? exec_node_data(type, node, field) : NULL)
739
740 #define foreach_list_typed(__type, __node, __field, __list) \
741 for (__type * __node = \
742 exec_node_data_forward(__type, (__list)->head_sentinel.next, __field); \
743 (__node) != NULL; \
744 (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
745
746 #define foreach_list_typed_from(__type, __node, __field, __list, __start) \
747 for (__type * __node = exec_node_data_forward(__type, (__start), __field); \
748 (__node) != NULL; \
749 (__node) = exec_node_data_forward(__type, (__node)->__field.next, __field))
750
751 #define foreach_list_typed_reverse(__type, __node, __field, __list) \
752 for (__type * __node = \
753 exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field); \
754 (__node) != NULL; \
755 (__node) = exec_node_data_backward(__type, (__node)->__field.prev, __field))
756
757 #define foreach_list_typed_safe(__type, __node, __field, __list) \
758 for (__type * __node = \
759 exec_node_data_forward(__type, (__list)->head_sentinel.next, __field), \
760 * __next = (__node) ? \
761 exec_node_data_forward(__type, (__node)->__field.next, __field) : NULL; \
762 (__node) != NULL; \
763 (__node) = __next, __next = (__next && (__next)->__field.next) ? \
764 exec_node_data_forward(__type, (__next)->__field.next, __field) : NULL)
765
766 #define foreach_list_typed_reverse_safe(__type, __node, __field, __list) \
767 for (__type * __node = \
768 exec_node_data_backward(__type, (__list)->tail_sentinel.prev, __field), \
769 * __prev = (__node) ? \
770 exec_node_data_backward(__type, (__node)->__field.prev, __field) : NULL; \
771 (__node) != NULL; \
772 (__node) = __prev, __prev = (__prev && (__prev)->__field.prev) ? \
773 exec_node_data_backward(__type, (__prev)->__field.prev, __field) : NULL)
774
775 #endif /* LIST_CONTAINER_H */
776