1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2016-2020 Intel Corporation
3 */
4
5 #ifndef __DLB_OSDEP_LIST_H__
6 #define __DLB_OSDEP_LIST_H__
7
8 #include <rte_tailq.h>
9
10 struct dlb_list_entry {
11 TAILQ_ENTRY(dlb_list_entry) node;
12 };
13
14 /* Dummy - just a struct definition */
15 TAILQ_HEAD(dlb_list_head, dlb_list_entry);
16
17 /* =================
18 * TAILQ Supplements
19 * =================
20 */
21
22 #ifndef TAILQ_FOREACH_ENTRY
23 #define TAILQ_FOREACH_ENTRY(ptr, head, name, iter) \
24 for ((iter) = TAILQ_FIRST(&head); \
25 (iter) \
26 && (ptr = container_of(iter, typeof(*(ptr)), name)); \
27 (iter) = TAILQ_NEXT((iter), node))
28 #endif
29
30 #ifndef TAILQ_FOREACH_ENTRY_SAFE
31 #define TAILQ_FOREACH_ENTRY_SAFE(ptr, head, name, iter, tvar) \
32 for ((iter) = TAILQ_FIRST(&head); \
33 (iter) && \
34 (ptr = container_of(iter, typeof(*(ptr)), name)) &&\
35 ((tvar) = TAILQ_NEXT((iter), node), 1); \
36 (iter) = (tvar))
37 #endif
38
39 /* =========
40 * DLB Lists
41 * =========
42 */
43
44 /**
45 * dlb_list_init_head() - initialize the head of a list
46 * @head: list head
47 */
dlb_list_init_head(struct dlb_list_head * head)48 static inline void dlb_list_init_head(struct dlb_list_head *head)
49 {
50 TAILQ_INIT(head);
51 }
52
53 /**
54 * dlb_list_add() - add an entry to a list
55 * @head: new entry will be added after this list header
56 * @entry: new list entry to be added
57 */
dlb_list_add(struct dlb_list_head * head,struct dlb_list_entry * entry)58 static inline void dlb_list_add(struct dlb_list_head *head,
59 struct dlb_list_entry *entry)
60 {
61 TAILQ_INSERT_TAIL(head, entry, node);
62 }
63
64 /**
65 * @head: list head
66 * @entry: list entry to be deleted
67 */
dlb_list_del(struct dlb_list_head * head,struct dlb_list_entry * entry)68 static inline void dlb_list_del(struct dlb_list_head *head,
69 struct dlb_list_entry *entry)
70 {
71 TAILQ_REMOVE(head, entry, node);
72 }
73
74 /**
75 * dlb_list_empty() - check if a list is empty
76 * @head: list head
77 *
78 * Return:
79 * Returns 1 if empty, 0 if not.
80 */
dlb_list_empty(struct dlb_list_head * head)81 static inline bool dlb_list_empty(struct dlb_list_head *head)
82 {
83 return TAILQ_EMPTY(head);
84 }
85
86 /**
87 * dlb_list_empty() - check if a list is empty
88 * @src_head: list to be added
89 * @ head: where src_head will be inserted
90 */
dlb_list_splice(struct dlb_list_head * src_head,struct dlb_list_head * head)91 static inline void dlb_list_splice(struct dlb_list_head *src_head,
92 struct dlb_list_head *head)
93 {
94 TAILQ_CONCAT(head, src_head, node);
95 }
96
97 /**
98 * DLB_LIST_HEAD() - retrieve the head of the list
99 * @head: list head
100 * @type: type of the list variable
101 * @name: name of the dlb_list within the struct
102 */
103 #define DLB_LIST_HEAD(head, type, name) \
104 (TAILQ_FIRST(&head) ? \
105 container_of(TAILQ_FIRST(&head), type, name) : \
106 NULL)
107
108 /**
109 * DLB_LIST_FOR_EACH() - iterate over a list
110 * @head: list head
111 * @ptr: pointer to struct containing a struct dlb_list_entry
112 * @name: name of the dlb_list_entry field within the containing struct
113 * @iter: iterator variable
114 */
115 #define DLB_LIST_FOR_EACH(head, ptr, name, tmp_iter) \
116 TAILQ_FOREACH_ENTRY(ptr, head, name, tmp_iter)
117
118 /**
119 * DLB_LIST_FOR_EACH_SAFE() - iterate over a list. This loop works even if
120 * an element is removed from the list while processing it.
121 * @ptr: pointer to struct containing a struct dlb_list_entry
122 * @ptr_tmp: pointer to struct containing a struct dlb_list_entry (temporary)
123 * @head: list head
124 * @name: name of the dlb_list_entry field within the containing struct
125 * @iter: iterator variable
126 * @iter_tmp: iterator variable (temporary)
127 */
128 #define DLB_LIST_FOR_EACH_SAFE(head, ptr, ptr_tmp, name, tmp_iter, saf_iter) \
129 TAILQ_FOREACH_ENTRY_SAFE(ptr, head, name, tmp_iter, saf_iter)
130
131 #endif /* __DLB_OSDEP_LIST_H__ */
132