From 58986ed5316acc6d6077541b7b6e754390069d73 Mon Sep 17 00:00:00 2001 From: "Luke T. Shumaker" Date: Sun, 17 Nov 2024 21:58:14 -0700 Subject: libcr: Fixups --- libcr/coroutine.c | 47 ++++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 19 deletions(-) diff --git a/libcr/coroutine.c b/libcr/coroutine.c index a468df0..252eca2 100644 --- a/libcr/coroutine.c +++ b/libcr/coroutine.c @@ -51,8 +51,9 @@ * - It has a small bit of platform-specific code in the "platform * support" section. Other than this, it should be portable to * other platforms CPUs. It currently contains implementations for - * __x86_64__ (assumes POSIX) and __arm__ (assumes bare-metal), and - * should be fairly easy to add implementations for other platforms. + * __unix__ and __ARM_EABI__ "operating systems" on __x86_64__ and + * __ARM_ARCH_6M__ CPUs, and should be fairly easy to add + * implementations for other platforms. * * - It uses setjmp()/longjmp() in "unsafe" ways. POSIX-2017 * longjmp(3p) says @@ -136,10 +137,10 @@ * Wrappers for setjmp()/longjmp() that do *not* save the * interrupt mask. */ #if __unix__ - /* On a *NIX OS, we use signals as interrupts. POSIX leaves - * it implementation-defined whether setjmp()/longjmp() save - * the signal mask; while glibc does not save it, let's not - * rely on that. */ + /* On __unix__, we use POSIX real-time signals as interrupts. + * POSIX leaves it implementation-defined whether + * setjmp()/longjmp() save the signal mask; while glibc does + * not save it, let's not rely on that. */ #define cr_plat_setjmp(env) sigsetjmp(env, 0) #define cr_plat_longjmp(env, val) siglongjmp(env, val) #elif __NEWLIB__ @@ -159,10 +160,12 @@ /* For a signal to be *in* the mask means that the signal is * *blocked*. */ + static inline void cr_plat_wait_for_interrupt(void) { sigset_t set; sigemptyset(&set); sigsuspend(&set); + sigfillset(&set); sigprocmask(SIG_SETMASK, &set, NULL); } @@ -177,8 +180,7 @@ sigemptyset(&zero); sigprocmask(SIG_SETMASK, &zero, NULL); } -#elif __arm__ - /* Assume bare-metal if !__unix__. */ +#elif __ARM_ARCH_6M__ && __ARM_EABI__ static ALWAYS_INLINE void cr_plat_wait_for_interrupt(void) { asm volatile ("wfi":::"memory"); } @@ -186,20 +188,20 @@ uint32_t primask; asm volatile ("mrs %0, PRIMASK\n" "cpsid i" - : /* %0 */"=r"(primask) + : /* %0 */"=l"(primask) ); return primask == 0; } void _cr_plat_enable_interrupts(void) { - asm volatile ("cpsie i":::"memory"); + asm volatile ("cpsie i"); } #else - #error unsupported platform (not __unix__, not bare-metal __arm__) + #error unsupported platform (not __unix__, not __ARM_ARCH_6M__ && __ARM_EABI__) #endif /*==================================================================== * Stack management routines. */ -#if __arm__ +#if __ARM_ARCH_6M__ #define CR_PLAT_STACK_GROWS_DOWNWARD 1 #if CONFIG_COROUTINE_MEASURE_STACK @@ -225,9 +227,9 @@ "mov sp, r0" /* ] */ : : /* %0 */"m"(saved_sp), - /* %1 */"r"(stack), - /* %2 */"r"(fn), - /* %3 */"r"(args) + /* %1 */"l"(stack), + /* %2 */"l"(fn), + /* %3 */"l"(args) : "r0" ); } @@ -259,7 +261,7 @@ ); } #else - #error unsupported platform (not __arm__, not __x86__) + #error unsupported CPU (not __ARM_ARCH_6M__, not __x86_64__) #endif #if 0 @@ -587,8 +589,7 @@ __attribute__ ((noreturn)) void cr_exit(void) { cr_plat_longjmp(coroutine_main_env, 1); /* jump to point=b */ } -void cr_unpause_from_intrhandler(cid_t cid) { - debugf("cr_unpause(%zu)\n", cid); +static void _cr_unpause(cid_t cid) { assert_cid_state(cid, state == CR_PAUSED); coroutine_table[cid-1].state = CR_RUNNABLE; @@ -596,11 +597,19 @@ void cr_unpause_from_intrhandler(cid_t cid) { } void cr_unpause(cid_t cid) { + debugf("cr_unpause(%zu)\n", cid); + assert_cid_state(coroutine_running, state == CR_RUNNING); bool saved = cr_save_and_disable_interrupts(); - cr_unpause_from_intrhandler(cid); + _cr_unpause(cid); cr_restore_interrupts(saved); } +void cr_unpause_from_intrhandler(cid_t cid) { + debugf("cr_unpause_from_intrhandler(%zu)\n", cid); + + _cr_unpause(cid); +} + cid_t cr_getcid(void) { assert_cid_state(coroutine_running, state == CR_RUNNING); return coroutine_running; -- cgit v1.2.3-2-g168b