aboutsummaryrefslogtreecommitdiff
path: root/src/coro.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/coro.c')
-rw-r--r--src/coro.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/src/coro.c b/src/coro.c
new file mode 100644
index 0000000..4e651d3
--- /dev/null
+++ b/src/coro.c
@@ -0,0 +1,56 @@
+#include <u.h>
+
+// -----------------------------------------------------------------------
+// Assembly routines.
+
+extern void _newcoro(coro *co, uintptr (*func)(coro*, uintptr), void *stk);
+extern uintptr _coroyield(coro *co, uintptr arg);
+
+struct coro
+{
+ void* sp;
+ void* bp;
+ uintptr size;
+ void* user;
+};
+
+coro*
+coro·New(uintptr stk, uintptr (*func)(coro*, uintptr))
+{
+ if (!func) return nil;
+
+ if (stk == 0) stk = 8192;
+
+ byte *block = malloc(stk);
+ coro *co = (coro*)&block[stk - sizeof(coro)];
+ co->bp = block;
+ co->size = stk;
+
+ _newcoro(co, func, co);
+ return co;
+}
+
+error
+coro·Free(coro *co)
+{
+ enum
+ {
+ GOOD,
+ NIL,
+ EMPTY,
+ LOST,
+ };
+
+ if (!co) return NIL;
+ if (!co->bp) return LOST;
+ if (co->size == 0) return EMPTY;
+
+ free(co->bp);
+ return GOOD;
+}
+
+uintptr
+coro·Yield(coro *c, uintptr arg)
+{
+ return _coroyield(c, arg);
+}