aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorNicholas Noll <nbnoll@eml.cc>2020-04-18 13:30:03 -0700
committerNicholas Noll <nbnoll@eml.cc>2020-04-18 13:30:03 -0700
commit392c9aff947a41e7e0da0b1a9612e174cfa956a7 (patch)
treeae45404b07da46490c6dcd0a09b82fd3a3dcf2e3 /src
parent1d188c4f816fce8728fdffaa7ad6ef205ca05abd (diff)
test: added prime sieve test of coroutines
Diffstat (limited to 'src')
-rw-r--r--src/coro.c15
-rw-r--r--src/coro_unix_x64.s39
-rw-r--r--src/rules.mk14
-rw-r--r--src/test.c103
4 files changed, 146 insertions, 25 deletions
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 <u.h>
// -----------------------------------------------------------------------
-// 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 <u.h>
+
+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);
+ }
+}