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 <llvm-libc-macros/containerof-macro.h> 13 #include <llvm-libc-macros/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 *first; \ 26 } 27 28 #define SLIST_CLASS_HEAD(name, type) \ 29 struct name { \ 30 class type *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)->first == NULL) 49 #define SLIST_FIRST(head) ((head)->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 *first; \ 136 struct type **last; \ 137 } 138 139 #define STAILQ_CLASS_HEAD(name, type) \ 140 struct name { \ 141 class type *first; \ 142 class type **last; \ 143 } 144 145 #define STAILQ_HEAD_INITIALIZER(head) \ 146 { NULL, &(head).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)->first == NULL) 161 #define STAILQ_FIRST(head) ((head)->first) 162 #define STAILQ_LAST(head, type, field) \ 163 (STAILQ_EMPTY(head) ? NULL : __containerof((head)->last, type, field.next)) 164 #define STAILQ_NEXT(elem, field) ((elem)->field.next) 165 166 #define STAILQ_FOREACH(var, head, field) \ 167 for ((var) = STAILQ_FIRST(head); (var); (var) = STAILQ_NEXT(var, field)) 168 169 #define STAILQ_FOREACH_FROM(var, head, field) \ 170 if (!(var)) \ 171 (var) = STAILQ_FIRST(head); \ 172 for (; (var); (var) = STAILQ_NEXT(var, field)) 173 174 #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ 175 for ((var) = STAILQ_FIRST(head); \ 176 (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar)) 177 178 #define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \ 179 if (!(var)) \ 180 (var) = STAILQ_FIRST(head); \ 181 for (; (var) && ((tvar) = STAILQ_NEXT(var, field), 1); (var) = (tvar)) 182 183 // Singly-linked tail queue functions. 184 185 #define STAILQ_CONCAT(head1, head2, type, field) \ 186 do { \ 187 if (!STAILQ_EMPTY(head2)) { \ 188 *(head1)->last = (head2)->first; \ 189 (head1)->last = (head2)->last; \ 190 STAILQ_INIT(head2); \ 191 } \ 192 } while (0) 193 194 #define STAILQ_INIT(head) \ 195 do { \ 196 STAILQ_FIRST(head) = NULL; \ 197 (head)->last = &STAILQ_FIRST(head); \ 198 } while (0) 199 200 #define STAILQ_INSERT_AFTER(head, listelem, elem, field) \ 201 do { \ 202 if ((STAILQ_NEXT(elem, field) = STAILQ_NEXT(listelem, field)) == NULL) \ 203 (head)->last = &STAILQ_NEXT(elem, field); \ 204 STAILQ_NEXT(listelem, field) = (elem); \ 205 } while (0) 206 207 #define STAILQ_INSERT_HEAD(head, elem, field) \ 208 do { \ 209 if ((STAILQ_NEXT(elem, field) = STAILQ_FIRST(head)) == NULL) \ 210 (head)->last = &STAILQ_NEXT(elem, field); \ 211 STAILQ_FIRST(head) = (elem); \ 212 } while (0) 213 214 #define STAILQ_INSERT_TAIL(head, elem, field) \ 215 do { \ 216 STAILQ_NEXT(elem, field) = NULL; \ 217 *(head)->last = (elem); \ 218 (head)->last = &STAILQ_NEXT(elem, field); \ 219 } while (0) 220 221 #define STAILQ_REMOVE(head, elem, type, field) \ 222 do { \ 223 if (STAILQ_FIRST(head) == (elem)) { \ 224 STAILQ_REMOVE_HEAD(head, field); \ 225 } else { \ 226 QUEUE_TYPEOF(type) *cur = STAILQ_FIRST(head); \ 227 while (STAILQ_NEXT(cur, field) != (elem)) \ 228 cur = STAILQ_NEXT(cur, field); \ 229 STAILQ_REMOVE_AFTER(head, cur, field); \ 230 } \ 231 } while (0) 232 233 #define STAILQ_REMOVE_AFTER(head, elem, field) \ 234 do { \ 235 if ((STAILQ_NEXT(elem, field) = \ 236 STAILQ_NEXT(STAILQ_NEXT(elem, field), field)) == NULL) \ 237 (head)->last = &STAILQ_NEXT(elem, field); \ 238 } while (0) 239 240 #define STAILQ_REMOVE_HEAD(head, field) \ 241 do { \ 242 if ((STAILQ_FIRST(head) = STAILQ_NEXT(STAILQ_FIRST(head), field)) == NULL) \ 243 (head)->last = &STAILQ_FIRST(head); \ 244 } while (0) 245 246 #define STAILQ_SWAP(head1, head2, type) \ 247 do { \ 248 QUEUE_TYPEOF(type) *first = STAILQ_FIRST(head1); \ 249 QUEUE_TYPEOF(type) **last = (head1)->last; \ 250 STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ 251 (head1)->last = (head2)->last; \ 252 STAILQ_FIRST(head2) = first; \ 253 (head2)->last = last; \ 254 if (STAILQ_EMPTY(head1)) \ 255 (head1)->last = &STAILQ_FIRST(head1); \ 256 if (STAILQ_EMPTY(head2)) \ 257 (head2)->last = &STAILQ_FIRST(head2); \ 258 } while (0) 259 260 #endif // __LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H 261