From 62cf1960ad0b2c2725024fb3329441b8ae145438 Mon Sep 17 00:00:00 2001 From: Daniel Leung Date: Mon, 5 Oct 2020 14:54:45 -0700 Subject: [PATCH] kernel: support using thread local storage for errno This enables storing errno in the thread local storage area. With this enabled, a syscall to access errno can be avoided when userspace is also enabled. Signed-off-by: Daniel Leung --- include/kernel.h | 4 +++- include/sys/errno_private.h | 12 ++++++++++++ kernel/Kconfig | 12 ++++++++++-- kernel/errno.c | 8 ++++++++ kernel/thread.c | 2 ++ 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/include/kernel.h b/include/kernel.h index 9f07e6185a2..381af790724 100644 --- a/include/kernel.h +++ b/include/kernel.h @@ -266,7 +266,9 @@ struct _mem_domain_info { #ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA struct _thread_userspace_local_data { +#if defined(CONFIG_ERRNO) && !defined(CONFIG_ERRNO_IN_TLS) int errno_var; +#endif }; #endif @@ -329,7 +331,7 @@ struct k_thread { struct _thread_userspace_local_data *userspace_local_data; #endif -#ifdef CONFIG_ERRNO +#if defined(CONFIG_ERRNO) && !defined(CONFIG_ERRNO_IN_TLS) #ifndef CONFIG_USERSPACE /** per-thread errno variable */ int errno_var; diff --git a/include/sys/errno_private.h b/include/sys/errno_private.h index a51f37765b1..f1c1bff4cb0 100644 --- a/include/sys/errno_private.h +++ b/include/sys/errno_private.h @@ -17,6 +17,14 @@ extern "C" { * and kernel.h */ +#ifdef CONFIG_ERRNO_IN_TLS +extern __thread int z_errno_var; + +static inline int *z_errno(void) +{ + return &z_errno_var; +} +#else /** * return a pointer to a memory location containing errno * @@ -27,10 +35,14 @@ extern "C" { */ __syscall int *z_errno(void); +#endif /* CONFIG_ERRNO_IN_TLS */ + #ifdef __cplusplus } #endif +#ifndef CONFIG_ERRNO_IN_TLS #include +#endif /* CONFIG_ERRNO_IN_TLS */ #endif /* ZEPHYR_INCLUDE_SYS_ERRNO_PRIVATE_H_ */ diff --git a/kernel/Kconfig b/kernel/Kconfig index 18441ada35f..db845a6bdef 100644 --- a/kernel/Kconfig +++ b/kernel/Kconfig @@ -195,16 +195,24 @@ config THREAD_CUSTOM_DATA config THREAD_USERSPACE_LOCAL_DATA bool depends on USERSPACE + default y if ERRNO && !ERRNO_IN_TLS config ERRNO bool "Enable errno support" default y - select THREAD_USERSPACE_LOCAL_DATA if USERSPACE help Enable per-thread errno in the kernel. Application and library code must include errno.h provided by the C library (libc) to use the errno symbol. The C library must access the per-thread errno via the - _get_errno() symbol. + z_errno() symbol. + +config ERRNO_IN_TLS + bool "Store errno in thread local storage (TLS)" + depends on ERRNO && THREAD_LOCAL_STORAGE + default y + help + Use thread local storage to store errno instead of storing it in + the kernel thread struct. This avoids a syscall if userspace is enabled. choice SCHED_ALGORITHM prompt "Scheduler priority queue algorithm" diff --git a/kernel/errno.c b/kernel/errno.c index 51a2363d28d..84f78593dc1 100644 --- a/kernel/errno.c +++ b/kernel/errno.c @@ -23,6 +23,11 @@ const int _k_neg_eagain = -EAGAIN; #ifdef CONFIG_ERRNO + +#ifdef CONFIG_ERRNO_IN_TLS +__thread int z_errno_var; +#else + #ifdef CONFIG_USERSPACE int *z_impl_z_errno(void) { @@ -44,4 +49,7 @@ int *z_impl_z_errno(void) return &_current->errno_var; } #endif /* CONFIG_USERSPACE */ + +#endif /* CONFIG_ERRNO_IN_TLS */ + #endif /* CONFIG_ERRNO */ diff --git a/kernel/thread.c b/kernel/thread.c index 16de7a8f93e..6e3b7e23b7d 100644 --- a/kernel/thread.c +++ b/kernel/thread.c @@ -835,8 +835,10 @@ FUNC_NORETURN void k_thread_user_mode_enter(k_thread_entry_t entry, #ifdef CONFIG_USERSPACE __ASSERT(z_stack_is_user_capable(_current->stack_obj), "dropping to user mode with kernel-only stack object"); +#ifdef CONFIG_THREAD_USERSPACE_LOCAL_DATA memset(_current->userspace_local_data, 0, sizeof(struct _thread_userspace_local_data)); +#endif arch_user_mode_enter(entry, p1, p2, p3); #else /* XXX In this case we do not reset the stack */