From 3f27e5e6f12378eb70f78f056683287c961e3ffb Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sat, 30 Nov 2024 15:27:57 -0700 Subject: libcr: Log stack allocations --- libcr/coroutine.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'libcr') diff --git a/libcr/coroutine.c b/libcr/coroutine.c index dbeef12..c6e3d4c 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -524,8 +524,10 @@ cid_t coroutine_add_with_stack_size(size_t stack_size, 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); coroutine_table[child-1].stack = aligned_alloc(CR_PLAT_STACK_ALIGNMENT, stack_size); + infof("...done"); #if CONFIG_COROUTINE_MEASURE_STACK || CONFIG_COROUTINE_PROTECT_STACK for (size_t i = 0; i < stack_size; i++) ((uint8_t *)coroutine_table[child-1].stack)[i] = -- cgit v1.2.3-2-g168b From 92c0baf72135a3ad3c396d0897e8741fc552e490 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Mon, 2 Dec 2024 22:10:04 -0700 Subject: libcr: Pull out a _CR_SIG_SENTINEL --- libcr/coroutine.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'libcr') diff --git a/libcr/coroutine.c b/libcr/coroutine.c index c6e3d4c..3435bbb 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -151,11 +151,13 @@ /* For a signal to be *in* the mask means that the signal is * *blocked*. */ + #define _CR_SIG_SENTINEL SIGHUP + bool cr_is_in_intrhandler(void) { sigset_t cur_mask; sigfillset(&cur_mask); sigprocmask(0, NULL, &cur_mask); - if (sigismember(&cur_mask, SIGHUP)) + if (sigismember(&cur_mask, _CR_SIG_SENTINEL)) /* Interrupts are disabled, so we cannot be in * an interrupt handler. */ return false; @@ -169,7 +171,7 @@ sigset_t cur_mask; sigfillset(&cur_mask); sigprocmask(0, NULL, &cur_mask); - return !sigismember(&cur_mask, SIGHUP); + return !sigismember(&cur_mask, _CR_SIG_SENTINEL); } static inline void cr_plat_wait_for_interrupt(void) { @@ -187,7 +189,7 @@ sigset_t all, old; sigfillset(&all); sigprocmask(SIG_SETMASK, &all, &old); - return !sigismember(&old, SIGHUP); + return !sigismember(&old, _CR_SIG_SENTINEL); } void _cr_plat_enable_interrupts(void) { assert(!cr_is_in_intrhandler()); -- cgit v1.2.3-2-g168b From 22579175678b3aa4e96b2e1a0082f4804b754299 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sat, 7 Dec 2024 23:40:50 -0700 Subject: libcr: Move preprocessor macros up --- libcr/coroutine.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'libcr') diff --git a/libcr/coroutine.c b/libcr/coroutine.c index 3435bbb..b4306d9 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -128,8 +128,15 @@ * no longer exists. */ -#define ALWAYS_INLINE [[gnu::always_inline]] inline -#define NEVER_INLINE [[gnu::noinline]] +/* preprocessor macros ********************************************************/ + +/** Return `n` rounded up to the nearest multiple of `d` */ +#define ROUND_UP(n, d) ( ( ((n)+(d)-1) / (d) ) * (d) ) +#define ARRAY_LEN(arr) (sizeof(arr)/sizeof((arr)[0])) +#define NEXT_POWER_OF_2(x) ((1ULL)<<((sizeof(unsigned long long)*8)-__builtin_clzll(x))) + +#define ALWAYS_INLINE [[gnu::always_inline]] inline +#define NEVER_INLINE [[gnu::noinline]] /* platform support ***********************************************************/ @@ -357,13 +364,6 @@ } #endif -/* preprocessor macros ********************************************************/ - -/** Return `n` rounded up to the nearest multiple of `d` */ -#define ROUND_UP(n, d) ( ( ((n)+(d)-1) / (d) ) * (d) ) -#define ARRAY_LEN(arr) (sizeof(arr)/sizeof((arr)[0])) -#define NEXT_POWER_OF_2(x) ((1ULL)<<((sizeof(unsigned long long)*8)-__builtin_clzll(x))) - /* types **********************************************************************/ enum coroutine_state { -- cgit v1.2.3-2-g168b From ca4de2716c6fa4772228e8e8e051ef09c69907e2 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sat, 7 Dec 2024 23:43:12 -0700 Subject: libcr: Centralize the structure of plat_jmp_buf --- libcr/coroutine.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'libcr') diff --git a/libcr/coroutine.c b/libcr/coroutine.c index b4306d9..996262e 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -339,6 +339,9 @@ env->sp = cr_plat_get_sp(); #endif } + #if CONFIG_COROUTINE_MEASURE_STACK + static uintptr_t cr_plat_setjmp_get_sp(cr_plat_jmp_buf *env) { return env->sp; } + #endif /* cr_plat_setjmp *NEEDS* to be a preprocessor macro rather * than a real function, because [[gnu::returns_twice]] * doesn't work. @@ -741,9 +744,9 @@ void cr_cid_info(cid_t cid, struct cr_cid_info *ret) { if (cid == coroutine_running) sp = cr_plat_get_sp(); else if (coroutine_table[cid-1].state == CR_RUNNING) - sp = coroutine_add_env.sp; + sp = cr_plat_setjmp_get_sp(&coroutine_add_env); else - sp = coroutine_table[cid-1].env.sp; + 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 -- cgit v1.2.3-2-g168b From c4106766ecc2ebcca66d3d5b8408768b36a31122 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sat, 7 Dec 2024 23:45:09 -0700 Subject: libcr: Add cr_{set,long}jmp wrappers around the cr_plat_ variants --- libcr/coroutine.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'libcr') diff --git a/libcr/coroutine.c b/libcr/coroutine.c index 996262e..c446276 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -471,6 +471,9 @@ static inline cid_t coroutine_ringbuf_pop(void) { return coroutine_ringbuf.buf[coroutine_ringbuf.tail++ % ARRAY_LEN(coroutine_ringbuf.buf)]; } +#define cr_setjmp(env) cr_plat_setjmp(env) +#define cr_longjmp(env) cr_plat_longjmp(env, 1) + static inline void assert_cid(cid_t cid) { assert(cid > 0); assert(cid <= CONFIG_COROUTINE_NUM); @@ -547,7 +550,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 */ + if (!cr_setjmp(&coroutine_add_env)) { /* point=a */ void *stack_base = coroutine_table[child-1].stack #if CR_PLAT_STACK_GROWS_DOWNWARD + stack_size @@ -596,10 +599,10 @@ void coroutine_main(void) { cr_plat_wait_for_interrupt(); } - if (!cr_plat_setjmp(&coroutine_main_env)) { /* point=b */ + if (!cr_setjmp(&coroutine_main_env)) { /* point=b */ coroutine_running = next; coroutine_table[coroutine_running-1].state = CR_RUNNING; - cr_plat_longjmp(&coroutine_table[coroutine_running-1].env, 1); /* jump to point=c */ + cr_longjmp(&coroutine_table[coroutine_running-1].env); /* jump to point=c */ } /* This is where we jump to from cr_exit(), and from * nowhere else. */ @@ -623,8 +626,8 @@ void cr_begin(void) { bool saved = cr_save_and_disable_interrupts(); coroutine_table[coroutine_running-1].state = CR_RUNNABLE; coroutine_ringbuf_push(coroutine_running); - if (!cr_plat_setjmp(&coroutine_table[coroutine_running-1].env)) /* point=c1 */ - cr_plat_longjmp(&coroutine_add_env, 1); /* jump to point=a */ + if (!cr_setjmp(&coroutine_table[coroutine_running-1].env)) /* point=c1 */ + cr_longjmp(&coroutine_add_env); /* jump to point=a */ cr_restore_interrupts(saved); } @@ -641,10 +644,10 @@ static inline void _cr_yield() { return; } - if (!cr_plat_setjmp(&coroutine_table[coroutine_running-1].env)) { /* point=c2 */ + if (!cr_setjmp(&coroutine_table[coroutine_running-1].env)) { /* point=c2 */ coroutine_running = next; coroutine_table[coroutine_running-1].state = CR_RUNNING; - cr_plat_longjmp(&coroutine_table[coroutine_running-1].env, 1); /* jump to point=c */ + cr_longjmp(&coroutine_table[coroutine_running-1].env); /* jump to point=c */ } } @@ -678,7 +681,7 @@ void cr_pause_and_yield(void) { (void)cr_save_and_disable_interrupts(); coroutine_table[coroutine_running-1].state = CR_NONE; - cr_plat_longjmp(&coroutine_main_env, 1); /* jump to point=b */ + cr_longjmp(&coroutine_main_env); /* jump to point=b */ } static void _cr_unpause(cid_t cid) { -- cgit v1.2.3-2-g168b From b9ebe41358244caa9334e72ca4e3c8c7a14c86e7 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sat, 7 Dec 2024 23:50:28 -0700 Subject: Fix libcr gdb integration? --- libcr/coroutine.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 8 deletions(-) (limited to 'libcr') diff --git a/libcr/coroutine.c b/libcr/coroutine.c index c446276..a947ae9 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -135,6 +135,8 @@ #define ARRAY_LEN(arr) (sizeof(arr)/sizeof((arr)[0])) #define NEXT_POWER_OF_2(x) ((1ULL)<<((sizeof(unsigned long long)*8)-__builtin_clzll(x))) +#define UNUSED(name) + #define ALWAYS_INLINE [[gnu::always_inline]] inline #define NEVER_INLINE [[gnu::noinline]] @@ -158,7 +160,10 @@ /* For a signal to be *in* the mask means that the signal is * *blocked*. */ - #define _CR_SIG_SENTINEL SIGHUP + #define _CR_SIG_SENTINEL SIGURG + #if CONFIG_COROUTINE_GDB + #define _CR_SIG_GDB SIGWINCH + #endif bool cr_is_in_intrhandler(void) { sigset_t cur_mask; @@ -205,6 +210,19 @@ sigemptyset(&zero); sigprocmask(SIG_SETMASK, &zero, NULL); } + #if CONFIG_COROUTINE_GDB + static void _cr_gdb_intrhandler(int UNUSED(sig)) {} + #endif + static void cr_plat_init(void) { + #if CONFIG_COROUTINE_GDB + int r; + struct sigaction action = { + .sa_handler = _cr_gdb_intrhandler, + }; + r = sigaction(_CR_SIG_GDB, &action, NULL); + assert(r == 0); + #endif + } #elif __ARM_ARCH_6M__ && __ARM_EABI__ bool cr_is_in_intrhandler(void) { uint32_t isr_number; @@ -242,6 +260,7 @@ assert(!_cr_plat_are_interrupts_enabled()); asm volatile ("cpsie i"); } + static void cr_plat_init(void) {} #else #error unsupported platform (not __unix__, not __ARM_ARCH_6M__ && __ARM_EABI__) #endif @@ -327,14 +346,7 @@ uintptr_t sp; #endif } cr_plat_jmp_buf; - #if CONIG_COROUTINE_GDB - NEVER_INLINE - #endif static void _cr_plat_setjmp_pre(cr_plat_jmp_buf *env [[gnu::unused]]) { - #if CONIG_COROUTINE_GDB - /* Prevent the call from being optimized away. */ - asm (""); - #endif #if CONFIG_COROUTINE_MEASURE_STACK env->sp = cr_plat_get_sp(); #endif @@ -415,8 +427,12 @@ static const uint8_t stack_pattern[] = { /* global variables ***********************************************************/ +static bool coroutine_initialized = false; static cr_plat_jmp_buf coroutine_add_env; static cr_plat_jmp_buf coroutine_main_env; +#if CONFIG_COROUTINE_GDB +static cr_plat_jmp_buf coroutine_gdb_env; +#endif /* * Invariants (and non-invariants): @@ -471,7 +487,26 @@ static inline cid_t coroutine_ringbuf_pop(void) { return coroutine_ringbuf.buf[coroutine_ringbuf.tail++ % ARRAY_LEN(coroutine_ringbuf.buf)]; } +#if CONFIG_COROUTINE_GDB +NEVER_INLINE void cr_gdb_breakpoint(void) { + /* Prevent the call from being optimized away. */ + asm (""); +} +NEVER_INLINE void cr_gdb_readjmp(cr_plat_jmp_buf *env) { + if (!cr_plat_setjmp(&coroutine_gdb_env)) + cr_plat_longjmp(env, 2); +} +#define cr_setjmp(env) ({ \ + int val = cr_plat_setjmp(env); \ + if (val == 2) { \ + cr_gdb_breakpoint(); \ + cr_plat_longjmp(&coroutine_gdb_env, 1); \ + } \ + val; \ + }) +#else #define cr_setjmp(env) cr_plat_setjmp(env) +#endif #define cr_longjmp(env) cr_plat_longjmp(env, 1) static inline void assert_cid(cid_t cid) { @@ -511,6 +546,11 @@ cid_t coroutine_add_with_stack_size(size_t stack_size, debugf("coroutine_add_with_stack_size(%zu, \"%s\", %p, %p)...", stack_size, name, fn, args); + if (!coroutine_initialized) { + cr_plat_init(); + coroutine_initialized = true; + } + cid_t child; { size_t base = last_created; @@ -587,6 +627,10 @@ cid_t coroutine_add(const char *name, cr_fn_t fn, void *args) { void coroutine_main(void) { debugf("coroutine_main()"); + if (!coroutine_initialized) { + cr_plat_init(); + coroutine_initialized = true; + } bool saved = cr_save_and_disable_interrupts(); assert(saved); assert(!cr_is_in_intrhandler()); -- cgit v1.2.3-2-g168b