Changeset View
Changeset View
Standalone View
Standalone View
sys/sys/queue.h
Show First 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | |||||
#define QMD_TRACE_ELEM(elem) | #define QMD_TRACE_ELEM(elem) | ||||
#define QMD_TRACE_HEAD(head) | #define QMD_TRACE_HEAD(head) | ||||
#define QMD_SAVELINK(name, link) | #define QMD_SAVELINK(name, link) | ||||
#define TRACEBUF | #define TRACEBUF | ||||
#define TRACEBUF_INITIALIZER | #define TRACEBUF_INITIALIZER | ||||
#define TRASHIT(x) | #define TRASHIT(x) | ||||
#endif /* QUEUE_MACRO_DEBUG */ | #endif /* QUEUE_MACRO_DEBUG */ | ||||
#ifdef __cplusplus | |||||
/* | /* | ||||
* In C++ there can be structure lists and class lists: | |||||
*/ | |||||
#define QUEUE_TYPEOF(type) type | |||||
#else | |||||
#define QUEUE_TYPEOF(type) struct type | |||||
#endif | |||||
/* | |||||
* Singly-linked List declarations. | * Singly-linked List declarations. | ||||
*/ | */ | ||||
#define SLIST_HEAD(name, type) \ | #define SLIST_HEAD(name, type) \ | ||||
struct name { \ | struct name { \ | ||||
struct type *slh_first; /* first element */ \ | QUEUE_TYPEOF(type) *slh_first; /* first element */ \ | ||||
} | } | ||||
#define SLIST_HEAD_INITIALIZER(head) \ | #define SLIST_HEAD_INITIALIZER(head) \ | ||||
imp: Why is this needed? Class and struct are the same thing in C++, with the definition controlling… | |||||
Not Done Inline ActionsTechnically it is not needed, except these macros should only be used with classes, and that makes the compiler warn. hselasky: Technically it is not needed, except these macros should only be used with classes, and that… | |||||
{ NULL } | { NULL } | ||||
#define SLIST_ENTRY(type) \ | #define SLIST_ENTRY(type) \ | ||||
struct { \ | struct { \ | ||||
struct type *sle_next; /* next element */ \ | QUEUE_TYPEOF(type) *sle_next; /* next element */ \ | ||||
Not Done Inline ActionsAlmost every occurrence of "struct type" needs to be changed to use QUEUE_TYPEOF. See D2767. vangyzen: Almost every occurrence of "struct type" needs to be changed to use QUEUE_TYPEOF. See [[ https… | |||||
hselaskyAuthorUnsubmitted Not Done Inline ActionsRight - fixed. hselasky: Right - fixed. | |||||
} | } | ||||
/* | /* | ||||
* Singly-linked List functions. | * Singly-linked List functions. | ||||
*/ | */ | ||||
#define SLIST_EMPTY(head) ((head)->slh_first == NULL) | #define SLIST_EMPTY(head) ((head)->slh_first == NULL) | ||||
#define SLIST_FIRST(head) ((head)->slh_first) | #define SLIST_FIRST(head) ((head)->slh_first) | ||||
Show All 40 Lines | |||||
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) | #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) | ||||
#define SLIST_REMOVE(head, elm, type, field) do { \ | #define SLIST_REMOVE(head, elm, type, field) do { \ | ||||
QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ | QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ | ||||
if (SLIST_FIRST((head)) == (elm)) { \ | if (SLIST_FIRST((head)) == (elm)) { \ | ||||
SLIST_REMOVE_HEAD((head), field); \ | SLIST_REMOVE_HEAD((head), field); \ | ||||
} \ | } \ | ||||
else { \ | else { \ | ||||
struct type *curelm = SLIST_FIRST((head)); \ | QUEUE_TYPEOF(type) *curelm = SLIST_FIRST(head); \ | ||||
Not Done Inline Actions__typeof doesn't work on older compilers. Bde will give you 10k words on this if you commit it. imp: __typeof doesn't work on older compilers. Bde will give you 10k words on this if you commit it. | |||||
Not Done Inline ActionsI see. I'll update the patch to not use typeof, but instead inline the missing structure parts. Else it won't work with extern "C" like said before. hselasky: I see. I'll update the patch to not use typeof, but instead inline the missing structure parts. | |||||
while (SLIST_NEXT(curelm, field) != (elm)) \ | while (SLIST_NEXT(curelm, field) != (elm)) \ | ||||
curelm = SLIST_NEXT(curelm, field); \ | curelm = SLIST_NEXT(curelm, field); \ | ||||
SLIST_REMOVE_AFTER(curelm, field); \ | SLIST_REMOVE_AFTER(curelm, field); \ | ||||
} \ | } \ | ||||
TRASHIT(*oldnext); \ | TRASHIT(*oldnext); \ | ||||
} while (0) | } while (0) | ||||
#define SLIST_REMOVE_AFTER(elm, field) do { \ | #define SLIST_REMOVE_AFTER(elm, field) do { \ | ||||
SLIST_NEXT(elm, field) = \ | SLIST_NEXT(elm, field) = \ | ||||
SLIST_NEXT(SLIST_NEXT(elm, field), field); \ | SLIST_NEXT(SLIST_NEXT(elm, field), field); \ | ||||
} while (0) | } while (0) | ||||
#define SLIST_REMOVE_HEAD(head, field) do { \ | #define SLIST_REMOVE_HEAD(head, field) do { \ | ||||
SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ | SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ | ||||
} while (0) | } while (0) | ||||
#define SLIST_SWAP(head1, head2, type) do { \ | #define SLIST_SWAP(head1, head2, type) do { \ | ||||
struct type *swap_first = SLIST_FIRST(head1); \ | QUEUE_TYPEOF(type) *swap_first = SLIST_FIRST(head1); \ | ||||
SLIST_FIRST(head1) = SLIST_FIRST(head2); \ | SLIST_FIRST(head1) = SLIST_FIRST(head2); \ | ||||
SLIST_FIRST(head2) = swap_first; \ | SLIST_FIRST(head2) = swap_first; \ | ||||
} while (0) | } while (0) | ||||
/* | /* | ||||
* Singly-linked Tail queue declarations. | * Singly-linked Tail queue declarations. | ||||
*/ | */ | ||||
#define STAILQ_HEAD(name, type) \ | #define STAILQ_HEAD(name, type) \ | ||||
struct name { \ | struct name { \ | ||||
struct type *stqh_first;/* first element */ \ | QUEUE_TYPEOF(type) *stqh_first;/* first element */ \ | ||||
struct type **stqh_last;/* addr of last next element */ \ | QUEUE_TYPEOF(type) **stqh_last;/* addr of last next element */ \ | ||||
} | } | ||||
#define STAILQ_HEAD_INITIALIZER(head) \ | #define STAILQ_HEAD_INITIALIZER(head) \ | ||||
{ NULL, &(head).stqh_first } | { NULL, &(head).stqh_first } | ||||
#define STAILQ_ENTRY(type) \ | #define STAILQ_ENTRY(type) \ | ||||
struct { \ | struct { \ | ||||
struct type *stqe_next; /* next element */ \ | QUEUE_TYPEOF(type) *stqe_next; /* next element */ \ | ||||
} | } | ||||
/* | /* | ||||
* Singly-linked Tail queue functions. | * Singly-linked Tail queue functions. | ||||
*/ | */ | ||||
#define STAILQ_CONCAT(head1, head2) do { \ | #define STAILQ_CONCAT(head1, head2) do { \ | ||||
if (!STAILQ_EMPTY((head2))) { \ | if (!STAILQ_EMPTY((head2))) { \ | ||||
*(head1)->stqh_last = (head2)->stqh_first; \ | *(head1)->stqh_last = (head2)->stqh_first; \ | ||||
▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | |||||
} while (0) | } while (0) | ||||
#define STAILQ_INSERT_TAIL(head, elm, field) do { \ | #define STAILQ_INSERT_TAIL(head, elm, field) do { \ | ||||
STAILQ_NEXT((elm), field) = NULL; \ | STAILQ_NEXT((elm), field) = NULL; \ | ||||
*(head)->stqh_last = (elm); \ | *(head)->stqh_last = (elm); \ | ||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ | (head)->stqh_last = &STAILQ_NEXT((elm), field); \ | ||||
} while (0) | } while (0) | ||||
#define STAILQ_LAST(head, type, field) \ | #define STAILQ_LAST(head, type, field) \ | ||||
(STAILQ_EMPTY((head)) ? NULL : \ | (STAILQ_EMPTY((head)) ? NULL : \ | ||||
__containerof((head)->stqh_last, struct type, field.stqe_next)) | __containerof((head)->stqh_last, \ | ||||
QUEUE_TYPEOF(type), field.stqe_next)) | |||||
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) | #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) | ||||
#define STAILQ_REMOVE(head, elm, type, field) do { \ | #define STAILQ_REMOVE(head, elm, type, field) do { \ | ||||
QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ | QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ | ||||
if (STAILQ_FIRST((head)) == (elm)) { \ | if (STAILQ_FIRST((head)) == (elm)) { \ | ||||
STAILQ_REMOVE_HEAD((head), field); \ | STAILQ_REMOVE_HEAD((head), field); \ | ||||
} \ | } \ | ||||
else { \ | else { \ | ||||
struct type *curelm = STAILQ_FIRST((head)); \ | QUEUE_TYPEOF(type) *curelm = STAILQ_FIRST(head); \ | ||||
while (STAILQ_NEXT(curelm, field) != (elm)) \ | while (STAILQ_NEXT(curelm, field) != (elm)) \ | ||||
curelm = STAILQ_NEXT(curelm, field); \ | curelm = STAILQ_NEXT(curelm, field); \ | ||||
STAILQ_REMOVE_AFTER(head, curelm, field); \ | STAILQ_REMOVE_AFTER(head, curelm, field); \ | ||||
} \ | } \ | ||||
TRASHIT(*oldnext); \ | TRASHIT(*oldnext); \ | ||||
} while (0) | } while (0) | ||||
#define STAILQ_REMOVE_AFTER(head, elm, field) do { \ | #define STAILQ_REMOVE_AFTER(head, elm, field) do { \ | ||||
if ((STAILQ_NEXT(elm, field) = \ | if ((STAILQ_NEXT(elm, field) = \ | ||||
STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ | STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ | ||||
(head)->stqh_last = &STAILQ_NEXT((elm), field); \ | (head)->stqh_last = &STAILQ_NEXT((elm), field); \ | ||||
} while (0) | } while (0) | ||||
#define STAILQ_REMOVE_HEAD(head, field) do { \ | #define STAILQ_REMOVE_HEAD(head, field) do { \ | ||||
if ((STAILQ_FIRST((head)) = \ | if ((STAILQ_FIRST((head)) = \ | ||||
STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ | STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ | ||||
(head)->stqh_last = &STAILQ_FIRST((head)); \ | (head)->stqh_last = &STAILQ_FIRST((head)); \ | ||||
} while (0) | } while (0) | ||||
#define STAILQ_SWAP(head1, head2, type) do { \ | #define STAILQ_SWAP(head1, head2, type) do { \ | ||||
struct type *swap_first = STAILQ_FIRST(head1); \ | QUEUE_TYPEOF(type) *swap_first = STAILQ_FIRST(head1); \ | ||||
struct type **swap_last = (head1)->stqh_last; \ | QUEUE_TYPEOF(type) **swap_last = (head1)->stqh_last; \ | ||||
STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ | STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ | ||||
(head1)->stqh_last = (head2)->stqh_last; \ | (head1)->stqh_last = (head2)->stqh_last; \ | ||||
STAILQ_FIRST(head2) = swap_first; \ | STAILQ_FIRST(head2) = swap_first; \ | ||||
(head2)->stqh_last = swap_last; \ | (head2)->stqh_last = swap_last; \ | ||||
if (STAILQ_EMPTY(head1)) \ | if (STAILQ_EMPTY(head1)) \ | ||||
(head1)->stqh_last = &STAILQ_FIRST(head1); \ | (head1)->stqh_last = &STAILQ_FIRST(head1); \ | ||||
if (STAILQ_EMPTY(head2)) \ | if (STAILQ_EMPTY(head2)) \ | ||||
(head2)->stqh_last = &STAILQ_FIRST(head2); \ | (head2)->stqh_last = &STAILQ_FIRST(head2); \ | ||||
} while (0) | } while (0) | ||||
/* | /* | ||||
* List declarations. | * List declarations. | ||||
*/ | */ | ||||
#define LIST_HEAD(name, type) \ | #define LIST_HEAD(name, type) \ | ||||
struct name { \ | struct name { \ | ||||
struct type *lh_first; /* first element */ \ | QUEUE_TYPEOF(type) *lh_first; /* first element */ \ | ||||
} | } | ||||
#define LIST_HEAD_INITIALIZER(head) \ | #define LIST_HEAD_INITIALIZER(head) \ | ||||
{ NULL } | { NULL } | ||||
#define LIST_ENTRY(type) \ | #define LIST_ENTRY(type) \ | ||||
struct { \ | struct { \ | ||||
struct type *le_next; /* next element */ \ | QUEUE_TYPEOF(type) *le_next; /* next element */ \ | ||||
struct type **le_prev; /* address of previous next element */ \ | QUEUE_TYPEOF(type) **le_prev; /* address of previous next element */ \ | ||||
} | } | ||||
/* | /* | ||||
* List functions. | * List functions. | ||||
*/ | */ | ||||
#if (defined(_KERNEL) && defined(INVARIANTS)) | #if (defined(_KERNEL) && defined(INVARIANTS)) | ||||
#define QMD_LIST_CHECK_HEAD(head, field) do { \ | #define QMD_LIST_CHECK_HEAD(head, field) do { \ | ||||
▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | #define LIST_INSERT_HEAD(head, elm, field) do { \ | ||||
if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ | if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ | ||||
LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ | LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ | ||||
LIST_FIRST((head)) = (elm); \ | LIST_FIRST((head)) = (elm); \ | ||||
(elm)->field.le_prev = &LIST_FIRST((head)); \ | (elm)->field.le_prev = &LIST_FIRST((head)); \ | ||||
} while (0) | } while (0) | ||||
#define LIST_NEXT(elm, field) ((elm)->field.le_next) | #define LIST_NEXT(elm, field) ((elm)->field.le_next) | ||||
#define LIST_PREV(elm, head, type, field) \ | #define LIST_PREV(elm, head, type, field) \ | ||||
((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ | ((elm)->field.le_prev == &LIST_FIRST((head)) ? NULL : \ | ||||
__containerof((elm)->field.le_prev, struct type, field.le_next)) | __containerof((elm)->field.le_prev, \ | ||||
QUEUE_TYPEOF(type), field.le_next)) | |||||
#define LIST_REMOVE(elm, field) do { \ | #define LIST_REMOVE(elm, field) do { \ | ||||
QMD_SAVELINK(oldnext, (elm)->field.le_next); \ | QMD_SAVELINK(oldnext, (elm)->field.le_next); \ | ||||
QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ | QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ | ||||
QMD_LIST_CHECK_NEXT(elm, field); \ | QMD_LIST_CHECK_NEXT(elm, field); \ | ||||
QMD_LIST_CHECK_PREV(elm, field); \ | QMD_LIST_CHECK_PREV(elm, field); \ | ||||
if (LIST_NEXT((elm), field) != NULL) \ | if (LIST_NEXT((elm), field) != NULL) \ | ||||
LIST_NEXT((elm), field)->field.le_prev = \ | LIST_NEXT((elm), field)->field.le_prev = \ | ||||
(elm)->field.le_prev; \ | (elm)->field.le_prev; \ | ||||
*(elm)->field.le_prev = LIST_NEXT((elm), field); \ | *(elm)->field.le_prev = LIST_NEXT((elm), field); \ | ||||
TRASHIT(*oldnext); \ | TRASHIT(*oldnext); \ | ||||
TRASHIT(*oldprev); \ | TRASHIT(*oldprev); \ | ||||
} while (0) | } while (0) | ||||
#define LIST_SWAP(head1, head2, type, field) do { \ | #define LIST_SWAP(head1, head2, type, field) do { \ | ||||
struct type *swap_tmp = LIST_FIRST((head1)); \ | QUEUE_TYPEOF(type) *swap_tmp = LIST_FIRST(head1); \ | ||||
LIST_FIRST((head1)) = LIST_FIRST((head2)); \ | LIST_FIRST((head1)) = LIST_FIRST((head2)); \ | ||||
LIST_FIRST((head2)) = swap_tmp; \ | LIST_FIRST((head2)) = swap_tmp; \ | ||||
if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ | if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ | ||||
swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ | swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ | ||||
if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ | if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ | ||||
swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ | swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ | ||||
} while (0) | } while (0) | ||||
/* | /* | ||||
* Tail queue declarations. | * Tail queue declarations. | ||||
*/ | */ | ||||
#define TAILQ_HEAD(name, type) \ | #define TAILQ_HEAD(name, type) \ | ||||
struct name { \ | struct name { \ | ||||
struct type *tqh_first; /* first element */ \ | QUEUE_TYPEOF(type) *tqh_first; /* first element */ \ | ||||
struct type **tqh_last; /* addr of last next element */ \ | QUEUE_TYPEOF(type) **tqh_last; /* addr of last next element */ \ | ||||
TRACEBUF \ | TRACEBUF \ | ||||
} | } | ||||
#define TAILQ_HEAD_INITIALIZER(head) \ | #define TAILQ_HEAD_INITIALIZER(head) \ | ||||
{ NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } | { NULL, &(head).tqh_first, TRACEBUF_INITIALIZER } | ||||
#define TAILQ_ENTRY(type) \ | #define TAILQ_ENTRY(type) \ | ||||
struct { \ | struct { \ | ||||
struct type *tqe_next; /* next element */ \ | QUEUE_TYPEOF(type) *tqe_next; /* next element */ \ | ||||
struct type **tqe_prev; /* address of previous next element */ \ | QUEUE_TYPEOF(type) **tqe_prev; /* address of previous next element */ \ | ||||
TRACEBUF \ | TRACEBUF \ | ||||
} | } | ||||
/* | /* | ||||
* Tail queue functions. | * Tail queue functions. | ||||
*/ | */ | ||||
#if (defined(_KERNEL) && defined(INVARIANTS)) | #if (defined(_KERNEL) && defined(INVARIANTS)) | ||||
#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ | #define QMD_TAILQ_CHECK_HEAD(head, field) do { \ | ||||
▲ Show 20 Lines • Show All 157 Lines • ▼ Show 20 Lines | #define TAILQ_REMOVE(head, elm, field) do { \ | ||||
} \ | } \ | ||||
*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ | *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ | ||||
TRASHIT(*oldnext); \ | TRASHIT(*oldnext); \ | ||||
TRASHIT(*oldprev); \ | TRASHIT(*oldprev); \ | ||||
QMD_TRACE_ELEM(&(elm)->field); \ | QMD_TRACE_ELEM(&(elm)->field); \ | ||||
} while (0) | } while (0) | ||||
#define TAILQ_SWAP(head1, head2, type, field) do { \ | #define TAILQ_SWAP(head1, head2, type, field) do { \ | ||||
struct type *swap_first = (head1)->tqh_first; \ | QUEUE_TYPEOF(type) *swap_first = (head1)->tqh_first; \ | ||||
struct type **swap_last = (head1)->tqh_last; \ | QUEUE_TYPEOF(type) **swap_last = (head1)->tqh_first; \ | ||||
(head1)->tqh_first = (head2)->tqh_first; \ | (head1)->tqh_first = (head2)->tqh_first; \ | ||||
(head1)->tqh_last = (head2)->tqh_last; \ | (head1)->tqh_last = (head2)->tqh_last; \ | ||||
(head2)->tqh_first = swap_first; \ | (head2)->tqh_first = swap_first; \ | ||||
(head2)->tqh_last = swap_last; \ | (head2)->tqh_last = swap_last; \ | ||||
if ((swap_first = (head1)->tqh_first) != NULL) \ | if ((swap_first = (head1)->tqh_first) != NULL) \ | ||||
swap_first->field.tqe_prev = &(head1)->tqh_first; \ | swap_first->field.tqe_prev = &(head1)->tqh_first; \ | ||||
else \ | else \ | ||||
(head1)->tqh_last = &(head1)->tqh_first; \ | (head1)->tqh_last = &(head1)->tqh_first; \ | ||||
if ((swap_first = (head2)->tqh_first) != NULL) \ | if ((swap_first = (head2)->tqh_first) != NULL) \ | ||||
swap_first->field.tqe_prev = &(head2)->tqh_first; \ | swap_first->field.tqe_prev = &(head2)->tqh_first; \ | ||||
else \ | else \ | ||||
(head2)->tqh_last = &(head2)->tqh_first; \ | (head2)->tqh_last = &(head2)->tqh_first; \ | ||||
} while (0) | } while (0) | ||||
Not Done Inline Actions#undef QUEUE_TYPEOF to avoid namespace pollution. vangyzen: ```
#undef QUEUE_TYPEOF
```
to avoid namespace pollution. | |||||
hselaskyAuthorUnsubmitted Not Done Inline ActionsIt needs to be there, else the code won't compile when the macros refer QUEUE_TYPEOF(). hselasky: It needs to be there, else the code won't compile when the macros refer QUEUE_TYPEOF(). | |||||
#endif /* !_SYS_QUEUE_H_ */ | #endif /* !_SYS_QUEUE_H_ */ |
Why is this needed? Class and struct are the same thing in C++, with the definition controlling whether the members are public by default or not.