xref: /aosp_15_r20/external/llvm-libc/include/llvm-libc-macros/sys-queue-macros.h (revision 71db0c75aadcf003ffe3238005f61d7618a3fead)
1 //===-- Macros defined in sys/queue.h header file -------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H
10 #define LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H
11 
12 #include "containerof-macro.h"
13 #include "null-macro.h"
14 
15 #ifdef __cplusplus
16 #define QUEUE_TYPEOF(type) type
17 #else
18 #define QUEUE_TYPEOF(type) struct type
19 #endif
20 
21 // Singly-linked list definitions.
22 
23 #define SLIST_HEAD(name, type)                                                 \
24   struct name {                                                                \
25     struct type *slh_first;                                                    \
26   }
27 
28 #define SLIST_CLASS_HEAD(name, type)                                           \
29   struct name {                                                                \
30     class type *slh_first;                                                     \
31   }
32 
33 #define SLIST_HEAD_INITIALIZER(head)                                           \
34   { NULL }
35 
36 #define SLIST_ENTRY(type)                                                      \
37   struct {                                                                     \
38     struct type *next;                                                         \
39   }
40 
41 #define SLIST_CLASS_ENTRY(type)                                                \
42   struct {                                                                     \
43     class type *next;                                                          \
44   }
45 
46 // Singly-linked list access methods.
47 
48 #define SLIST_EMPTY(head) ((head)->slh_first == NULL)
49 #define SLIST_FIRST(head) ((head)->slh_first)
50 #define SLIST_NEXT(elem, field) ((elem)->field.next)
51 
52 #define SLIST_FOREACH(var, head, field)                                        \
53   for ((var) = SLIST_FIRST(head); (var); (var) = SLIST_NEXT(var, field))
54 
55 #define SLIST_FOREACH_FROM(var, head, field)                                   \
56   if (!(var))                                                                  \
57     (var) = SLIST_FIRST(head);                                                 \
58   for (; (var); (var) = SLIST_NEXT(var, field))
59 
60 #define SLIST_FOREACH_SAFE(var, head, field, tvar)                             \
61   for ((var) = SLIST_FIRST(head);                                              \
62        (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar))
63 
64 #define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar)                        \
65   if (!(var))                                                                  \
66     (var) = SLIST_FIRST(head);                                                 \
67   for (; (var) && ((tvar) = SLIST_NEXT(var, field), 1); (var) = (tvar))
68 
69 // Singly-linked list functions.
70 
71 #define SLIST_CONCAT(head1, head2, type, field)                                \
72   do {                                                                         \
73     if (SLIST_EMPTY(head1)) {                                                  \
74       if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL)                   \
75         SLIST_INIT(head2);                                                     \
76     } else if (!SLIST_EMPTY(head2)) {                                          \
77       QUEUE_TYPEOF(type) *cur = SLIST_FIRST(head1);                            \
78       while (SLIST_NEXT(cur, field) != NULL)                                   \
79         cur = SLIST_NEXT(cur, field);                                          \
80       SLIST_NEXT(cur, field) = SLIST_FIRST(head2);                             \
81       SLIST_INIT(head2);                                                       \
82     }                                                                          \
83   } while (0)
84 
85 #define SLIST_INIT(head)                                                       \
86   do {                                                                         \
87     SLIST_FIRST(head) = NULL;                                                  \
88   } while (0)
89 
90 #define SLIST_INSERT_AFTER(slistelem, elem, field)                             \
91   do {                                                                         \
92     SLIST_NEXT(elem, field) = SLIST_NEXT(slistelem, field);                    \
93     SLIST_NEXT(slistelem, field) = (elem);                                     \
94   } while (0)
95 
96 #define SLIST_INSERT_HEAD(head, elem, field)                                   \
97   do {                                                                         \
98     SLIST_NEXT(elem, field) = SLIST_FIRST(head);                               \
99     SLIST_FIRST(head) = (elem);                                                \
100   } while (0)
101 
102 #define SLIST_REMOVE(head, elem, type, field)                                  \
103   do {                                                                         \
104     if (SLIST_FIRST(head) == (elem)) {                                         \
105       SLIST_REMOVE_HEAD(head, field);                                          \
106     } else {                                                                   \
107       QUEUE_TYPEOF(type) *cur = SLIST_FIRST(head);                             \
108       while (SLIST_NEXT(cur, field) != (elem))                                 \
109         cur = SLIST_NEXT(cur, field);                                          \
110       SLIST_REMOVE_AFTER(cur, field);                                          \
111     }                                                                          \
112   } while (0)
113 
114 #define SLIST_REMOVE_AFTER(elem, field)                                        \
115   do {                                                                         \
116     SLIST_NEXT(elem, field) = SLIST_NEXT(SLIST_NEXT(elem, field), field);      \
117   } while (0)
118 
119 #define SLIST_REMOVE_HEAD(head, field)                                         \
120   do {                                                                         \
121     SLIST_FIRST(head) = SLIST_NEXT(SLIST_FIRST(head), field);                  \
122   } while (0)
123 
124 #define SLIST_SWAP(head1, head2, type)                                         \
125   do {                                                                         \
126     QUEUE_TYPEOF(type) *first = SLIST_FIRST(head1);                            \
127     SLIST_FIRST(head1) = SLIST_FIRST(head2);                                   \
128     SLIST_FIRST(head2) = first;                                                \
129   } while (0)
130 
131 // Singly-linked tail queue definitions.
132 
133 #define STAILQ_HEAD(name, type)                                                \
134   struct name {                                                                \
135     struct type *stqh_first;                                                   \
136     struct type **stqh_last;                                                   \
137   }
138 
139 #define STAILQ_CLASS_HEAD(name, type)                                          \
140   struct name {                                                                \
141     class type *stqh_first;                                                    \
142     class type **stqh_last;                                                    \
143   }
144 
145 #define STAILQ_HEAD_INITIALIZER(head)                                          \
146   { NULL, &(head).stqh_first }
147 
148 #define STAILQ_ENTRY(type)                                                     \
149   struct {                                                                     \
150     struct type *next;                                                         \
151   }
152 
153 #define STAILQ_CLASS_ENTRY(type)                                               \
154   struct {                                                                     \
155     class type *next;                                                          \
156   }
157 
158 // Singly-linked tail queue access methods.
159 
160 #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
161 #define STAILQ_FIRST(head) ((head)->stqh_first)
162 #define STAILQ_LAST(head, type, field)                                         \
163   (STAILQ_EMPTY(head)                                                          \
164        ? NULL                                                                  \
165        : __containerof((head)->stqh_last, QUEUE_TYPEOF(type), field.next))
166 #define STAILQ_NEXT(elem, field) ((elem)->field.next)
167 
168 #define STAILQ_FOREACH(var, head, field)                                       \
169   for ((var) = STAILQ_FIRST(head); (var); (var) = STAILQ_NEXT(var, field))
170 
171 #define STAILQ_FOREACH_FROM(var, head, field)                                  \
172   if (!(var))                                                                  \
173     (var) = STAILQ_FIRST(head);                                                \
174   for (; (var); (var) = STAILQ_NEXT(var, field))
175 
176 #define STAILQ_FOREACH_SAFE(var, head, field, tvar)                            \
177   for ((var) = STAILQ_FIRST(head);                                             \
178        (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar))
179 
180 #define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar)                       \
181   if (!(var))                                                                  \
182     (var) = STAILQ_FIRST(head);                                                \
183   for (; (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar))
184 
185 // Singly-linked tail queue functions.
186 
187 #define STAILQ_CONCAT(head1, head2, type, field)                               \
188   do {                                                                         \
189     if (!STAILQ_EMPTY(head2)) {                                                \
190       *(head1)->stqh_last = (head2)->stqh_first;                               \
191       (head1)->stqh_last = (head2)->stqh_last;                                 \
192       STAILQ_INIT(head2);                                                      \
193     }                                                                          \
194   } while (0)
195 
196 #define STAILQ_INIT(head)                                                      \
197   do {                                                                         \
198     STAILQ_FIRST(head) = NULL;                                                 \
199     (head)->stqh_last = &STAILQ_FIRST(head);                                   \
200   } while (0)
201 
202 #define STAILQ_INSERT_AFTER(head, listelem, elem, field)                       \
203   do {                                                                         \
204     if ((STAILQ_NEXT(elem, field) = STAILQ_NEXT(listelem, field)) == NULL)     \
205       (head)->stqh_last = &STAILQ_NEXT(elem, field);                           \
206     STAILQ_NEXT(listelem, field) = (elem);                                     \
207   } while (0)
208 
209 #define STAILQ_INSERT_HEAD(head, elem, field)                                  \
210   do {                                                                         \
211     if ((STAILQ_NEXT(elem, field) = STAILQ_FIRST(head)) == NULL)               \
212       (head)->stqh_last = &STAILQ_NEXT(elem, field);                           \
213     STAILQ_FIRST(head) = (elem);                                               \
214   } while (0)
215 
216 #define STAILQ_INSERT_TAIL(head, elem, field)                                  \
217   do {                                                                         \
218     STAILQ_NEXT(elem, field) = NULL;                                           \
219     *(head)->stqh_last = (elem);                                               \
220     (head)->stqh_last = &STAILQ_NEXT(elem, field);                             \
221   } while (0)
222 
223 #define STAILQ_REMOVE(head, elem, type, field)                                 \
224   do {                                                                         \
225     if (STAILQ_FIRST(head) == (elem)) {                                        \
226       STAILQ_REMOVE_HEAD(head, field);                                         \
227     } else {                                                                   \
228       QUEUE_TYPEOF(type) *cur = STAILQ_FIRST(head);                            \
229       while (STAILQ_NEXT(cur, field) != (elem))                                \
230         cur = STAILQ_NEXT(cur, field);                                         \
231       STAILQ_REMOVE_AFTER(head, cur, field);                                   \
232     }                                                                          \
233   } while (0)
234 
235 #define STAILQ_REMOVE_AFTER(head, elem, field)                                 \
236   do {                                                                         \
237     if ((STAILQ_NEXT(elem, field) =                                            \
238              STAILQ_NEXT(STAILQ_NEXT(elem, field), field)) == NULL)            \
239       (head)->stqh_last = &STAILQ_NEXT(elem, field);                           \
240   } while (0)
241 
242 #define STAILQ_REMOVE_HEAD(head, field)                                        \
243   do {                                                                         \
244     if ((STAILQ_FIRST(head) = STAILQ_NEXT(STAILQ_FIRST(head), field)) == NULL) \
245       (head)->stqh_last = &STAILQ_FIRST(head);                                 \
246   } while (0)
247 
248 #define STAILQ_SWAP(head1, head2, type)                                        \
249   do {                                                                         \
250     QUEUE_TYPEOF(type) *first = STAILQ_FIRST(head1);                           \
251     QUEUE_TYPEOF(type) **last = (head1)->stqh_last;                            \
252     STAILQ_FIRST(head1) = STAILQ_FIRST(head2);                                 \
253     (head1)->stqh_last = (head2)->stqh_last;                                   \
254     STAILQ_FIRST(head2) = first;                                               \
255     (head2)->stqh_last = last;                                                 \
256     if (STAILQ_EMPTY(head1))                                                   \
257       (head1)->stqh_last = &STAILQ_FIRST(head1);                               \
258     if (STAILQ_EMPTY(head2))                                                   \
259       (head2)->stqh_last = &STAILQ_FIRST(head2);                               \
260   } while (0)
261 
262 #endif // LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H
263