From c09d9d87b766be3290bae2e6b55ca9faa927235f Mon Sep 17 00:00:00 2001 From: Gunar Schorcht Date: Wed, 2 Mar 2022 11:57:39 +0100 Subject: [PATCH] sys/posix/pthread: newlib compatibility When using a toolchain with built-in POSIX thread support, static C++ constructors use a static mutex variable which is initialized with `pthread_once` when first used. However, since RIOT's `pthread_once_t` type is different from that in newlib's `pthread`, which is assumed by GCC, RIOT crashes as soon as static constructors are used. Changing the `pthread_once_t` type to be compatible with newlib's `pthread_once_t` type solves the problem and allows the RIOT `pthread` modules to be used even with toolchains with built-in POSIX thread support. --- sys/posix/pthread/include/pthread_once.h | 12 +++++++++--- sys/posix/pthread/pthread_once.c | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/sys/posix/pthread/include/pthread_once.h b/sys/posix/pthread/include/pthread_once.h index 6c01a4a1759d..2a10358497d1 100644 --- a/sys/posix/pthread/include/pthread_once.h +++ b/sys/posix/pthread/include/pthread_once.h @@ -23,15 +23,21 @@ extern "C" { /** * @brief Datatype to supply to pthread_once(). + * @details This data type must be compatible with the one defined + * in newlib's `include/sys/_pthreadtypes.h`. */ -typedef volatile int pthread_once_t; +typedef struct { + int is_initialized; /**< initialized */ + int init_executed; /**< init function executed */ +} pthread_once_t; /** * @def PTHREAD_ONCE_INIT * @brief Initialization for pthread_once_t. - * @details A zeroed out pthread_once_t is initialized. + * @details pthread_once_t variables are declared as initialized, but + * the init function is not yet executed. */ -#define PTHREAD_ONCE_INIT 0 +#define PTHREAD_ONCE_INIT { 1, 0 } /** * @brief Helper function that ensures that `init_routine` is called at once. diff --git a/sys/posix/pthread/pthread_once.c b/sys/posix/pthread/pthread_once.c index 59bc2d0e7f66..c6ac4dc196fe 100644 --- a/sys/posix/pthread/pthread_once.c +++ b/sys/posix/pthread/pthread_once.c @@ -22,11 +22,11 @@ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void)) { - if (*once_control == PTHREAD_ONCE_INIT) { + if (!once_control->init_executed) { init_routine(); } - *once_control = PTHREAD_ONCE_INIT + 1; + once_control->init_executed = 1; return 0; }