diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-19 20:06:02 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-19 20:06:02 -0600 |
commit | 75fcb1ef5db5a2d6daaf02a0a02de037f5eaedff (patch) | |
tree | 402fcd7403db850236eab6d3aebf924ee8d16956 /coroutine.c | |
parent | 9c9e63fe8a49dd78bd6145060b15ae722d8ed1e2 (diff) |
comments
Diffstat (limited to 'coroutine.c')
-rw-r--r-- | coroutine.c | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/coroutine.c b/coroutine.c index 9a53731..50e4135 100644 --- a/coroutine.c +++ b/coroutine.c @@ -5,7 +5,7 @@ */ #include <stdint.h> /* for uint8_t */ -#include <stdio.h> /* for fprintf(), stderr */ +#include <stdio.h> /* for printf(), fprintf(), stderr */ #include <stdlib.h> /* for calloc(), free() */ #include <assert.h> #include <setjmp.h> @@ -104,6 +104,9 @@ * and a few bytes. */ +static jmp_buf coroutine_add_env; +static jmp_buf coroutine_main_env; + enum coroutine_state { CR_NONE = 0, /* this slot in the table is empty */ CR_INITIALIZING, /* running, before cr_begin() */ @@ -112,6 +115,23 @@ enum coroutine_state { CR_PAUSED, /* not running, and not runnable */ }; +/* + * Invariants (and non-invariants): + * + * - exactly 0 or 1 coroutines have state CR_INITIALIZING + * - exactly 0 or 1 coroutines have state CR_RUNNING + * - if coroutine_running is not zero, then + * coroutine_table[coroutine_running-1] is the currently-running + * coroutine + * - the coroutine_running coroutine either has state CR_RUNNING or + * CR_INITIALIZNG + * - a coroutine having state CR_RUNNING does *not* imply that + * coroutine_running points at that coroutine; if that coroutine is + * in the middle of coroutine_add(), it coroutine_running points at + * the CR_INITIALIZING child coroutine, while leaving the parent + * coroutine as CR_RUNNING. + */ + struct coroutine { enum coroutine_state state; jmp_buf env; @@ -121,8 +141,6 @@ struct coroutine { static struct coroutine coroutine_table[COROUTINE_NUM] = {0}; static cid_t coroutine_running = 0; -static jmp_buf coroutine_add_env; -static jmp_buf coroutine_main_env; static void call_with_stack(void *stack, cr_fn_t fn, void *args) { static void *saved_sp = NULL; @@ -247,7 +265,7 @@ bool cr_begin(void) { static inline __attribute__ ((no_split_stack)) void _cr_transition(enum coroutine_state state) { assert(coroutine_running && coroutine_table[coroutine_running-1].state == CR_RUNNING); coroutine_table[coroutine_running-1].state = state; - if (!setjmp(coroutine_table[coroutine_running-1].env)) /* point=c2 */ + if (!setjmp(coroutine_table[coroutine_running-1].env)) /* point=c2 */ longjmp(coroutine_main_env, 1); /* jump to point=b */ } @@ -261,7 +279,7 @@ void cr_exit(void) { } void cr_unpause(cid_t cid) { - assert(coroutine_table[cid-1].state == CR_PAUSED); + assert(cid && coroutine_table[cid-1].state == CR_PAUSED); coroutine_table[cid-1].state = CR_RUNNABLE; } |