Skip to content

Commit 71e9416

Browse files
committed
extract list manipulation logic from waitlist.c
the api is inspired from bsd queue.h
1 parent 911b6af commit 71e9416

File tree

4 files changed

+115
-1
lines changed

4 files changed

+115
-1
lines changed

.clang-format

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@ ConstructorInitializerIndentWidth: 8
88
AlwaysBreakAfterReturnType: TopLevelDefinitions
99
BreakBeforeBraces: Linux
1010
IndentGotoLabels: false
11-
ForEachMacros: ["ARRAY_FOREACH", "VEC_FOREACH", "VEC_FOREACH_IDX"]
11+
ForEachMacros: ["ARRAY_FOREACH", "LIST_FOREACH", "VEC_FOREACH", "VEC_FOREACH_IDX"]
1212
SpaceBeforeParens: ControlStatementsExceptControlMacros

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ set(lib_sources
187187
"lib/insn.c"
188188
"lib/instance.c"
189189
"lib/leb128.c"
190+
"lib/list.c"
190191
"lib/module.c"
191192
"lib/nbio.c"
192193
"lib/report.c"

lib/list.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include <assert.h>
2+
#include <stddef.h>
3+
#include <stdint.h>
4+
5+
#include "list.h"
6+
7+
void
8+
list_remove(struct list_head *h, void *elem, struct list_entry *e)
9+
{
10+
assert(h->first != NULL);
11+
assert(*h->tailnextp == NULL);
12+
assert(*e->prevnextp == elem);
13+
*e->prevnextp = e->next;
14+
if (e->next == NULL) {
15+
assert(h->tailnextp == &e->next);
16+
h->tailnextp = e->prevnextp;
17+
} else {
18+
uintptr_t offset = (uintptr_t)e - (uintptr_t)elem;
19+
struct list_entry *nextentry =
20+
(void *)((uintptr_t)e->next + offset);
21+
assert(nextentry->prevnextp == &e->next);
22+
nextentry->prevnextp = e->prevnextp;
23+
}
24+
assert(*h->tailnextp == NULL);
25+
}
26+
27+
void
28+
list_insert_tail(struct list_head *h, void *elem, struct list_entry *e)
29+
{
30+
assert(*h->tailnextp == NULL);
31+
e->prevnextp = h->tailnextp;
32+
*h->tailnextp = elem;
33+
h->tailnextp = &e->next;
34+
e->next = NULL;
35+
assert(h->first != NULL);
36+
assert(*h->tailnextp == NULL);
37+
assert(*e->prevnextp == elem);
38+
}
39+
40+
void
41+
list_head_init(struct list_head *h)
42+
{
43+
h->first = NULL;
44+
h->tailnextp = &h->first;
45+
}

lib/list.h

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include "platform.h"
2+
3+
struct list_elem;
4+
5+
struct list_entry {
6+
struct list_elem *next;
7+
struct list_elem **prevnextp;
8+
};
9+
10+
struct list_head {
11+
struct list_elem *first;
12+
struct list_elem **tailnextp;
13+
};
14+
15+
void list_head_init(struct list_head *h);
16+
void list_remove(struct list_head *h, void *elem, struct list_entry *e);
17+
void list_insert_tail(struct list_head *h, void *elem, struct list_entry *e);
18+
19+
#define LIST_ENTRY(TYPE) \
20+
struct { \
21+
TYPE *next; \
22+
TYPE **prevnextp; \
23+
}
24+
25+
#define LIST_HEAD(TYPE) \
26+
struct { \
27+
TYPE *first; \
28+
TYPE **tailnextp; \
29+
}
30+
31+
#define LIST_FOREACH(VAR, HEAD, NAME) \
32+
for (VAR = (HEAD)->first; VAR != NULL; VAR = (VAR)->NAME.next)
33+
34+
#if defined(__clang__)
35+
#define CHECK_TYPE(a, b) \
36+
do { \
37+
__attribute__((__unused__)) __typeof__(a) __dummy = b; \
38+
} while (0)
39+
#else
40+
#define CHECK_TYPE(a, b)
41+
#endif
42+
43+
#define LIST_FIRST(HEAD) (HEAD)->first
44+
45+
#define LIST_EMPTY(HEAD) (LIST_FIRST(HEAD) == NULL)
46+
47+
#define LIST_REMOVE(HEAD, ELEM, NAME) \
48+
CHECK_TYPE(&(HEAD)->first, (HEAD)->tailnextp); \
49+
CHECK_TYPE((HEAD)->first, (ELEM)->NAME.next); \
50+
CHECK_TYPE(&(ELEM)->NAME.next, (ELEM)->NAME.prevnextp); \
51+
ctassert(sizeof(*(HEAD)) == sizeof(struct list_head)); \
52+
ctassert(sizeof((ELEM)->NAME) == sizeof(struct list_entry)); \
53+
list_remove((struct list_head *)(HEAD), (ELEM), \
54+
(struct list_entry *)&(ELEM)->NAME)
55+
56+
#define LIST_INSERT_TAIL(HEAD, ELEM, NAME) \
57+
CHECK_TYPE(&(HEAD)->first, (HEAD)->tailnextp); \
58+
CHECK_TYPE((HEAD)->first, (ELEM)->NAME.next); \
59+
CHECK_TYPE(&(ELEM)->NAME.next, (ELEM)->NAME.prevnextp); \
60+
ctassert(sizeof(*(HEAD)) == sizeof(struct list_head)); \
61+
ctassert(sizeof((ELEM)->NAME) == sizeof(struct list_entry)); \
62+
list_insert_tail((struct list_head *)(HEAD), (ELEM), \
63+
(struct list_entry *)&(ELEM)->NAME)
64+
65+
#define LIST_HEAD_INIT(HEAD) \
66+
CHECK_TYPE(&(HEAD)->first, (HEAD)->tailnextp); \
67+
ctassert(sizeof(*(HEAD)) == sizeof(struct list_head)); \
68+
list_head_init((struct list_head *)(HEAD))

0 commit comments

Comments
 (0)