diff options
Diffstat (limited to 'sys/libn/coro.c')
-rw-r--r-- | sys/libn/coro.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/sys/libn/coro.c b/sys/libn/coro.c new file mode 100644 index 0000000..af0a359 --- /dev/null +++ b/sys/libn/coro.c @@ -0,0 +1,65 @@ +#include <u.h> + +// ----------------------------------------------------------------------- +// 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; + 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 + { + NIL, + GOOD, + 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); +} |