summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-19 20:06:02 -0600
committerLuke T. Shumaker <lukeshu@lukeshu.com>2024-09-19 20:06:02 -0600
commit75fcb1ef5db5a2d6daaf02a0a02de037f5eaedff (patch)
tree402fcd7403db850236eab6d3aebf924ee8d16956
parent9c9e63fe8a49dd78bd6145060b15ae722d8ed1e2 (diff)
comments
-rw-r--r--coroutine.c28
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;
}