diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-26 19:31:05 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-26 19:31:05 -0600 |
commit | f5da707e77ee954b12f3c961012e4f40fa4e1bd3 (patch) | |
tree | 6a9ddcdd487ee5c60f3c8570866b813e5fe74d9e /coroutine.c | |
parent | a9acf65bc8e3439d7fd2c927b2a920f120cb3a47 (diff) |
races
Diffstat (limited to 'coroutine.c')
-rw-r--r-- | coroutine.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/coroutine.c b/coroutine.c index f138fcf..12d4a25 100644 --- a/coroutine.c +++ b/coroutine.c @@ -154,10 +154,11 @@ enum coroutine_state { */ struct coroutine { - enum coroutine_state state; - jmp_buf env; - size_t stack_size; - void *stack; + volatile enum coroutine_state state; + volatile bool sig_unpause; + jmp_buf env; + size_t stack_size; + void *stack; }; static struct coroutine coroutine_table[CONFIG_COROUTINE_NUM] = {0}; @@ -213,8 +214,10 @@ static void call_with_stack(void *stack, cr_fn_t fn, void *args) { static const uint8_t stack_pattern[] = {0x1e, 0x15, 0x16, 0x0a, 0xcc, 0x52, 0x7e, 0xb7}; #endif +static void inline assert_cid(cid_t cid) { + assert(cid > 0); + assert(cid <= CONFIG_COROUTINE_NUM); #if CONFIG_COROUTINE_PROTECT_STACK -void assert_stack_protection(cid_t cid) { assert(coroutine_table[cid-1].stack_size); assert(coroutine_table[cid-1].stack); for (size_t i = 0; i < sizeof(stack_pattern); i++) { @@ -222,16 +225,12 @@ void assert_stack_protection(cid_t cid) { assert(((uint8_t*)coroutine_table[cid-1].stack)[i] == stack_pattern[i]); assert(((uint8_t*)coroutine_table[cid-1].stack)[j] == stack_pattern[j%sizeof(stack_pattern)]); } -} -#else -# define assert_stack_protection(cid) ((void)0) #endif +} #define assert_cid_state(cid, opstate) do { \ - assert((cid) > 0); \ - assert((cid) <= CONFIG_COROUTINE_NUM); \ + assert_cid(cid); \ assert(coroutine_table[(cid)-1].state opstate); \ - assert_stack_protection(cid); \ } while (0) cid_t coroutine_add_with_stack_size(size_t stack_size, cr_fn_t fn, void *args) { @@ -344,7 +343,6 @@ void cr_begin(void) { } static inline void _cr_transition(enum coroutine_state state) { - assert_cid_state(coroutine_running, == CR_RUNNING); debugf("cid=%zu: transition %i->%i\n", coroutine_running, coroutine_table[coroutine_running-1].state, state); coroutine_table[coroutine_running-1].state = state; @@ -352,8 +350,19 @@ static inline void _cr_transition(enum coroutine_state state) { longjmp(coroutine_main_env, 1); /* jump to point=b */ } -void cr_yield(void) { _cr_transition(CR_RUNNABLE); } -void cr_pause_and_yield(void) { _cr_transition(CR_PAUSED); } +void cr_yield(void) { + assert_cid_state(coroutine_running, == CR_RUNNING); + _cr_transition(CR_RUNNABLE); +} + +void cr_pause_and_yield(void) { + assert_cid_state(coroutine_running, == CR_RUNNING); + if (coroutine_table[cid-1].sig_unpause) + _cr_transition(CR_RUNNABLE); + else + _cr_transition(CR_PAUSED); + coroutine_table[cid-1].sig_unpause = false; +} void cr_exit(void) { assert_cid_state(coroutine_running, == CR_RUNNING); @@ -367,7 +376,21 @@ void cr_unpause(cid_t cid) { assert_cid_state(cid, == CR_PAUSED); debugf("cr_unpause(%zu)\n", cid); - coroutine_table[cid-1].state = CR_RUNNABLE; + coroutine_table[cid-1].sig_unpause = false; + coroutine_table[cid-1].state = CR_RUNNABLE; +} + +void cr_unpause_from_sighandler(cid_t cid) { + assert_cid(cid); + + switch (coroutine_table[cid-1].state) { + case CR_RUNNING: + coroutine_table[cid-1].sig_unpause = true; + case CR_PAUSED: + coroutine_table[cid-1].state = CR_RUNNABLE; + default: + assert(false); + } } cid_t cr_getcid(void) { |