diff options
-rw-r--r-- | libcr/coroutine.c | 8 | ||||
-rw-r--r-- | libcr/include/libcr/coroutine.h | 4 | ||||
-rw-r--r-- | libcr/tests/test_matrix.c | 10 |
3 files changed, 15 insertions, 7 deletions
diff --git a/libcr/coroutine.c b/libcr/coroutine.c index 76d21f3..18b2b80 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -434,6 +434,7 @@ static struct { cid_t buf[NEXT_POWER_OF_2(CONFIG_COROUTINE_NUM)]; } coroutine_ringbuf = {0}; static cid_t coroutine_running = 0; +static size_t coroutine_cnt = 0; /* utility functions **********************************************************/ @@ -527,6 +528,7 @@ cid_t coroutine_add_with_stack_size(size_t stack_size, coroutine_running = child; coroutine_table[child-1].state = CR_INITIALIZING; + coroutine_cnt++; if (!cr_plat_setjmp(&coroutine_add_env)) { /* point=a */ void *stack_base = coroutine_table[child-1].stack #if CR_PLAT_STACK_GROWS_DOWNWARD @@ -562,13 +564,13 @@ cid_t coroutine_add(const char *name, cr_fn_t fn, void *args) { /* coroutine_main() ***********************************************************/ -[[noreturn]] void coroutine_main(void) { +void coroutine_main(void) { debugf("coroutine_main()"); bool saved = cr_save_and_disable_interrupts(); assert(saved); assert(!cr_is_in_intrhandler()); coroutine_running = 0; - for (;;) { + while (coroutine_cnt) { cid_t next; while ( !((next = coroutine_ringbuf_pop())) ) { /* No coroutines are runnable, wait for an interrupt @@ -589,7 +591,9 @@ cid_t coroutine_add(const char *name, cr_fn_t fn, void *args) { #endif free(coroutine_table[coroutine_running-1].stack); coroutine_table[coroutine_running-1] = (struct coroutine){0}; + coroutine_cnt--; } + cr_restore_interrupts(saved); } /* cr_*() *********************************************************************/ diff --git a/libcr/include/libcr/coroutine.h b/libcr/include/libcr/coroutine.h index 86b8452..f6c5e14 100644 --- a/libcr/include/libcr/coroutine.h +++ b/libcr/include/libcr/coroutine.h @@ -93,9 +93,9 @@ cid_t coroutine_add_with_stack_size(size_t stack_size, const char *name, cr_fn_t cid_t coroutine_add(const char *name, cr_fn_t fn, void *args); /** - * The main scheduler loop. + * The main scheduler loop. Returns if all coroutines exit. */ -[[noreturn]] void coroutine_main(void); +void coroutine_main(void); /* inside of coroutines *******************************************************/ diff --git a/libcr/tests/test_matrix.c b/libcr/tests/test_matrix.c index f1aa6fe..1f23455 100644 --- a/libcr/tests/test_matrix.c +++ b/libcr/tests/test_matrix.c @@ -4,17 +4,21 @@ * SPDX-License-Identifier: AGPL-3.0-or-later */ -#include <stdlib.h> /* for exit(3) */ - #include <libcr/coroutine.h> +int a = 1; + COROUTINE cr_init(void *) { cr_begin(); - exit(0); + a = 2; cr_end(); } int main() { coroutine_add("init", cr_init, NULL); coroutine_main(); + if (a != 2) + return 1; + coroutine_main(); + return 0; } |