diff --git a/arch/riscv/core/thread.c b/arch/riscv/core/thread.c index 59adbc42e46..b4999bda09a 100644 --- a/arch/riscv/core/thread.c +++ b/arch/riscv/core/thread.c @@ -15,7 +15,7 @@ /* * Per-thread (TLS) variable indicating whether execution is in user mode. */ -__thread uint8_t is_user_mode; +Z_THREAD_LOCAL uint8_t is_user_mode; #endif void arch_new_thread(struct k_thread *thread, k_thread_stack_t *stack, diff --git a/arch/xtensa/core/thread.c b/arch/xtensa/core/thread.c index f59c8274994..f9b8179173d 100644 --- a/arch/xtensa/core/thread.c +++ b/arch/xtensa/core/thread.c @@ -22,7 +22,7 @@ LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL); /* * Per-thread (TLS) variable indicating whether execution is in user mode. */ -__thread uint32_t is_user_mode; +Z_THREAD_LOCAL uint32_t is_user_mode; #endif #endif /* CONFIG_USERSPACE */ diff --git a/doc/kernel/services/other/thread_local_storage.rst b/doc/kernel/services/other/thread_local_storage.rst index 529a0383de3..6e499e4fd60 100644 --- a/doc/kernel/services/other/thread_local_storage.rst +++ b/doc/kernel/services/other/thread_local_storage.rst @@ -29,25 +29,25 @@ making a system call. Declaring and Using Thread Local Variables ****************************************** -The keyword ``__thread`` can be used to declare thread local variables. +The macro ``Z_THREAD_LOCAL`` can be used to declare thread local variables. For example, to declare a thread local variable in header files: .. code-block:: c - extern __thread int i; + extern Z_THREAD_LOCAL int i; And to declare the actual variable in source files: .. code-block:: c - __thread int i; + Z_THREAD_LOCAL int i; Keyword ``static`` can also be used to limit the variable within a source file: .. code-block:: c - static __thread int j; + static Z_THREAD_LOCAL int j; Using the thread local variable is the same as using other variable, for example: diff --git a/include/zephyr/toolchain/common.h b/include/zephyr/toolchain/common.h index c84328365fd..1891b35538a 100644 --- a/include/zephyr/toolchain/common.h +++ b/include/zephyr/toolchain/common.h @@ -39,6 +39,24 @@ #endif #endif +/* + * Thread local variables are declared with different keywords depending on + * which C/C++ standard that is used. C++11 and C23 uses "thread_local" whilst + * C11 uses "_Thread_local". Previously the GNU "__thread" keyword was used + * which is the same in both gcc and g++. + */ +#ifndef Z_THREAD_LOCAL +#if defined(__cplusplus) && (__cplusplus) >= 201103L /* C++11 */ +#define Z_THREAD_LOCAL thread_local +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__) >= 202311L /* C23 */ +#define Z_THREAD_LOCAL thread_local +#elif defined(__STDC_VERSION__) && (__STDC_VERSION__) >= 201112L /* C11 */ +#define Z_THREAD_LOCAL _Thread_local +#else /* Default back to old behavior which used the GNU keyword. */ +#define Z_THREAD_LOCAL __thread +#endif +#endif /* Z_THREAD_LOCAL */ + /* * Generate a reference to an external symbol. * The reference indicates to the linker that the symbol is required diff --git a/kernel/compiler_stack_protect.c b/kernel/compiler_stack_protect.c index 928fdc6ec9a..e8408a33ed1 100644 --- a/kernel/compiler_stack_protect.c +++ b/kernel/compiler_stack_protect.c @@ -47,7 +47,7 @@ void _StackCheckHandler(void) * The canary value gets initialized in z_cstart(). */ #ifdef CONFIG_STACK_CANARIES_TLS -__thread volatile uintptr_t __stack_chk_guard; +Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; #elif CONFIG_USERSPACE K_APP_DMEM(z_libc_partition) volatile uintptr_t __stack_chk_guard; #else diff --git a/kernel/errno.c b/kernel/errno.c index f268bb72fdf..bbbd6f87bfd 100644 --- a/kernel/errno.c +++ b/kernel/errno.c @@ -27,7 +27,7 @@ const int _k_neg_eagain = -EAGAIN; #if defined(CONFIG_LIBC_ERRNO) /* nothing needed here */ #elif defined(CONFIG_ERRNO_IN_TLS) -__thread int z_errno_var; +Z_THREAD_LOCAL int z_errno_var; #else #ifdef CONFIG_USERSPACE diff --git a/kernel/init.c b/kernel/init.c index 7c1846e229b..afbffe1ccff 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -291,7 +291,7 @@ void z_bss_zero_pinned(void) #ifdef CONFIG_STACK_CANARIES #ifdef CONFIG_STACK_CANARIES_TLS -extern __thread volatile uintptr_t __stack_chk_guard; +extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; #else extern volatile uintptr_t __stack_chk_guard; #endif /* CONFIG_STACK_CANARIES_TLS */ diff --git a/kernel/xip.c b/kernel/xip.c index a5752560c85..d068174a1e9 100644 --- a/kernel/xip.c +++ b/kernel/xip.c @@ -12,7 +12,7 @@ #ifdef CONFIG_STACK_CANARIES #ifdef CONFIG_STACK_CANARIES_TLS -extern __thread volatile uintptr_t __stack_chk_guard; +extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; #else extern volatile uintptr_t __stack_chk_guard; #endif /* CONFIG_STACK_CANARIES_TLS */ diff --git a/lib/os/thread_entry.c b/lib/os/thread_entry.c index ed6ca142d99..a1541b587cc 100644 --- a/lib/os/thread_entry.c +++ b/lib/os/thread_entry.c @@ -15,11 +15,11 @@ #ifdef CONFIG_CURRENT_THREAD_USE_TLS #include -__thread k_tid_t z_tls_current; +Z_THREAD_LOCAL k_tid_t z_tls_current; #endif #ifdef CONFIG_STACK_CANARIES_TLS -extern __thread volatile uintptr_t __stack_chk_guard; +extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; #endif /* CONFIG_STACK_CANARIES_TLS */ /* diff --git a/tests/kernel/mem_protect/stackprot/src/main.c b/tests/kernel/mem_protect/stackprot/src/main.c index 6ebbe2deb89..f30cb9055fc 100644 --- a/tests/kernel/mem_protect/stackprot/src/main.c +++ b/tests/kernel/mem_protect/stackprot/src/main.c @@ -143,7 +143,7 @@ ZTEST(stackprot, test_create_alt_thread) } #ifdef CONFIG_STACK_CANARIES_TLS -extern __thread volatile uintptr_t __stack_chk_guard; +extern Z_THREAD_LOCAL volatile uintptr_t __stack_chk_guard; #else extern volatile uintptr_t __stack_chk_guard; #endif diff --git a/tests/kernel/threads/tls/src/main.c b/tests/kernel/threads/tls/src/main.c index be85bb26d6f..da2486ea1a8 100644 --- a/tests/kernel/threads/tls/src/main.c +++ b/tests/kernel/threads/tls/src/main.c @@ -51,14 +51,14 @@ K_APP_BMEM(part_common) static k_tid_t tls_tid[NUM_THREADS]; K_APP_BMEM(part_common) static enum test_result tls_result[NUM_THREADS]; /* Thread data with initialized values */ -static uint8_t __thread thread_data8 = STATIC_DATA8; -static uint32_t __thread thread_data32 = STATIC_DATA32; -static uint64_t __thread thread_data64 = STATIC_DATA64; +static uint8_t Z_THREAD_LOCAL thread_data8 = STATIC_DATA8; +static uint32_t Z_THREAD_LOCAL thread_data32 = STATIC_DATA32; +static uint64_t Z_THREAD_LOCAL thread_data64 = STATIC_DATA64; /* Zeroed thread data */ -static uint8_t __thread thread_bss8; -static uint32_t __thread thread_bss32; -static uint64_t __thread thread_bss64; +static uint8_t Z_THREAD_LOCAL thread_bss8; +static uint32_t Z_THREAD_LOCAL thread_bss32; +static uint64_t Z_THREAD_LOCAL thread_bss64; static void tls_thread_entry(void *p1, void *p2, void *p3) {