diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-18 01:12:07 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-18 01:12:07 -0600 |
commit | 05ce08877ff420ca9fc77599dd947ff610d02cb0 (patch) | |
tree | 52ee0fbcd5ada2bb4725fce5c57f29863e17f7c9 /coroutine.c | |
parent | 52eb34af7be585c411a9a9ab39f0bea1d19e7d32 (diff) |
fixes
Diffstat (limited to 'coroutine.c')
-rw-r--r-- | coroutine.c | 31 |
1 files changed, 21 insertions, 10 deletions
diff --git a/coroutine.c b/coroutine.c index 9e0920d..6219883 100644 --- a/coroutine.c +++ b/coroutine.c @@ -109,20 +109,26 @@ void coroutine_main(void) { for (coroutine_running = 1;; coroutine_running = (coroutine_running%COROUTINE_NUM)+1) { if (coroutine_running == 1) ran = false; - if (coroutine_table[coroutine_running-1].state == CR_RUNNABLE) { - printf("running %zu...\n", coroutine_running); + struct coroutine *cr = &coroutine_table[coroutine_running-1]; + if (cr->state == CR_RUNNABLE) { ran = true; - coroutine_table[coroutine_running-1].state = CR_RUNNING; + cr->state = CR_RUNNING; if (!setjmp(coroutine_main_env)) { /* point=b */ - longjmp(coroutine_table[coroutine_running-1].env, 1); /* jump to point=c */ + longjmp(cr->env, 1); /* jump to point=c */ assert(false); /* should cr_exit() instead of returning */ } - if (coroutine_table[coroutine_running-1].state == CR_NONE) { - free(coroutine_table[coroutine_running-1].stack); + if (cr->state == CR_NONE) { +#if DEBUG + size_t stack_used = cr->stack_size; + while (stack_used > 0 && ((uint8_t*)cr->stack)[STACK_GROWS_DOWNWARD ? cr->stack_size - stack_used : stack_used - 1] == 0) + stack_used--; + printf("info: coroutine %zu exited having used %zu B stack space\n", coroutine_running, stack_used); +#endif + free(cr->stack); coroutine_table[coroutine_running-1] = (struct coroutine){0}; } } - if (coroutine_running == COROUTINE_NUM+1 && !ran) { + if (coroutine_running == COROUTINE_NUM && !ran) { fprintf(stderr, "error: no runnable coroutines\n"); return; } @@ -136,17 +142,22 @@ bool cr_begin(void) { longjmp(coroutine_add_env, 1); /* jump to point=a */ } -static inline void _cr_transition(enum coroutine_state state) { +static inline __attribute__ ((no_split_stack)) void _cr_transition(enum coroutine_state state) { assert(coroutine_table[coroutine_running-1].state == CR_RUNNING); coroutine_table[coroutine_running-1].state = state; - if (state == CR_NONE || !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 */ } -void cr_exit(void) { _cr_transition(CR_NONE); } void cr_yield(void) { _cr_transition(CR_RUNNABLE); } void cr_pause_and_yield(void) { _cr_transition(CR_PAUSED); } +void cr_exit(void) { + assert(coroutine_table[coroutine_running-1].state == CR_RUNNING); + coroutine_table[coroutine_running-1].state = CR_NONE; + longjmp(coroutine_main_env, 1); /* jump to point=b */ +} + void cr_unpause(cid_t cid) { assert(coroutine_table[cid-1].state == CR_PAUSED); coroutine_table[cid-1].state = CR_RUNNABLE; |