Zephyr API Documentation  3.6.0
A Scalable Open Source RTOS
3.6.0
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
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
25#ifndef ZEPHYR_INCLUDE_SYS_DLIST_H_
26#define ZEPHYR_INCLUDE_SYS_DLIST_H_
27
28#include <stddef.h>
29#include <stdbool.h>
30#include <zephyr/toolchain.h>
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36
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
51typedef struct _dnode sys_dlist_t;
55typedef struct _dnode sys_dnode_t;
56
57
73#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn) \
74 for (__dn = sys_dlist_peek_head(__dl); __dn != NULL; \
75 __dn = sys_dlist_peek_next(__dl, __dn))
76
97#define SYS_DLIST_ITERATE_FROM_NODE(__dl, __dn) \
98 for (__dn = __dn ? sys_dlist_peek_next_no_check(__dl, __dn) \
99 : sys_dlist_peek_head(__dl); \
100 __dn != NULL; \
101 __dn = sys_dlist_peek_next(__dl, __dn))
102
119#define SYS_DLIST_FOR_EACH_NODE_SAFE(__dl, __dn, __dns) \
120 for (__dn = sys_dlist_peek_head(__dl), \
121 __dns = sys_dlist_peek_next(__dl, __dn); \
122 __dn != NULL; __dn = __dns, \
123 __dns = sys_dlist_peek_next(__dl, __dn))
124
133#define SYS_DLIST_CONTAINER(__dn, __cn, __n) \
134 ((__dn != NULL) ? CONTAINER_OF(__dn, __typeof__(*__cn), __n) : NULL)
142#define SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n) \
143 SYS_DLIST_CONTAINER(sys_dlist_peek_head(__dl), __cn, __n)
144
152#define SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n) \
153 ((__cn != NULL) ? \
154 SYS_DLIST_CONTAINER(sys_dlist_peek_next(__dl, &(__cn->__n)), \
155 __cn, __n) : NULL)
156
171#define SYS_DLIST_FOR_EACH_CONTAINER(__dl, __cn, __n) \
172 for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n); \
173 __cn != NULL; \
174 __cn = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
175
191#define SYS_DLIST_FOR_EACH_CONTAINER_SAFE(__dl, __cn, __cns, __n) \
192 for (__cn = SYS_DLIST_PEEK_HEAD_CONTAINER(__dl, __cn, __n), \
193 __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n); \
194 __cn != NULL; __cn = __cns, \
195 __cns = SYS_DLIST_PEEK_NEXT_CONTAINER(__dl, __cn, __n))
196
203static inline void sys_dlist_init(sys_dlist_t *list)
204{
205 list->head = (sys_dnode_t *)list;
206 list->tail = (sys_dnode_t *)list;
207}
208
212#define SYS_DLIST_STATIC_INIT(ptr_to_list) { {(ptr_to_list)}, {(ptr_to_list)} }
213
220static inline void sys_dnode_init(sys_dnode_t *node)
221{
222 node->next = NULL;
223 node->prev = NULL;
224}
225
234static inline bool sys_dnode_is_linked(const sys_dnode_t *node)
235{
236 return node->next != NULL;
237}
238
248static inline bool sys_dlist_is_head(sys_dlist_t *list, sys_dnode_t *node)
249{
250 return list->head == node;
251}
252
262static inline bool sys_dlist_is_tail(sys_dlist_t *list, sys_dnode_t *node)
263{
264 return list->tail == node;
265}
266
275static inline bool sys_dlist_is_empty(sys_dlist_t *list)
276{
277 return list->head == list;
278}
279
291{
292 return list->head != list->tail;
293}
294
304{
305 return sys_dlist_is_empty(list) ? NULL : list->head;
306}
307
319{
320 return list->head;
321}
322
335 sys_dnode_t *node)
336{
337 return (node == list->tail) ? NULL : node->next;
338}
339
351 sys_dnode_t *node)
352{
353 return (node != NULL) ? sys_dlist_peek_next_no_check(list, node) : NULL;
354}
355
369 sys_dnode_t *node)
370{
371 return (node == list->head) ? NULL : node->prev;
372}
373
386 sys_dnode_t *node)
387{
388 return (node != NULL) ? sys_dlist_peek_prev_no_check(list, node) : NULL;
389}
390
400{
401 return sys_dlist_is_empty(list) ? NULL : list->tail;
402}
403
413static inline void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
414{
415 sys_dnode_t *const tail = list->tail;
416
417 node->next = list;
418 node->prev = tail;
419
420 tail->next = node;
421 list->tail = node;
422}
423
433static inline void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
434{
435 sys_dnode_t *const head = list->head;
436
437 node->next = head;
438 node->prev = list;
439
440 head->prev = node;
441 list->head = node;
442}
443
452static inline void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
453{
454 sys_dnode_t *const prev = successor->prev;
455
456 node->prev = prev;
457 node->next = successor;
458 prev->next = node;
459 successor->prev = node;
460}
461
477static inline void sys_dlist_insert_at(sys_dlist_t *list, sys_dnode_t *node,
478 int (*cond)(sys_dnode_t *node, void *data), void *data)
479{
480 if (sys_dlist_is_empty(list)) {
481 sys_dlist_append(list, node);
482 } else {
483 sys_dnode_t *pos = sys_dlist_peek_head(list);
484
485 while ((pos != NULL) && (cond(pos, data) == 0)) {
486 pos = sys_dlist_peek_next(list, pos);
487 }
488 if (pos != NULL) {
489 sys_dlist_insert(pos, node);
490 } else {
491 sys_dlist_append(list, node);
492 }
493 }
494}
495
505static inline void sys_dlist_remove(sys_dnode_t *node)
506{
507 sys_dnode_t *const prev = node->prev;
508 sys_dnode_t *const next = node->next;
509
510 prev->next = next;
511 next->prev = prev;
512 sys_dnode_init(node);
513}
514
526{
527 sys_dnode_t *node = NULL;
528
529 if (!sys_dlist_is_empty(list)) {
530 node = list->head;
531 sys_dlist_remove(node);
532 }
533
534 return node;
535}
536
544static inline size_t sys_dlist_len(sys_dlist_t *list)
545{
546 size_t len = 0;
547 sys_dnode_t *node = NULL;
548
549 SYS_DLIST_FOR_EACH_NODE(list, node) {
550 len++;
551 }
552 return len;
553}
554
557#ifdef __cplusplus
558}
559#endif
560
561#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:290
static void sys_dlist_remove(sys_dnode_t *node)
remove a specific node from a list
Definition: dlist.h:505
static void sys_dlist_append(sys_dlist_t *list, sys_dnode_t *node)
add node to tail of list
Definition: dlist.h:413
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:385
static sys_dnode_t * sys_dlist_get(sys_dlist_t *list)
get the first node in a list
Definition: dlist.h:525
#define SYS_DLIST_FOR_EACH_NODE(__dl, __dn)
Provide the primitive to iterate on a list Note: the loop is unsafe and thus __dn should not be remov...
Definition: dlist.h:73
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:262
struct _dnode sys_dnode_t
Doubly-linked list node structure.
Definition: dlist.h:55
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:477
static void sys_dlist_prepend(sys_dlist_t *list, sys_dnode_t *node)
add node to head of list
Definition: dlist.h:433
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:303
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:318
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:350
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:248
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:368
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:334
static size_t sys_dlist_len(sys_dlist_t *list)
Compute the size of the given list in O(n) time.
Definition: dlist.h:544
static void sys_dlist_insert(sys_dnode_t *successor, sys_dnode_t *node)
Insert a node into a list.
Definition: dlist.h:452
struct _dnode sys_dlist_t
Doubly-linked list structure.
Definition: dlist.h:51
static bool sys_dlist_is_empty(sys_dlist_t *list)
check if the list is empty
Definition: dlist.h:275
static bool sys_dnode_is_linked(const sys_dnode_t *node)
check if a node is a member of any list
Definition: dlist.h:234
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:399
static void sys_dnode_init(sys_dnode_t *node)
initialize node to its state when not in a list
Definition: dlist.h:220
static void sys_dlist_init(sys_dlist_t *list)
initialize list to its empty state
Definition: dlist.h:203
Macros to abstract toolchain specific capabilities.