Zephyr Project API  3.3.0
A Scalable Open Source RTOS
dlist.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2013-2015 Wind River Systems, Inc.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
20#ifndef ZEPHYR_INCLUDE_SYS_DLIST_H_
21#define ZEPHYR_INCLUDE_SYS_DLIST_H_
22
23#include <stddef.h>
24#include <stdbool.h>
25#include <zephyr/toolchain.h>
26
27#ifdef __cplusplus
28extern "C" {
29#endif
30
37struct _dnode {
38 union {
39 struct _dnode *head; /* ptr to head of list (sys_dlist_t) */
40 struct _dnode *next; /* ptr to next node (sys_dnode_t) */
41 };
42 union {
43 struct _dnode *tail; /* ptr to tail of list (sys_dlist_t) */
44 struct _dnode *prev; /* ptr to previous node (sys_dnode_t) */
45 };
46};
47
48typedef struct _dnode sys_dlist_t;
49typedef struct _dnode sys_dnode_t;
50
51
67#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn) \
68 for (__dn = sys_dlist_peek_head(__dl); __dn != NULL; \
69 __dn = sys_dlist_peek_next(__dl, __dn))
70
91#define SYS_DLIST_ITERATE_FROM_NODE(__dl, __dn) \
92 for (__dn = __dn ? sys_dlist_peek_next_no_check(__dl, __dn) \
93 : sys_dlist_peek_head(__dl); \
94 __dn != NULL; \
95 __dn = sys_dlist_peek_next(__dl, __dn))
96
113#define SYS_DLIST_FOR_EACH_NODE_SAFE(__dl, __dn, __dns) \
114 for (__dn = sys_dlist_peek_head(__dl), \
115 __dns = sys_dlist_peek_next(__dl, __dn); \
116 __dn != NULL; __dn = __dns, \
117 __dns = sys_dlist_peek_next(__dl, __dn))
118
119/*
120 * @brief Provide the primitive to resolve the container of a list node
121 * Note: it is safe to use with NULL pointer nodes
122 *
123 * @param __dn A pointer on a sys_dnode_t to get its container
124 * @param __cn Container struct type pointer
125 * @param __n The field name of sys_dnode_t within the container struct
126 */
127#define SYS_DLIST_CONTAINER(__dn, __cn, __n) \
128 ((__dn != NULL) ? CONTAINER_OF(__dn, __typeof__(*__cn), __n) : NULL)
129/*
130 * @brief Provide the primitive to peek container of the list head
131 *
132 * @param __dl A pointer on a sys_dlist_t to peek
133 * @param __cn Container struct type pointer
134 * @param __n The field name of sys_dnode_t within the container struct
135 */
136#define SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n) \
137 SYS_DLIST_CONTAINER(sys_dlist_peek_head(__dl), __cn, __n)
138
139/*
140 * @brief Provide the primitive to peek the next container
141 *
142 * @param __dl A pointer on a sys_dlist_t to peek
143 * @param __cn Container struct type pointer
144 * @param __n The field name of sys_dnode_t within the container struct
145 */
146#define SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n) \
147 ((__cn != NULL) ? \
148 SYS_DLIST_CONTAINER(sys_dlist_peek_next(__dl, &(__cn->__n)), \
149 __cn, __n) : NULL)
150
165#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n) \
166 for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n); \
167 __cn != NULL; \
168 __cn = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
169
185#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n) \
186 for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n), \
187 __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n); \
188 __cn != NULL; __cn = __cns, \
189 __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
190
197static inline void sys_dlist_init(sys_dlist_t *list)
198{
199 list->head = (sys_dnode_t *)list;
200 list->tail = (sys_dnode_t *)list;
201}
202
203#define SYS_DLIST_STATIC_INIT(ptr_to_list) { {(ptr_to_list)}, {(ptr_to_list)} }
204
211static inline void sys_dnode_init(sys_dnode_t *node)
212{
213 node->next = NULL;
214 node->prev = NULL;
215}
216
225static inline bool sys_dnode_is_linked(const sys_dnode_t *node)
226{
227 return node->next != NULL;
228}
229
239static inline bool sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node)
240{
241 return list->head == node;
242}
243
253static inline bool sys_dlist_is_tail(sys_dlist_t *list, sys_dnode_t *node)
254{
255 return list->tail == node;
256}
257
266static inline bool sys_dlist_is_empty(sys_dlist_t *list)
267{
268 return list->head == list;
269}
270
282{
283 return list->head != list->tail;
284}
285
295{
296 return sys_dlist_is_empty(list) ? NULL : list->head;
297}
298
310{
311 return list->head;
312}
313
326 sys_dnode_t *node)
327{
328 return (node == list->tail) ? NULL : node->next;
329}
330
342 sys_dnode_t *node)
343{
344 return (node != NULL) ? sys_dlist_peek_next_no_check(list, node) : NULL;
345}
346
360 sys_dnode_t *node)
361{
362 return (node == list->head) ? NULL : node->prev;
363}
364
377 sys_dnode_t *node)
378{
379 return (node != NULL) ? sys_dlist_peek_prev_no_check(list, node) : NULL;
380}
381
391{
392 return sys_dlist_is_empty(list) ? NULL : list->tail;
393}
394
404static inline void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
405{
406 sys_dnode_t *const tail = list->tail;
407
408 node->next = list;
409 node->prev = tail;
410
411 tail->next = node;
412 list->tail = node;
413}
414
424static inline void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
425{
426 sys_dnode_t *const head = list->head;
427
428 node->next = head;
429 node->prev = list;
430
431 head->prev = node;
432 list->head = node;
433}
434
443static inline void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
444{
445 sys_dnode_t *const prev = successor->prev;
446
447 node->prev = prev;
448 node->next = successor;
449 prev->next = node;
450 successor->prev = node;
451}
452
468static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node,
469 int (*cond)(sys_dnode_t *node, void *data), void *data)
470{
471 if (sys_dlist_is_empty(list)) {
472 sys_dlist_append(list, node);
473 } else {
475
476 while ((pos != NULL) && (cond(pos, data) == 0)) {
477 pos = sys_dlist_peek_next(list, pos);
478 }
479 if (pos != NULL) {
480 sys_dlist_insert(pos, node);
481 } else {
482 sys_dlist_append(list, node);
483 }
484 }
485}
486
496static inline void sys_dlist_remove(sys_dnode_t *node)
497{
498 sys_dnode_t *const prev = node->prev;
499 sys_dnode_t *const next = node->next;
500
501 prev->next = next;
502 next->prev = prev;
503 sys_dnode_init(node);
504}
505
517{
518 sys_dnode_t *node = NULL;
519
520 if (!sys_dlist_is_empty(list)) {
521 node = list->head;
522 sys_dlist_remove(node);
523 }
524
525 return node;
526}
527
530#ifdef __cplusplus
531}
532#endif
533
534#endif /* ZEPHYR_INCLUDE_SYS_DLIST_H_ */
static bool sys_dlist_has_multiple_nodes(sys_dlist_t *list)
check if more than one node present
Definition: dlist.h:281
static void sys_dlist_remove(sys_dnode_t *node)
remove a specific node from a list
Definition: dlist.h:496
static void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
add node to tail of list
Definition: dlist.h:404
static sys_dnode_t * sys_dlist_peek_prev(sys_dlist_t *list, sys_dnode_t *node)
get a reference to the previous item in the list
Definition: dlist.h:376
static sys_dnode_t * sys_dlist_get(sys_dlist_t *list)
get the first node in a list
Definition: dlist.h:516
static bool sys_dlist_is_tail(sys_dlist_t *list, sys_dnode_t *node)
check if a node is the list's tail
Definition: dlist.h:253
struct _dnode sys_dnode_t
Definition: dlist.h:49
static void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node, int(*cond)(sys_dnode_t *node, void *data), void *data)
insert node at position
Definition: dlist.h:468
static void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
add node to head of list
Definition: dlist.h:424
static sys_dnode_t * sys_dlist_peek_head(sys_dlist_t *list)
get a reference to the head item in the list
Definition: dlist.h:294
static sys_dnode_t * sys_dlist_peek_head_not_empty(sys_dlist_t *list)
get a reference to the head item in the list
Definition: dlist.h:309
static sys_dnode_t * sys_dlist_peek_next(sys_dlist_t *list, sys_dnode_t *node)
get a reference to the next item in the list
Definition: dlist.h:341
static bool sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node)
check if a node is the list's head
Definition: dlist.h:239
static sys_dnode_t * sys_dlist_peek_prev_no_check(sys_dlist_t *list, sys_dnode_t *node)
get a reference to the previous item in the list, node is not NULL
Definition: dlist.h:359
static sys_dnode_t * sys_dlist_peek_next_no_check(sys_dlist_t *list, sys_dnode_t *node)
get a reference to the next item in the list, node is not NULL
Definition: dlist.h:325
static void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
Insert a node into a list.
Definition: dlist.h:443
struct _dnode sys_dlist_t
Definition: dlist.h:48
static bool sys_dlist_is_empty(sys_dlist_t *list)
check if the list is empty
Definition: dlist.h:266
static bool sys_dnode_is_linked(const sys_dnode_t *node)
check if a node is a member of any list
Definition: dlist.h:225
static sys_dnode_t * sys_dlist_peek_tail(sys_dlist_t *list)
get a reference to the tail item in the list
Definition: dlist.h:390
static void sys_dnode_init(sys_dnode_t *node)
initialize node to its state when not in a list
Definition: dlist.h:211
static void sys_dlist_init(sys_dlist_t *list)
initialize list to its empty state
Definition: dlist.h:197
static int pos
Definition: printk.c:11
static fdata_t data[2]
Definition: test_fifo_contexts.c:15
Macros to abstract toolchain specific capabilities.