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