summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libcr/coroutine.c8
-rw-r--r--libcr/include/libcr/coroutine.h4
-rw-r--r--libcr/tests/test_matrix.c10
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;
}