/* coroutine.c - Simple coroutine and request/response implementation * * Copyright (C) 2024 Luke T. Shumaker * SPDX-Licence-Identifier: AGPL-3.0-or-later */ #include #include /* for malloc(pico_malloc) and realloc(pico_malloc) */ #include "coroutine.h" static cid_t coroutine_table_len = 0; _cr_entry_t *_coroutine_table = NULL; cid_t _cur_cid = 0; void coroutine_init(void) { printf("coroutine_table_len = %u\n", (int)coroutine_table_len); if (coroutine_table_len) { printf("return\n"); return; } coroutine_table_len = 1; printf("coroutine_table_len = %u\n", (int)coroutine_table_len); _coroutine_table = malloc(sizeof _coroutine_table[0]); _coroutine_table[0] = (_cr_entry_t){ .fn = (cr_fn_t)0xDEAD, .stack = NULL, .state = 0, .blocked = true, }; } cid_t coroutine_add(cr_fn_t fn, void *stack) { cid_t cid = 0; for (cid_t i = 1; cid == 0 && i < coroutine_table_len; i++) if (_coroutine_table[i].fn == NULL) cid = i; if (cid == 0) { cid = coroutine_table_len++; _coroutine_table = realloc(_coroutine_table, (sizeof _coroutine_table[0]) * coroutine_table_len); } _coroutine_table[cid] = (_cr_entry_t){ .fn = fn, .stack = stack, .state = 0, .blocked = false, }; printf("added coroutine %u\n", (int)cid); return cid; } void coroutine_task(void) { cid_t start = (_cur_cid + 1) % coroutine_table_len; cid_t shift; for (shift = 0; shift < coroutine_table_len && (_coroutine_table[(start+shift)%coroutine_table_len].fn == NULL || _coroutine_table[(start+shift)%coroutine_table_len].blocked); shift++) {} if (shift == coroutine_table_len) { printf("idle\n"); return; } _cur_cid = (start + shift) % coroutine_table_len; printf("running %u\n", (int)_cur_cid); if (_cur_cid == 0) exit(1); _coroutine_table[_cur_cid].fn(_coroutine_table[_cur_cid].stack); }