From 8100203e95225696b94081c6e4988a099bd4f624 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 10 Dec 2021 15:43:51 +0100 Subject: [PATCH] core/thread, mutex: provide dummy implementation for riotboot This is intended for the bootloader module where we don't enter thread mode, so mutex must never attempt to switch context. Instead use a simple busy wait that is enough to make the possible mutex users (e.g. interrupt based SPI) in bootloader mode work. --- core/Kconfig | 4 ++++ core/Makefile | 2 +- core/include/mutex.h | 35 +++++++++++++++++++++++++++++++++ core/include/sched.h | 4 ++++ core/include/thread.h | 15 ++++++++++++++ core/lib/init.c | 14 +++++++++---- core/mutex.c | 6 ++++++ makefiles/defaultmodules.inc.mk | 2 +- 8 files changed, 76 insertions(+), 6 deletions(-) diff --git a/core/Kconfig b/core/Kconfig index f0219729d1..8815d0f378 100644 --- a/core/Kconfig +++ b/core/Kconfig @@ -43,6 +43,10 @@ config MODULE_CORE_PANIC bool "Kernel crash handling module" default y +config MODULE_CORE_THREAD + bool "Support for Threads" + default y + config MODULE_CORE_THREAD_FLAGS bool "Thread flags" diff --git a/core/Makefile b/core/Makefile index 50308607e3..e03d095c13 100644 --- a/core/Makefile +++ b/core/Makefile @@ -1,5 +1,5 @@ # exclude submodule sources from *.c wildcard source selection -SRC := $(filter-out mbox.c msg.c msg_bus.c thread_flags.c,$(wildcard *.c)) +SRC := $(filter-out mbox.c msg.c msg_bus.c thread.c thread_flags.c,$(wildcard *.c)) # enable submodules SUBMODULES := 1 diff --git a/core/include/mutex.h b/core/include/mutex.h index 62d13a3ad5..551da41be1 100644 --- a/core/include/mutex.h +++ b/core/include/mutex.h @@ -249,7 +249,31 @@ static inline int mutex_trylock(mutex_t *mutex) * * @post The mutex @p is locked and held by the calling thread. */ +#if (MAXTHREADS > 1) || DOXYGEN void mutex_lock(mutex_t *mutex); +#else +/** + * @brief dummy implementation for when no scheduler is used + */ +static inline void mutex_lock(mutex_t *mutex) +{ + /* (ab)use next pointer as lock variable */ + volatile uintptr_t *lock = (void *)&mutex->queue.next; + + /* spin until lock is released (e.g. by interrupt). + * + * Note: since only the numbers 0 and 1 are ever stored in lock, this + * read does not need to be atomic here - even while a concurrent write + * is performed on lock, a read will still either yield 0 or 1 (so the old + * or new value, which both is fine), even if the lock is read out byte-wise + * (e.g. on AVR). + */ + while (*lock) {} + + /* set lock variable */ + *lock = 1; +} +#endif /** * @brief Locks a mutex, blocking. This function can be canceled. @@ -284,7 +308,18 @@ int mutex_lock_cancelable(mutex_cancel_t *mc); * @note It is safe to unlock a mutex held by a different thread. * @note It is safe to call this function from IRQ context. */ +#if (MAXTHREADS > 1) || DOXYGEN void mutex_unlock(mutex_t *mutex); +#else +/** + * @brief dummy implementation for when no scheduler is used + */ +static inline void mutex_unlock(mutex_t *mutex) +{ + /* (ab)use next pointer as lock variable */ + mutex->queue.next = NULL; +} +#endif /** * @brief Unlocks the mutex and sends the current thread to sleep diff --git a/core/include/sched.h b/core/include/sched.h index 5a5c2bbb34..49b4c35eef 100644 --- a/core/include/sched.h +++ b/core/include/sched.h @@ -97,7 +97,11 @@ extern "C" { * @brief The maximum number of threads to be scheduled */ #ifndef MAXTHREADS +#if defined(MODULE_CORE_THREAD) #define MAXTHREADS 32 +#else +#define MAXTHREADS 0 +#endif #endif /** diff --git a/core/include/thread.h b/core/include/thread.h index dd1ee69040..233f7a07fe 100644 --- a/core/include/thread.h +++ b/core/include/thread.h @@ -325,7 +325,14 @@ void thread_sleep(void); * * @see thread_yield_higher() */ +#if defined(MODULE_CORE_THREAD) || DOXYGEN void thread_yield(void); +#else +static inline void thread_yield(void) +{ + /* NO-OP */ +} +#endif /** * @brief Lets current thread yield in favor of a higher prioritized thread. @@ -436,7 +443,15 @@ void thread_add_to_list(list_node_t *list, thread_t *thread); * @return the threads name * @return `NULL` if pid is unknown */ +#if defined(MODULE_CORE_THREAD) || DOXYGEN const char *thread_getname(kernel_pid_t pid); +#else +static inline const char *thread_getname(kernel_pid_t pid) +{ + (void)pid; + return "(none)"; +} +#endif /** * @brief Measures the stack usage of a stack diff --git a/core/lib/init.c b/core/lib/init.c index 840677c49e..cf5bf972a0 100644 --- a/core/lib/init.c +++ b/core/lib/init.c @@ -89,10 +89,16 @@ void kernel_init(void) idle_thread, NULL, "idle"); } - thread_create(main_stack, sizeof(main_stack), - THREAD_PRIORITY_MAIN, - THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, - main_trampoline, NULL, "main"); + if (IS_USED(MODULE_CORE_THREAD)) { + thread_create(main_stack, sizeof(main_stack), + THREAD_PRIORITY_MAIN, + THREAD_CREATE_WOUT_YIELD | THREAD_CREATE_STACKTEST, + main_trampoline, NULL, "main"); + } + else { + irq_enable(); + main_trampoline(NULL); + } cpu_switch_context_exit(); } diff --git a/core/mutex.c b/core/mutex.c index 01c2a11b2f..257e779627 100644 --- a/core/mutex.c +++ b/core/mutex.c @@ -33,6 +33,8 @@ #define ENABLE_DEBUG 0 #include "debug.h" +#if MAXTHREADS > 1 + /** * @brief Block waiting for a locked mutex * @pre IRQs are disabled @@ -226,3 +228,7 @@ int mutex_trylock_ffi(mutex_t *mutex) { return mutex_trylock(mutex); } + +#else /* MAXTHREADS < 2 */ +typedef int dont_be_pedantic; +#endif diff --git a/makefiles/defaultmodules.inc.mk b/makefiles/defaultmodules.inc.mk index 8e3f6b21df..1231427d31 100644 --- a/makefiles/defaultmodules.inc.mk +++ b/makefiles/defaultmodules.inc.mk @@ -1,6 +1,6 @@ DEFAULT_MODULE += board board_common_init \ cpu \ - core core_init core_lib core_msg core_panic \ + core core_init core_lib core_msg core_panic core_thread \ sys # Include potentially added default modules by the board