From 392c9aff947a41e7e0da0b1a9612e174cfa956a7 Mon Sep 17 00:00:00 2001 From: Nicholas Noll Date: Sat, 18 Apr 2020 13:30:03 -0700 Subject: test: added prime sieve test of coroutines --- src/coro.c | 15 ++++++-- src/coro_unix_x64.s | 39 +++++++++++--------- src/rules.mk | 14 +++++-- src/test.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 146 insertions(+), 25 deletions(-) create mode 100644 src/test.c (limited to 'src') diff --git a/src/coro.c b/src/coro.c index 82ef4f4..af0a359 100644 --- a/src/coro.c +++ b/src/coro.c @@ -1,11 +1,20 @@ #include // ----------------------------------------------------------------------- -// Assembly routines. +// Assembly routines extern void _newcoro(coro *co, uintptr (*func)(coro*, uintptr), void *stk); extern uintptr _coroyield(coro *co, uintptr arg); +// ----------------------------------------------------------------------- +// Globals + +// static thread_local coro *CONTEXT; + +// ----------------------------------------------------------------------- +// C interface + +/* Co-routine context */ struct coro { void* sp; @@ -17,9 +26,7 @@ struct coro coro* coro·new(uintptr stk, uintptr (*func)(coro*, uintptr)) { - if (!func) - return nil; - + if (!func) return nil; if (stk == 0) stk = 8192; byte *block = malloc(stk); diff --git a/src/coro_unix_x64.s b/src/coro_unix_x64.s index 98710c2..d7de2a2 100644 --- a/src/coro_unix_x64.s +++ b/src/coro_unix_x64.s @@ -36,9 +36,9 @@ rerun: ; func(R7, R6, R2, R1, R8, R9, Z0-7): R0 ; ; # Stack layout of an in-flight coro -; ^coro -; ^func -; ^bp (base pointer of stack) +; *coro +; *func +; *bp (base pointer of stack) ; ....... STACK ......... ; Saved Clobbers ; @@ -57,31 +57,33 @@ rerun: ; R14 [1] ; R15 [0] -%define WORDS 8 -%define SAVES 9 +%define WORDSZ 8 +%define NSAVES 9 -; func sys.newCoro(co ^coro, fn func, bp ^stack) +; coro *coro·new(co *coro, fn func, bp *stack) _newcoro: - lea R0, [coroinit] - lea R1, [R2 - SAVES*WORDS] + lea R0, [coroinit] ; Store address of init function + lea R1, [R2 - NSAVES*WORDSZ] ; Store offset address of stack - mov [R1 + 8*WORDS], R7 - mov [R1 + 7*WORDS], R6 - mov [R1 + 6*WORDS], R0 - mov [R1 + 5*WORDS], R2 + mov [R1 + 8*WORDSZ], R7 ; Store context pointer + mov [R1 + 7*WORDSZ], R6 ; Store function pointer + mov [R1 + 6*WORDSZ], R0 ; Store initializer pointer + mov [R1 + 5*WORDSZ], R2 ; Store stack base pointer xor R0, R0 + ; Start of mutable stack ; Blank out the clobbers - mov [R1 + 4*WORDS], R0 ; R3 - mov [R1 + 3*WORDS], R0 ; R12 - mov [R1 + 2*WORDS], R0 ; R13 - mov [R1 + 1*WORDS], R0 ; R14 - mov [R1 + 0*WORDS], R0 ; R15 + mov [R1 + 4*WORDSZ], R0 ; R3 + mov [R1 + 3*WORDSZ], R0 ; R12 + mov [R1 + 2*WORDSZ], R0 ; R13 + mov [R1 + 1*WORDSZ], R0 ; R14 + mov [R1 + 0*WORDSZ], R0 ; R15 mov [R7], R1 ret +; Saves register state %macro pushclobs 0 push RBP push R3 @@ -91,6 +93,7 @@ _newcoro: push R15 %endmacro +; Restores register state %macro popclobs 0 pop R15 pop R14 @@ -100,7 +103,7 @@ _newcoro: pop RBP %endmacro -; func coro.yield(co ^coro, ret uintptr) +; uintptr coro.yield(co *coro, data uintptr) _coroyield: pushclobs mov R0, R6 ; Move return value into return register. diff --git a/src/rules.mk b/src/rules.mk index ef9b36c..b9efc37 100644 --- a/src/rules.mk +++ b/src/rules.mk @@ -4,9 +4,11 @@ DIRSTACK_$(SP) := $(d) d := $(DIR) # Iterate through subdirectory tree +DIR := $(d)/bufio +include $(DIR)/rules.mk # ... -# Local variables +# Local sources SRCS_$(d) := $(wildcard $(d)/*.c) ASMS_$(d) := $(wildcard $(d)/*.s) OBJS_$(d) := $(SRCS_$(d):.c=.o) @@ -17,11 +19,14 @@ DEPS_$(d) := $(OBJS_$(d):.o=.d) OBJS := $(OBJS) $(OBJS_$(d)) DEPS := $(DEPS) $(DEPS_$(d)) +# Local targets LIBS_$(d) := $(d)/libnbn.a LIBS_$(d) := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(LIBS_$(d))) -BINS_$(d) := +LIBS := $(LIBS) $(LIBS_$(d)) -LIBS := $(LIBS) $(LIBS_$(d)) +BINS_$(d) := $(d)/test +BINS_$(d) := $(patsubst $(SRC_DIR)/%, $(OBJ_DIR)/%, $(BINS_$(d))) +BINS := $(BINS) $(BINS_$(d)) # Local rules # $(LIBS_$(d)) := TGTFLAGS := @@ -31,6 +36,9 @@ LIBS := $(LIBS) $(LIBS_$(d)) $(LIBS_$(d)): $(OBJS_$(d)) $(ARCHIVE) +$(BINS_$(d)): $(OBJ_DIR)/test.o + $(LINK) + # ---- Pop off stack ---- -include $(DEPS_$(d)) diff --git a/src/test.c b/src/test.c new file mode 100644 index 0000000..e9743cb --- /dev/null +++ b/src/test.c @@ -0,0 +1,103 @@ +#include + +uintptr +printtest(coro *c, uintptr d) +{ + printf("--> Recieved %lu\n", d); + d = coro·yield(c, d+10); + printf("--> Now %lu\n", d); + + return d; +} + +uintptr +sequence(coro *c, uintptr start) +{ + int d = start; + for (;;) { + coro·yield(c, d++); + } + + return d; +} + +struct PrimeMsg +{ + coro *seq; + int p; +}; + +uintptr +filter(coro *c, uintptr data) +{ + int x, p; + coro *seq; + struct PrimeMsg *msg; + + msg = (struct PrimeMsg*)data; + seq = msg->seq; + p = msg->p; + + for (;;) { + x = coro·yield(seq, x); + if (x % p != 0) { + x = coro·yield(c, x); + } + } + + return 0; +} + +int +main() +{ + int i; + coro *c[4]; + uintptr d; + + printf("Starting singleton test\n"); + + for (i = 0; i < arrlen(c); i++) { + c[i] = coro·new(0, &printtest); + } + + /* Singleton test */ + d = 0; + for (i = 0; i < 10; i++) { + d = coro·yield(c[0], d); + } + + printf("Starting triplet test\n"); + + /* Triplet test */ + for (i = 0; i < 10; i++) { + d = coro·yield(c[1], d); + d = coro·yield(c[2], d+100); + d = coro·yield(c[3], d+200); + } + + for (i = 0; i < arrlen(c); i++) { + coro·free(c[i]); + } + + /* Prime sieve */ + printf("Starting prime test\n"); + uintptr num; + coro *cur, *seq[50]; + + num = 2; + seq[0] = coro·new(4096, &sequence); + cur = *seq; + + num = coro·yield(cur, num); + for (i = 1; i < arrlen(seq); i++) { + seq[i] = coro·new(4096, &filter); + struct PrimeMsg msg = { + .seq = cur, + .p = num, + }; + cur = seq[i]; + num = coro·yield(cur, (uintptr)&msg); + printf("--> prime number %lu\n", num); + } +} -- cgit v1.2.1