263 lines · c
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-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H10#define LLVM_LIBC_MACROS_SYS_QUEUE_MACROS_H11 12#include "containerof-macro.h"13#include "null-macro.h"14 15#ifdef __cplusplus16#define QUEUE_TYPEOF(type) type17#else18#define QUEUE_TYPEOF(type) struct type19#endif20 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_H263