summaryrefslogtreecommitdiff
path: root/libcr/coroutine.c
diff options
context:
space:
mode:
Diffstat (limited to 'libcr/coroutine.c')
-rw-r--r--libcr/coroutine.c105
1 files changed, 68 insertions, 37 deletions
diff --git a/libcr/coroutine.c b/libcr/coroutine.c
index 708e2ea..c6eeb43 100644
--- a/libcr/coroutine.c
+++ b/libcr/coroutine.c
@@ -387,23 +387,24 @@ static_assert(CONFIG_COROUTINE_NUM > 1);
/* types **********************************************************************/
-enum coroutine_state {
- CR_NONE = 0, /* this slot in the table is empty */
- CR_INITIALIZING, /* running, before cr_begin() */
- CR_RUNNING, /* running, after cr_begin() */
- CR_RUNNABLE, /* not running, but runnable */
- CR_PAUSED, /* not running, and not runnable */
-};
-
struct coroutine {
+ /* 1. state *************************************************/
volatile enum coroutine_state state;
- cr_plat_jmp_buf env;
+
+ /* 2. name **************************************************/
+ [[gnu::nonstring]] char name[CONFIG_COROUTINE_NAME_LEN];
+
+ /* 3. stack *************************************************/
+ /* stack_size *includes* CR_STACK_GUARD at each end. */
size_t stack_size;
+ /* stack is the bottom of the CR_STACK_GUARD at the bottom of the stack. */
void *stack;
#if CONFIG_COROUTINE_VALGRIND
unsigned stack_id;
#endif
- [[gnu::nonstring]] char name[CONFIG_COROUTINE_NAME_LEN];
+
+ /* 4. env ***************************************************/
+ cr_plat_jmp_buf env;
};
/* constants ******************************************************************/
@@ -476,11 +477,6 @@ static size_t coroutine_cnt = 0;
/* utility functions **********************************************************/
-static inline const char* coroutine_state_str(enum coroutine_state state) {
- assert(state < LM_ARRAY_LEN(coroutine_state_strs));
- return coroutine_state_strs[state];
-}
-
static inline void coroutine_ringbuf_push(cid_t val) {
coroutine_ringbuf.buf[coroutine_ringbuf.head++ % LM_ARRAY_LEN(coroutine_ringbuf.buf)] = val;
assert((coroutine_ringbuf.head % LM_ARRAY_LEN(coroutine_ringbuf.buf)) !=
@@ -576,37 +572,43 @@ cid_t coroutine_add_with_stack_size(size_t stack_size,
return 0;
debugf("...child=%zu", child);
+ /* 1. state *************************************************/
+ coroutine_table[child-1].state = CR_INITIALIZING;
+
+ /* 2. name **************************************************/
if (name)
strncpy(coroutine_table[child-1].name, name, sizeof(coroutine_table[child-1].name));
else
memset(coroutine_table[child-1].name, 0, sizeof(coroutine_table[child-1].name));
- coroutine_table[child-1].stack_size = stack_size;
- infof("allocing \"%s\" stack with size %zu", name, stack_size);
+ /* 3. stack *************************************************/
+ coroutine_table[child-1].stack_size = stack_size + 2*CR_STACK_GUARD_SIZE;
+ infof("allocing \"%s\" stack with size %zu+2*%zu=%zu",
+ name, stack_size, CR_STACK_GUARD_SIZE, coroutine_table[child-1].stack_size);
coroutine_table[child-1].stack =
- aligned_alloc(CR_PLAT_STACK_ALIGNMENT, stack_size);
- infof("...done");
+ aligned_alloc(CR_PLAT_STACK_ALIGNMENT, coroutine_table[child-1].stack_size);
+ infof("... done, stack is [%#zx,%#zx)",
+ coroutine_table[child-1].stack + CR_STACK_GUARD_SIZE,
+ coroutine_table[child-1].stack + CR_STACK_GUARD_SIZE + stack_size);
#if CONFIG_COROUTINE_MEASURE_STACK || CONFIG_COROUTINE_PROTECT_STACK
- for (size_t i = 0; i < stack_size; i++)
+ for (size_t i = 0; i < coroutine_table[child-1].stack_size; i++)
((uint8_t *)coroutine_table[child-1].stack)[i] =
stack_pattern[i%sizeof(stack_pattern)];
#endif
#if CONFIG_COROUTINE_VALGRIND
coroutine_table[child-1].stack_id = VALGRIND_STACK_REGISTER(
coroutine_table[child-1].stack + CR_STACK_GUARD_SIZE,
- coroutine_table[child-1].stack + stack_size - CR_STACK_GUARD_SIZE);
+ coroutine_table[child-1].stack + CR_STACK_GUARD_SIZE + stack_size);
#endif
+ /* 4. env ***************************************************/
coroutine_running = child;
- coroutine_table[child-1].state = CR_INITIALIZING;
coroutine_cnt++;
if (!cr_setjmp(&coroutine_add_env)) { /* point=a */
void *stack_base = coroutine_table[child-1].stack
+ + CR_STACK_GUARD_SIZE
#if CR_PLAT_STACK_GROWS_DOWNWARD
+ stack_size
- - CR_STACK_GUARD_SIZE
-#else
- + CR_STACK_GUARD_SIZE
#endif
;
debugf("...stack =%p", coroutine_table[child-1].stack);
@@ -785,20 +787,35 @@ void cr_assert_in_intrhandler(void) {
}
#endif
-/* cr_cid_info() **************************************************************/
-
-#if CONFIG_COROUTINE_MEASURE_STACK
+/* answering questions about coroutines ***************************************/
void cr_cid_info(cid_t cid, struct cr_cid_info *ret) {
- assert_cid(cid);
+ assert(cid > 0);
+ assert(cid <= CONFIG_COROUTINE_NUM);
assert(ret);
+ memset(ret, 0, sizeof(*ret));
+ if (coroutine_table[cid-1].state == CR_NONE)
+ return;
+ assert_cid(cid);
+
+ /* 1. state *************************************************/
+ ret->state = coroutine_table[cid-1].state;
+
+ /* 2. name **************************************************/
+ memcpy(ret->name, coroutine_table[cid-1].name, CONFIG_COROUTINE_NAME_LEN);
+
+ /* 3. stack *************************************************/
+#if CONFIG_COROUTINE_MEASURE_STACK
+ uint8_t *stack = (uint8_t *)coroutine_table[cid-1].stack;
+ uint8_t *stack_lo = stack + CR_STACK_GUARD_SIZE;
+ uint8_t *stack_hi = stack + coroutine_table[cid-1].stack_size - CR_STACK_GUARD_SIZE;
+
/* stack_cap */
- ret->stack_cap = coroutine_table[cid-1].stack_size - 2*CR_STACK_GUARD_SIZE;
+ ret->stack_cap = stack_hi - stack_lo;
/* stack_max */
ret->stack_max = ret->stack_cap;
- uint8_t *stack = (uint8_t *)coroutine_table[cid-1].stack;
for (;;) {
size_t i =
#if CR_PLAT_STACK_GROWS_DOWNWARD
@@ -807,8 +824,17 @@ void cr_cid_info(cid_t cid, struct cr_cid_info *ret) {
ret->stack_max - 1 - CR_STACK_GUARD_SIZE
#endif
;
- if (ret->stack_max == 0 ||
- stack[i] != stack_pattern[i%sizeof(stack_pattern)])
+ if (ret->stack_max == 0)
+ break;
+ assert(stack_lo <= &stack[i] && &stack[i] < stack_hi);
+#if CONFIG_COROUTINE_VALGRIND
+ VALGRIND_DISABLE_ERROR_REPORTING;
+#endif
+ uint8_t v = stack[i];
+#if CONFIG_COROUTINE_VALGRIND
+ VALGRIND_ENABLE_ERROR_REPORTING;
+#endif
+ if (v != stack_pattern[i%sizeof(stack_pattern)])
break;
ret->stack_max--;
}
@@ -822,12 +848,17 @@ void cr_cid_info(cid_t cid, struct cr_cid_info *ret) {
else
sp = cr_plat_setjmp_get_sp(&coroutine_table[cid-1].env);
assert(sp);
- uintptr_t sb = (uintptr_t)coroutine_table[cid-1].stack;
#if CR_PLAT_STACK_GROWS_DOWNWARD
- ret->stack_cur = (sb - CR_STACK_GUARD_SIZE) - sp;
+ uintptr_t sb = (uintptr_t)stack_hi;
+ ret->stack_cur = sb - sp;
#else
- ret->stack_cur = sp - (sb + CR_STACK_GUARD_SIZE);
+ uintptr_t sb = (uintptr_t)stack_lo;
+ ret->stack_cur = sp - sb;
#endif
+#endif /* CONFIG_COROUTINE_MEASURE_STACK */
}
-#endif /* CONFIG_COROUTINE_MEASURE_STACK */
+const char *coroutine_state_str(enum coroutine_state state) {
+ assert(state < LM_ARRAY_LEN(coroutine_state_strs));
+ return coroutine_state_strs[state];
+}