Path: blob/main/contrib/libarchive/unzip/la_queue.h
39478 views
/* SPDX-License-Identifier: BSD-3-Clause1*2* Copyright (c) 1991, 19933* The Regents of the University of California. All rights reserved.4*/56#ifndef _SYS_QUEUE_H_7#define _SYS_QUEUE_H_89/*10* This file defines four types of data structures: singly-linked lists,11* singly-linked tail queues, lists and tail queues.12*13* A singly-linked list is headed by a single forward pointer. The elements14* are singly linked for minimum space and pointer manipulation overhead at15* the expense of O(n) removal for arbitrary elements. New elements can be16* added to the list after an existing element or at the head of the list.17* Elements being removed from the head of the list should use the explicit18* macro for this purpose for optimum efficiency. A singly-linked list may19* only be traversed in the forward direction. Singly-linked lists are ideal20* for applications with large datasets and few or no removals or for21* implementing a LIFO queue.22*23* A singly-linked tail queue is headed by a pair of pointers, one to the24* head of the list and the other to the tail of the list. The elements are25* singly linked for minimum space and pointer manipulation overhead at the26* expense of O(n) removal for arbitrary elements. New elements can be added27* to the list after an existing element, at the head of the list, or at the28* end of the list. Elements being removed from the head of the tail queue29* should use the explicit macro for this purpose for optimum efficiency.30* A singly-linked tail queue may only be traversed in the forward direction.31* Singly-linked tail queues are ideal for applications with large datasets32* and few or no removals or for implementing a FIFO queue.33*34* A list is headed by a single forward pointer (or an array of forward35* pointers for a hash table header). The elements are doubly linked36* so that an arbitrary element can be removed without a need to37* traverse the list. New elements can be added to the list before38* or after an existing element or at the head of the list. A list39* may be traversed in either direction.40*41* A tail queue is headed by a pair of pointers, one to the head of the42* list and the other to the tail of the list. The elements are doubly43* linked so that an arbitrary element can be removed without a need to44* traverse the list. New elements can be added to the list before or45* after an existing element, at the head of the list, or at the end of46* the list. A tail queue may be traversed in either direction.47*48* For details on the use of these macros, see the queue(3) manual page.49*50* Below is a summary of implemented functions where:51* + means the macro is available52* - means the macro is not available53* s means the macro is available but is slow (runs in O(n) time)54*55* SLIST LIST STAILQ TAILQ56* _HEAD + + + +57* _CLASS_HEAD + + + +58* _HEAD_INITIALIZER + + + +59* _ENTRY + + + +60* _CLASS_ENTRY + + + +61* _INIT + + + +62* _EMPTY + + + +63* _FIRST + + + +64* _NEXT + + + +65* _PREV - + - +66* _LAST - - + +67* _LAST_FAST - - - +68* _FOREACH + + + +69* _FOREACH_FROM + + + +70* _FOREACH_SAFE + + + +71* _FOREACH_FROM_SAFE + + + +72* _FOREACH_REVERSE - - - +73* _FOREACH_REVERSE_FROM - - - +74* _FOREACH_REVERSE_SAFE - - - +75* _FOREACH_REVERSE_FROM_SAFE - - - +76* _INSERT_HEAD + + + +77* _INSERT_BEFORE - + - +78* _INSERT_AFTER + + + +79* _INSERT_TAIL - - + +80* _CONCAT s s + +81* _REMOVE_AFTER + - + -82* _REMOVE_HEAD + - + -83* _REMOVE s + s +84* _SWAP + + + +85*/86#ifdef QUEUE_MACRO_DEBUG87#warn Use QUEUE_MACRO_DEBUG_TRACE and/or QUEUE_MACRO_DEBUG_TRASH88#define QUEUE_MACRO_DEBUG_TRACE89#define QUEUE_MACRO_DEBUG_TRASH90#endif9192#ifdef QUEUE_MACRO_DEBUG_TRACE93/* Store the last 2 places the queue element or head was altered */94struct qm_trace {95unsigned long lastline;96unsigned long prevline;97const char *lastfile;98const char *prevfile;99};100101#define TRACEBUF struct qm_trace trace;102#define TRACEBUF_INITIALIZER { __LINE__, 0, __FILE__, NULL } ,103104#define QMD_TRACE_HEAD(head) do { \105(head)->trace.prevline = (head)->trace.lastline; \106(head)->trace.prevfile = (head)->trace.lastfile; \107(head)->trace.lastline = __LINE__; \108(head)->trace.lastfile = __FILE__; \109} while (0)110111#define QMD_TRACE_ELEM(elem) do { \112(elem)->trace.prevline = (elem)->trace.lastline; \113(elem)->trace.prevfile = (elem)->trace.lastfile; \114(elem)->trace.lastline = __LINE__; \115(elem)->trace.lastfile = __FILE__; \116} while (0)117118#else /* !QUEUE_MACRO_DEBUG_TRACE */119#define QMD_TRACE_ELEM(elem)120#define QMD_TRACE_HEAD(head)121#define TRACEBUF122#define TRACEBUF_INITIALIZER123#endif /* QUEUE_MACRO_DEBUG_TRACE */124125#ifdef QUEUE_MACRO_DEBUG_TRASH126#define QMD_SAVELINK(name, link) void **name = (void *)&(link)127#define TRASHIT(x) do {(x) = (void *)-1;} while (0)128#define QMD_IS_TRASHED(x) ((x) == (void *)(intptr_t)-1)129#else /* !QUEUE_MACRO_DEBUG_TRASH */130#define QMD_SAVELINK(name, link)131#define TRASHIT(x)132#define QMD_IS_TRASHED(x) 0133#endif /* QUEUE_MACRO_DEBUG_TRASH */134135#ifdef __cplusplus136/*137* In C++ there can be structure lists and class lists:138*/139#define QUEUE_TYPEOF(type) type140#else141#define QUEUE_TYPEOF(type) struct type142#endif143144/*145* Singly-linked List declarations.146*/147#define SLIST_HEAD(name, type) \148struct name { \149struct type *slh_first; /* first element */ \150}151152#define SLIST_CLASS_HEAD(name, type) \153struct name { \154class type *slh_first; /* first element */ \155}156157#define SLIST_HEAD_INITIALIZER(head) \158{ NULL }159160#define SLIST_ENTRY(type) \161struct { \162struct type *sle_next; /* next element */ \163}164165#define SLIST_CLASS_ENTRY(type) \166struct { \167class type *sle_next; /* next element */ \168}169170/*171* Singly-linked List functions.172*/173#if (defined(_KERNEL) && defined(INVARIANTS))174#define QMD_SLIST_CHECK_PREVPTR(prevp, elm) do { \175if (*(prevp) != (elm)) \176panic("Bad prevptr *(%p) == %p != %p", \177(prevp), *(prevp), (elm)); \178} while (0)179#else180#define QMD_SLIST_CHECK_PREVPTR(prevp, elm)181#endif182183#define SLIST_CONCAT(head1, head2, type, field) do { \184QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head1); \185if (curelm == NULL) { \186if ((SLIST_FIRST(head1) = SLIST_FIRST(head2)) != NULL) \187SLIST_INIT(head2); \188} else if (SLIST_FIRST(head2) != NULL) { \189while (SLIST_NEXT(curelm, field) != NULL) \190curelm = SLIST_NEXT(curelm, field); \191SLIST_NEXT(curelm, field) = SLIST_FIRST(head2); \192SLIST_INIT(head2); \193} \194} while (0)195196#define SLIST_EMPTY(head) ((head)->slh_first == NULL)197198#define SLIST_FIRST(head) ((head)->slh_first)199200#define SLIST_FOREACH(var, head, field) \201for ((var) = SLIST_FIRST((head)); \202(var); \203(var) = SLIST_NEXT((var), field))204205#define SLIST_FOREACH_FROM(var, head, field) \206for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \207(var); \208(var) = SLIST_NEXT((var), field))209210#define SLIST_FOREACH_SAFE(var, head, field, tvar) \211for ((var) = SLIST_FIRST((head)); \212(var) && ((tvar) = SLIST_NEXT((var), field), 1); \213(var) = (tvar))214215#define SLIST_FOREACH_FROM_SAFE(var, head, field, tvar) \216for ((var) = ((var) ? (var) : SLIST_FIRST((head))); \217(var) && ((tvar) = SLIST_NEXT((var), field), 1); \218(var) = (tvar))219220#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \221for ((varp) = &SLIST_FIRST((head)); \222((var) = *(varp)) != NULL; \223(varp) = &SLIST_NEXT((var), field))224225#define SLIST_INIT(head) do { \226SLIST_FIRST((head)) = NULL; \227} while (0)228229#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \230SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \231SLIST_NEXT((slistelm), field) = (elm); \232} while (0)233234#define SLIST_INSERT_HEAD(head, elm, field) do { \235SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \236SLIST_FIRST((head)) = (elm); \237} while (0)238239#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)240241#define SLIST_REMOVE(head, elm, type, field) do { \242QMD_SAVELINK(oldnext, (elm)->field.sle_next); \243if (SLIST_FIRST((head)) == (elm)) { \244SLIST_REMOVE_HEAD((head), field); \245} \246else { \247QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \248while (SLIST_NEXT(curelm, field) != (elm)) \249curelm = SLIST_NEXT(curelm, field); \250SLIST_REMOVE_AFTER(curelm, field); \251} \252TRASHIT(*oldnext); \253} while (0)254255#define SLIST_REMOVE_AFTER(elm, field) do { \256SLIST_NEXT(elm, field) = \257SLIST_NEXT(SLIST_NEXT(elm, field), field); \258} while (0)259260#define SLIST_REMOVE_HEAD(head, field) do { \261SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \262} while (0)263264#define SLIST_REMOVE_PREVPTR(prevp, elm, field) do { \265QMD_SLIST_CHECK_PREVPTR(prevp, elm); \266*(prevp) = SLIST_NEXT(elm, field); \267TRASHIT((elm)->field.sle_next); \268} while (0)269270#define SLIST_SWAP(head1, head2, type) do { \271QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \272SLIST_FIRST(head1) = SLIST_FIRST(head2); \273SLIST_FIRST(head2) = swap_first; \274} while (0)275276/*277* Singly-linked Tail queue declarations.278*/279#define STAILQ_HEAD(name, type) \280struct name { \281struct type *stqh_first;/* first element */ \282struct type **stqh_last;/* addr of last next element */ \283}284285#define STAILQ_CLASS_HEAD(name, type) \286struct name { \287class type *stqh_first; /* first element */ \288class type **stqh_last; /* addr of last next element */ \289}290291#define STAILQ_HEAD_INITIALIZER(head) \292{ NULL, &(head).stqh_first }293294#define STAILQ_ENTRY(type) \295struct { \296struct type *stqe_next; /* next element */ \297}298299#define STAILQ_CLASS_ENTRY(type) \300struct { \301class type *stqe_next; /* next element */ \302}303304/*305* Singly-linked Tail queue functions.306*/307#define STAILQ_CONCAT(head1, head2) do { \308if (!STAILQ_EMPTY((head2))) { \309*(head1)->stqh_last = (head2)->stqh_first; \310(head1)->stqh_last = (head2)->stqh_last; \311STAILQ_INIT((head2)); \312} \313} while (0)314315#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)316317#define STAILQ_FIRST(head) ((head)->stqh_first)318319#define STAILQ_FOREACH(var, head, field) \320for((var) = STAILQ_FIRST((head)); \321(var); \322(var) = STAILQ_NEXT((var), field))323324#define STAILQ_FOREACH_FROM(var, head, field) \325for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \326(var); \327(var) = STAILQ_NEXT((var), field))328329#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \330for ((var) = STAILQ_FIRST((head)); \331(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \332(var) = (tvar))333334#define STAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \335for ((var) = ((var) ? (var) : STAILQ_FIRST((head))); \336(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \337(var) = (tvar))338339#define STAILQ_INIT(head) do { \340STAILQ_FIRST((head)) = NULL; \341(head)->stqh_last = &STAILQ_FIRST((head)); \342} while (0)343344#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \345if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\346(head)->stqh_last = &STAILQ_NEXT((elm), field); \347STAILQ_NEXT((tqelm), field) = (elm); \348} while (0)349350#define STAILQ_INSERT_HEAD(head, elm, field) do { \351if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \352(head)->stqh_last = &STAILQ_NEXT((elm), field); \353STAILQ_FIRST((head)) = (elm); \354} while (0)355356#define STAILQ_INSERT_TAIL(head, elm, field) do { \357STAILQ_NEXT((elm), field) = NULL; \358*(head)->stqh_last = (elm); \359(head)->stqh_last = &STAILQ_NEXT((elm), field); \360} while (0)361362#define STAILQ_LAST(head, type, field) \363(STAILQ_EMPTY((head)) ? NULL : \364__containerof((head)->stqh_last, \365QUEUE_TYPEOF(type), field.stqe_next))366367#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)368369#define STAILQ_REMOVE(head, elm, type, field) do { \370QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \371if (STAILQ_FIRST((head)) == (elm)) { \372STAILQ_REMOVE_HEAD((head), field); \373} \374else { \375QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \376while (STAILQ_NEXT(curelm, field) != (elm)) \377curelm = STAILQ_NEXT(curelm, field); \378STAILQ_REMOVE_AFTER(head, curelm, field); \379} \380TRASHIT(*oldnext); \381} while (0)382383#define STAILQ_REMOVE_AFTER(head, elm, field) do { \384if ((STAILQ_NEXT(elm, field) = \385STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \386(head)->stqh_last = &STAILQ_NEXT((elm), field); \387} while (0)388389#define STAILQ_REMOVE_HEAD(head, field) do { \390if ((STAILQ_FIRST((head)) = \391STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \392(head)->stqh_last = &STAILQ_FIRST((head)); \393} while (0)394395#define STAILQ_SWAP(head1, head2, type) do { \396QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \397QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \398STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \399(head1)->stqh_last = (head2)->stqh_last; \400STAILQ_FIRST(head2) = swap_first; \401(head2)->stqh_last = swap_last; \402if (STAILQ_EMPTY(head1)) \403(head1)->stqh_last = &STAILQ_FIRST(head1); \404if (STAILQ_EMPTY(head2)) \405(head2)->stqh_last = &STAILQ_FIRST(head2); \406} while (0)407408409/*410* List declarations.411*/412#define LIST_HEAD(name, type) \413struct name { \414struct type *lh_first; /* first element */ \415}416417#define LIST_CLASS_HEAD(name, type) \418struct name { \419class type *lh_first; /* first element */ \420}421422#define LIST_HEAD_INITIALIZER(head) \423{ NULL }424425#define LIST_ENTRY(type) \426struct { \427struct type *le_next; /* next element */ \428struct type **le_prev; /* address of previous next element */ \429}430431#define LIST_CLASS_ENTRY(type) \432struct { \433class type *le_next; /* next element */ \434class type **le_prev; /* address of previous next element */ \435}436437/*438* List functions.439*/440441#if (defined(_KERNEL) && defined(INVARIANTS))442/*443* QMD_LIST_CHECK_HEAD(LIST_HEAD *head, LIST_ENTRY NAME)444*445* If the list is non-empty, validates that the first element of the list446* points back at 'head.'447*/448#define QMD_LIST_CHECK_HEAD(head, field) do { \449if (LIST_FIRST((head)) != NULL && \450LIST_FIRST((head))->field.le_prev != \451&LIST_FIRST((head))) \452panic("Bad list head %p first->prev != head", (head)); \453} while (0)454455/*456* QMD_LIST_CHECK_NEXT(TYPE *elm, LIST_ENTRY NAME)457*458* If an element follows 'elm' in the list, validates that the next element459* points back at 'elm.'460*/461#define QMD_LIST_CHECK_NEXT(elm, field) do { \462if (LIST_NEXT((elm), field) != NULL && \463LIST_NEXT((elm), field)->field.le_prev != \464&((elm)->field.le_next)) \465panic("Bad link elm %p next->prev != elm", (elm)); \466} while (0)467468/*469* QMD_LIST_CHECK_PREV(TYPE *elm, LIST_ENTRY NAME)470*471* Validates that the previous element (or head of the list) points to 'elm.'472*/473#define QMD_LIST_CHECK_PREV(elm, field) do { \474if (*(elm)->field.le_prev != (elm)) \475panic("Bad link elm %p prev->next != elm", (elm)); \476} while (0)477#else478#define QMD_LIST_CHECK_HEAD(head, field)479#define QMD_LIST_CHECK_NEXT(elm, field)480#define QMD_LIST_CHECK_PREV(elm, field)481#endif /* (_KERNEL && INVARIANTS) */482483#define LIST_CONCAT(head1, head2, type, field) do { \484QUEUE_TYPEOF(type) *curelm = LIST_FIRST(head1); \485if (curelm == NULL) { \486if ((LIST_FIRST(head1) = LIST_FIRST(head2)) != NULL) { \487LIST_FIRST(head2)->field.le_prev = \488&LIST_FIRST((head1)); \489LIST_INIT(head2); \490} \491} else if (LIST_FIRST(head2) != NULL) { \492while (LIST_NEXT(curelm, field) != NULL) \493curelm = LIST_NEXT(curelm, field); \494LIST_NEXT(curelm, field) = LIST_FIRST(head2); \495LIST_FIRST(head2)->field.le_prev = &LIST_NEXT(curelm, field); \496LIST_INIT(head2); \497} \498} while (0)499500#define LIST_EMPTY(head) ((head)->lh_first == NULL)501502#define LIST_FIRST(head) ((head)->lh_first)503504#define LIST_FOREACH(var, head, field) \505for ((var) = LIST_FIRST((head)); \506(var); \507(var) = LIST_NEXT((var), field))508509#define LIST_FOREACH_FROM(var, head, field) \510for ((var) = ((var) ? (var) : LIST_FIRST((head))); \511(var); \512(var) = LIST_NEXT((var), field))513514#define LIST_FOREACH_SAFE(var, head, field, tvar) \515for ((var) = LIST_FIRST((head)); \516(var) && ((tvar) = LIST_NEXT((var), field), 1); \517(var) = (tvar))518519#define LIST_FOREACH_FROM_SAFE(var, head, field, tvar) \520for ((var) = ((var) ? (var) : LIST_FIRST((head))); \521(var) && ((tvar) = LIST_NEXT((var), field), 1); \522(var) = (tvar))523524#define LIST_INIT(head) do { \525LIST_FIRST((head)) = NULL; \526} while (0)527528#define LIST_INSERT_AFTER(listelm, elm, field) do { \529QMD_LIST_CHECK_NEXT(listelm, field); \530if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\531LIST_NEXT((listelm), field)->field.le_prev = \532&LIST_NEXT((elm), field); \533LIST_NEXT((listelm), field) = (elm); \534(elm)->field.le_prev = &LIST_NEXT((listelm), field); \535} while (0)536537#define LIST_INSERT_BEFORE(listelm, elm, field) do { \538QMD_LIST_CHECK_PREV(listelm, field); \539(elm)->field.le_prev = (listelm)->field.le_prev; \540LIST_NEXT((elm), field) = (listelm); \541*(listelm)->field.le_prev = (elm); \542(listelm)->field.le_prev = &LIST_NEXT((elm), field); \543} while (0)544545#define LIST_INSERT_HEAD(head, elm, field) do { \546QMD_LIST_CHECK_HEAD((head), field); \547if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \548LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\549LIST_FIRST((head)) = (elm); \550(elm)->field.le_prev = &LIST_FIRST((head)); \551} while (0)552553#define LIST_NEXT(elm, field) ((elm)->field.le_next)554555#define LIST_PREV(elm, head, type, field) \556((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \557__containerof((elm)->field.le_prev, \558QUEUE_TYPEOF(type), field.le_next))559560#define LIST_REMOVE(elm, field) do { \561QMD_SAVELINK(oldnext, (elm)->field.le_next); \562QMD_SAVELINK(oldprev, (elm)->field.le_prev); \563QMD_LIST_CHECK_NEXT(elm, field); \564QMD_LIST_CHECK_PREV(elm, field); \565if (LIST_NEXT((elm), field) != NULL) \566LIST_NEXT((elm), field)->field.le_prev = \567(elm)->field.le_prev; \568*(elm)->field.le_prev = LIST_NEXT((elm), field); \569TRASHIT(*oldnext); \570TRASHIT(*oldprev); \571} while (0)572573#define LIST_SWAP(head1, head2, type, field) do { \574QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \575LIST_FIRST((head1)) = LIST_FIRST((head2)); \576LIST_FIRST((head2)) = swap_tmp; \577if ((swap_tmp = LIST_FIRST((head1))) != NULL) \578swap_tmp->field.le_prev = &LIST_FIRST((head1)); \579if ((swap_tmp = LIST_FIRST((head2))) != NULL) \580swap_tmp->field.le_prev = &LIST_FIRST((head2)); \581} while (0)582583/*584* Tail queue declarations.585*/586#define TAILQ_HEAD(name, type) \587struct name { \588struct type *tqh_first; /* first element */ \589struct type **tqh_last; /* addr of last next element */ \590TRACEBUF \591}592593#define TAILQ_CLASS_HEAD(name, type) \594struct name { \595class type *tqh_first; /* first element */ \596class type **tqh_last; /* addr of last next element */ \597TRACEBUF \598}599600#define TAILQ_HEAD_INITIALIZER(head) \601{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER }602603#define TAILQ_ENTRY(type) \604struct { \605struct type *tqe_next; /* next element */ \606struct type **tqe_prev; /* address of previous next element */ \607TRACEBUF \608}609610#define TAILQ_CLASS_ENTRY(type) \611struct { \612class type *tqe_next; /* next element */ \613class type **tqe_prev; /* address of previous next element */ \614TRACEBUF \615}616617/*618* Tail queue functions.619*/620#if (defined(_KERNEL) && defined(INVARIANTS))621/*622* QMD_TAILQ_CHECK_HEAD(TAILQ_HEAD *head, TAILQ_ENTRY NAME)623*624* If the tailq is non-empty, validates that the first element of the tailq625* points back at 'head.'626*/627#define QMD_TAILQ_CHECK_HEAD(head, field) do { \628if (!TAILQ_EMPTY(head) && \629TAILQ_FIRST((head))->field.tqe_prev != \630&TAILQ_FIRST((head))) \631panic("Bad tailq head %p first->prev != head", (head)); \632} while (0)633634/*635* QMD_TAILQ_CHECK_TAIL(TAILQ_HEAD *head, TAILQ_ENTRY NAME)636*637* Validates that the tail of the tailq is a pointer to pointer to NULL.638*/639#define QMD_TAILQ_CHECK_TAIL(head, field) do { \640if (*(head)->tqh_last != NULL) \641panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \642} while (0)643644/*645* QMD_TAILQ_CHECK_NEXT(TYPE *elm, TAILQ_ENTRY NAME)646*647* If an element follows 'elm' in the tailq, validates that the next element648* points back at 'elm.'649*/650#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \651if (TAILQ_NEXT((elm), field) != NULL && \652TAILQ_NEXT((elm), field)->field.tqe_prev != \653&((elm)->field.tqe_next)) \654panic("Bad link elm %p next->prev != elm", (elm)); \655} while (0)656657/*658* QMD_TAILQ_CHECK_PREV(TYPE *elm, TAILQ_ENTRY NAME)659*660* Validates that the previous element (or head of the tailq) points to 'elm.'661*/662#define QMD_TAILQ_CHECK_PREV(elm, field) do { \663if (*(elm)->field.tqe_prev != (elm)) \664panic("Bad link elm %p prev->next != elm", (elm)); \665} while (0)666#else667#define QMD_TAILQ_CHECK_HEAD(head, field)668#define QMD_TAILQ_CHECK_TAIL(head, headname)669#define QMD_TAILQ_CHECK_NEXT(elm, field)670#define QMD_TAILQ_CHECK_PREV(elm, field)671#endif /* (_KERNEL && INVARIANTS) */672673#define TAILQ_CONCAT(head1, head2, field) do { \674if (!TAILQ_EMPTY(head2)) { \675*(head1)->tqh_last = (head2)->tqh_first; \676(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \677(head1)->tqh_last = (head2)->tqh_last; \678TAILQ_INIT((head2)); \679QMD_TRACE_HEAD(head1); \680QMD_TRACE_HEAD(head2); \681} \682} while (0)683684#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)685686#define TAILQ_FIRST(head) ((head)->tqh_first)687688#define TAILQ_FOREACH(var, head, field) \689for ((var) = TAILQ_FIRST((head)); \690(var); \691(var) = TAILQ_NEXT((var), field))692693#define TAILQ_FOREACH_FROM(var, head, field) \694for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \695(var); \696(var) = TAILQ_NEXT((var), field))697698#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \699for ((var) = TAILQ_FIRST((head)); \700(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \701(var) = (tvar))702703#define TAILQ_FOREACH_FROM_SAFE(var, head, field, tvar) \704for ((var) = ((var) ? (var) : TAILQ_FIRST((head))); \705(var) && ((tvar) = TAILQ_NEXT((var), field), 1); \706(var) = (tvar))707708#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \709for ((var) = TAILQ_LAST((head), headname); \710(var); \711(var) = TAILQ_PREV((var), headname, field))712713#define TAILQ_FOREACH_REVERSE_FROM(var, head, headname, field) \714for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \715(var); \716(var) = TAILQ_PREV((var), headname, field))717718#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \719for ((var) = TAILQ_LAST((head), headname); \720(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \721(var) = (tvar))722723#define TAILQ_FOREACH_REVERSE_FROM_SAFE(var, head, headname, field, tvar) \724for ((var) = ((var) ? (var) : TAILQ_LAST((head), headname)); \725(var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \726(var) = (tvar))727728#define TAILQ_INIT(head) do { \729TAILQ_FIRST((head)) = NULL; \730(head)->tqh_last = &TAILQ_FIRST((head)); \731QMD_TRACE_HEAD(head); \732} while (0)733734#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \735QMD_TAILQ_CHECK_NEXT(listelm, field); \736if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\737TAILQ_NEXT((elm), field)->field.tqe_prev = \738&TAILQ_NEXT((elm), field); \739else { \740(head)->tqh_last = &TAILQ_NEXT((elm), field); \741QMD_TRACE_HEAD(head); \742} \743TAILQ_NEXT((listelm), field) = (elm); \744(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \745QMD_TRACE_ELEM(&(elm)->field); \746QMD_TRACE_ELEM(&(listelm)->field); \747} while (0)748749#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \750QMD_TAILQ_CHECK_PREV(listelm, field); \751(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \752TAILQ_NEXT((elm), field) = (listelm); \753*(listelm)->field.tqe_prev = (elm); \754(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \755QMD_TRACE_ELEM(&(elm)->field); \756QMD_TRACE_ELEM(&(listelm)->field); \757} while (0)758759#define TAILQ_INSERT_HEAD(head, elm, field) do { \760QMD_TAILQ_CHECK_HEAD(head, field); \761if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \762TAILQ_FIRST((head))->field.tqe_prev = \763&TAILQ_NEXT((elm), field); \764else \765(head)->tqh_last = &TAILQ_NEXT((elm), field); \766TAILQ_FIRST((head)) = (elm); \767(elm)->field.tqe_prev = &TAILQ_FIRST((head)); \768QMD_TRACE_HEAD(head); \769QMD_TRACE_ELEM(&(elm)->field); \770} while (0)771772#define TAILQ_INSERT_TAIL(head, elm, field) do { \773QMD_TAILQ_CHECK_TAIL(head, field); \774TAILQ_NEXT((elm), field) = NULL; \775(elm)->field.tqe_prev = (head)->tqh_last; \776*(head)->tqh_last = (elm); \777(head)->tqh_last = &TAILQ_NEXT((elm), field); \778QMD_TRACE_HEAD(head); \779QMD_TRACE_ELEM(&(elm)->field); \780} while (0)781782#define TAILQ_LAST(head, headname) \783(*(((struct headname *)((head)->tqh_last))->tqh_last))784785/*786* The FAST function is fast in that it causes no data access other787* then the access to the head. The standard LAST function above788* will cause a data access of both the element you want and789* the previous element. FAST is very useful for instances when790* you may want to prefetch the last data element.791*/792#define TAILQ_LAST_FAST(head, type, field) \793(TAILQ_EMPTY(head) ? NULL : __containerof((head)->tqh_last, QUEUE_TYPEOF(type), field.tqe_next))794795#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)796797#define TAILQ_PREV(elm, headname, field) \798(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))799800#define TAILQ_PREV_FAST(elm, head, type, field) \801((elm)->field.tqe_prev == &(head)->tqh_first ? NULL : \802__containerof((elm)->field.tqe_prev, QUEUE_TYPEOF(type), field.tqe_next))803804#define TAILQ_REMOVE(head, elm, field) do { \805QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \806QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \807QMD_TAILQ_CHECK_NEXT(elm, field); \808QMD_TAILQ_CHECK_PREV(elm, field); \809if ((TAILQ_NEXT((elm), field)) != NULL) \810TAILQ_NEXT((elm), field)->field.tqe_prev = \811(elm)->field.tqe_prev; \812else { \813(head)->tqh_last = (elm)->field.tqe_prev; \814QMD_TRACE_HEAD(head); \815} \816*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \817TRASHIT(*oldnext); \818TRASHIT(*oldprev); \819QMD_TRACE_ELEM(&(elm)->field); \820} while (0)821822#define TAILQ_SWAP(head1, head2, type, field) do { \823QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \824QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_last; \825(head1)->tqh_first = (head2)->tqh_first; \826(head1)->tqh_last = (head2)->tqh_last; \827(head2)->tqh_first = swap_first; \828(head2)->tqh_last = swap_last; \829if ((swap_first = (head1)->tqh_first) != NULL) \830swap_first->field.tqe_prev = &(head1)->tqh_first; \831else \832(head1)->tqh_last = &(head1)->tqh_first; \833if ((swap_first = (head2)->tqh_first) != NULL) \834swap_first->field.tqe_prev = &(head2)->tqh_first; \835else \836(head2)->tqh_last = &(head2)->tqh_first; \837} while (0)838839#endif /* !_SYS_QUEUE_H_ */840841842