From 24468128dec42609a16a3804c7ca57a316327fc9 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 11 Mar 2016 07:17:32 -0600 Subject: [PATCH] TLS: Simplify --- TODO | 4 ++ arch | 2 +- include/nuttx/arch.h | 21 +++---- include/nuttx/tls.h | 46 ++++----------- libc/Kconfig | 43 ++++++++++++++ libc/Makefile | 35 +++++------ {sched => libc}/tls/Make.defs | 8 +-- {sched => libc}/tls/tls.h | 0 {sched => libc}/tls/tls_getelem.c | 5 +- {sched => libc}/tls/tls_setelem.c | 5 +- sched/Kconfig | 43 -------------- sched/Makefile | 1 - sched/tls/tls_cpuindex.c | 97 ------------------------------- 13 files changed, 91 insertions(+), 219 deletions(-) rename {sched => libc}/tls/Make.defs (94%) rename {sched => libc}/tls/tls.h (100%) rename {sched => libc}/tls/tls_getelem.c (97%) rename {sched => libc}/tls/tls_setelem.c (97%) delete mode 100644 sched/tls/tls_cpuindex.c diff --git a/TODO b/TODO index d9c66df017..74e94c7b5a 100644 --- a/TODO +++ b/TODO @@ -524,6 +524,10 @@ o Kernel/Protected Build console output. The requests for the pid() are part of the implementation of the I/O's re-entrant semaphore implementation and would not be an issue in the more general case. + + Update: + One solution might be to used CONFIG_TLS, add the PID to struct + tls_info_s. Then the PID could be obtained without a system call. Status: Open Priority: Low-Medium. Right now, I do not know if these syscalls are a real performance issue or not. The above statistics were collected diff --git a/arch b/arch index 42309e169e..bc619710ab 160000 --- a/arch +++ b/arch @@ -1 +1 @@ -Subproject commit 42309e169e94db92096afb8f4b6957e84c6b6fc8 +Subproject commit bc619710ab72168bc8ad658deb344e68caf7dcf4 diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 448029f47e..0a176653fd 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -1654,9 +1654,7 @@ int up_timer_start(FAR const struct timespec *ts); * of the stack and stack allocation and initialization logic must take * care to preserve this structure content. * - * The stack memory is fully accessible to user mode threads but will - * contain references to OS internal, private data structures (such as the - * TCB) + * The stack memory is fully accessible to user mode threads. * * Input Parameters: * None @@ -1670,8 +1668,12 @@ int up_timer_start(FAR const struct timespec *ts); ****************************************************************************/ #ifdef CONFIG_TLS -struct tls_info_s; /* Forward reference */ -FAR struct tls_info_s *up_tls_info(void); +/* struct tls_info_s; + * FAR struct tls_info_s *up_tls_info(void); + * + * The actual declaration or definition is provided in arch/tls.h. The + * actual implementation may be a MACRO or and inline function. + */ #endif /**************************************************************************** @@ -1705,10 +1707,6 @@ FAR struct tls_info_s *up_tls_info(void); * Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that * corresponds to the currently executing CPU. * - * If TLS is enabled, then the RTOS can get this information from the TLS - * info structure. Otherwise, the MCU-specific logic must provide some - * mechanism to provide the CPU index. - * * Input Parameters: * None * @@ -1719,12 +1717,7 @@ FAR struct tls_info_s *up_tls_info(void); ****************************************************************************/ #ifdef CONFIG_SMP -# ifdef CONFIG_TLS -int tls_cpu_index(void); -# define up_cpu_index() tls_cpu_index() -# else int up_cpu_index(void); -# endif #else # define up_cpu_index() (0) #endif diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index e6feaaeb15..39c9529716 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -57,7 +57,13 @@ #ifndef CONFIG_TLS_NELEM # warning CONFIG_TLS_NELEM is not defined -# define CONFIG_TLS_NELEM 0 +# define CONFIG_TLS_NELEM 1 +#endif + +#if CONFIG_TLS_NELEM < 1 +# error CONFIG_TLS_NELEM must be at least one +# undef CONFIG_TLS_NELEM +# define CONFIG_TLS_NELEM 1 #endif /* TLS Definitions **********************************************************/ @@ -80,45 +86,19 @@ * of the stack and stack allocation and initialization logic must take * care to preserve this structure content. * - * The stack memory is fully accessible to user mode threads but will - * contain references to OS internal, private data structures (such as the - * TCB) + * The stack memory is fully accessible to user mode threads. TLS is not + * available from interrupt handlers (nor from the IDLE thread). */ -struct tcb_s; /* Forward reference */ struct tls_info_s { - FAR struct tcb_s *tl_tcb; /* The TCB of the current task */ -#if CONFIG_TLS_NELEM > 0 uintptr_t tl_elem[CONFIG_TLS_NELEM]; /* TLS elements */ -#endif }; /**************************************************************************** * Public Function Prototypes ****************************************************************************/ -/**************************************************************************** - * Name: tls_cpu_index - * - * Description: - * Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that - * corresponds to the currently executing CPU. This is index is retained - * in the task TCB which is accessible via the tls_info_s structure. - * - * Input Parameters: - * None - * - * Returned Value: - * An integer index in the range of 0 through (CONFIG_SMP_NCPUS-1) that - * corresponds to the currently executing CPU - * - ****************************************************************************/ - -#ifdef CONFIG_SMP -int tls_cpu_index(void); -#endif - /**************************************************************************** * Name: tls_get_element * @@ -132,13 +112,11 @@ int tls_cpu_index(void); * The value of TLS element associated with 'elem'. Errors are not reported. * Aero is returned in the event of an error, but zero may also be valid * value and returned when there is no error. The only possible error would - * be if elem >=CONFIG_TLS_NELEM. + * be if elemn < 0 or elem >=CONFIG_TLS_NELEM. * ****************************************************************************/ -#if CONFIG_TLS_NELEM > 0 uintptr_t tls_get_element(int elem); -#endif /**************************************************************************** * Name: tls_get_element @@ -152,13 +130,11 @@ uintptr_t tls_get_element(int elem); * * Returned Value: * None. Errors are not reported. The only possible error would be if - * elem >=CONFIG_TLS_NELEM. + * elem < 0 or elem >=CONFIG_TLS_NELEM. * ****************************************************************************/ -#if CONFIG_TLS_NELEM > 0 void tls_set_element(int elem, uintptr_t value); -#endif #endif /* CONFIG_TLS */ #endif /* __INCLUDE_NUTTX_TLS_H */ diff --git a/libc/Kconfig b/libc/Kconfig index 54df4e2ede..276cc502e5 100644 --- a/libc/Kconfig +++ b/libc/Kconfig @@ -504,6 +504,49 @@ config ARCH_BZERO endif # ARCH_OPTIMIZED_FUNCTIONS +config ARCH_HAVE_TLS + bool + default n + ---help--- + Selected by the configuration system if the current architecture + supports TLS. + +menuconfig TLS + bool "Thread Local Storage (TLS)" + default n + depends on ARCH_HAVE_TLS + ---help--- + Build in support for stack based thread local storage (TLS). + +if TLS + +config TLS_LOG2_MAXSTACK + int "Maximum stack size (log2)" + default 13 + range 11 24 + ---help--- + Stack based TLS works by fetch thread information from the beginning + of the stack memory allocation. In order to do this, the memory + must be aligned in such a way that the executing logic can simply + masking the current stack pointer to get the beginning of the stack + allocation. + + This setting specifies the alignment of the stack as a power of 2: + 11=2KB, 12=4KB, 13=8KB, etc. The exact alignment is not so critical + except that (1) a very large value can cause you to run out of + alignable memory (and fail memory allocations), and (2) smaller + values will limit the maximum size of the stack (hence the naming + of this configuration value). + +config TLS_NELEM + int "Number of TLS elements" + default 1 + ---help--- + The number of unique TLS elements. These can be accessed with + the user library functions tls_get_element() and tls_set_element(). + +endif # TLS + config LIBC_NETDB bool default n diff --git a/libc/Makefile b/libc/Makefile index d83957a95c..f07366f076 100644 --- a/libc/Makefile +++ b/libc/Makefile @@ -61,30 +61,31 @@ CSRCS = DEPPATH := --dep-path . VPATH := . -include stdio/Make.defs -include stdlib/Make.defs -include unistd/Make.defs -include sched/Make.defs -include syslog/Make.defs -include string/Make.defs include aio/Make.defs -include pthread/Make.defs -include semaphore/Make.defs -include signal/Make.defs -include math/Make.defs +include audio/Make.defs +include dirent/Make.defs include fixedmath/Make.defs +include libgen/Make.defs +include math/Make.defs +include misc/Make.defs include net/Make.defs include netdb/Make.defs -include time/Make.defs -include libgen/Make.defs -include dirent/Make.defs -include termios/Make.defs -include spawn/Make.defs +include pthread/Make.defs include queue/Make.defs +include sched/Make.defs +include semaphore/Make.defs +include signal/Make.defs +include spawn/Make.defs +include stdio/Make.defs +include stdlib/Make.defs +include string/Make.defs include symtab/Make.defs +include syslog/Make.defs +include termios/Make.defs +include time/Make.defs +include tls/Make.defs +include unistd/Make.defs include wqueue/Make.defs -include misc/Make.defs -include audio/Make.defs # REVISIT: Backslash causes problems in $(COBJS) target DELIM := $(strip /) diff --git a/sched/tls/Make.defs b/libc/tls/Make.defs similarity index 94% rename from sched/tls/Make.defs rename to libc/tls/Make.defs index a200777001..c948e07194 100644 --- a/sched/tls/Make.defs +++ b/libc/tls/Make.defs @@ -1,5 +1,5 @@ ############################################################################ -# sched/tls/Make.defs +# libc/tls/Make.defs # # Copyright (C) 2016 Gregory Nutt. All rights reserved. # Author: Gregory Nutt @@ -35,13 +35,7 @@ ifeq ($(CONFIG_TLS),y) -ifeq ($(CONFIG_SMP),y) -CSRCS += tls_cpuindex.c -endif - -ifneq ($(CONFIG_TLS_NELEM),0) CSRCS += tls_setelem.c tls_getelem.c -endif # Include tls build support diff --git a/sched/tls/tls.h b/libc/tls/tls.h similarity index 100% rename from sched/tls/tls.h rename to libc/tls/tls.h diff --git a/sched/tls/tls_getelem.c b/libc/tls/tls_getelem.c similarity index 97% rename from sched/tls/tls_getelem.c rename to libc/tls/tls_getelem.c index 9a11a5194b..a7a10299fc 100644 --- a/sched/tls/tls_getelem.c +++ b/libc/tls/tls_getelem.c @@ -44,8 +44,9 @@ #include #include +#include -#if defined(CONFIG_TLS) && CONFIG_TLS_NELEM > 0 +#ifdef CONFIG_TLS /**************************************************************************** * Public Functions @@ -89,4 +90,4 @@ uintptr_t tls_get_element(int elem) return ret; } -#endif /* CONFIG_TLS && CONFIG_TLS_NELEM > 0 */ +#endif /* CONFIG_TLS */ diff --git a/sched/tls/tls_setelem.c b/libc/tls/tls_setelem.c similarity index 97% rename from sched/tls/tls_setelem.c rename to libc/tls/tls_setelem.c index cca74adee3..14152590da 100644 --- a/sched/tls/tls_setelem.c +++ b/libc/tls/tls_setelem.c @@ -44,8 +44,9 @@ #include #include +#include -#if defined(CONFIG_TLS) && CONFIG_TLS_NELEM > 0 +#ifdef CONFIG_TLS /**************************************************************************** * Public Functions @@ -85,4 +86,4 @@ void tls_set_element(int elem, uintptr_t value) } } -#endif /* CONFIG_TLS && CONFIG_TLS_NELEM > 0 */ +#endif /* CONFIG_TLS */ diff --git a/sched/Kconfig b/sched/Kconfig index d1f4471b1e..66c9f02459 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -503,49 +503,6 @@ config SCHED_WAITPID endmenu # Tasks and Scheduling -config ARCH_HAVE_TLS - bool - default n - ---help--- - Selected by the configuration system if the current architecture - supports TLS. - -menuconfig TLS - bool "Thread Local Storage (TLS)" - default n - depends on ARCH_HAVE_TLS - ---help--- - Build in support for stack based thread local storage (TLS). - -if TLS - -config TLS_LOG2_MAXSTACK - int "Maximum stack size (log2)" - default 13 - range 11 24 - ---help--- - Stack based TLS works by fetch thread information from the beginning - of the stack memory allocation. In order to do this, the memory - must be aligned in such a way that the executing logic can simply - masking the current stack pointer to get the beginning of the stack - allocation. - - This setting specifies the alignment of the stack as a power of 2: - 11=2KB, 12=4KB, 13=8KB, etc. The exact alignment is not so critical - except that (1) a very large value can cause you to run out of - alignable memory (and fail memory allocations), and (2) smaller - values will limit the maximum size of the stack (hence the naming - of this configuration value). - -config TLS_NELEM - int "Number of TLS elements" - default 0 - ---help--- - The number of unique TLS elements. These can be accessed with - tls_get_element() and tls_set_element(). - -endif # TLS - menu "Pthread Options" depends on !DISABLE_PTHREAD diff --git a/sched/Makefile b/sched/Makefile index 6a07d4a194..63d1c519ed 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -56,7 +56,6 @@ include semaphore/Make.defs include signal/Make.defs include task/Make.defs include timer/Make.defs -include tls/Make.defs include wdog/Make.defs include wqueue/Make.defs diff --git a/sched/tls/tls_cpuindex.c b/sched/tls/tls_cpuindex.c deleted file mode 100644 index b906d0ade9..0000000000 --- a/sched/tls/tls_cpuindex.c +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** - * libc/fixedmath/tls_cpuindex.c - * - * Copyright (C) 2016 Gregory Nutt. All rights reserved. - * Author: Gregory Nutt - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * 3. Neither the name NuttX nor the names of its contributors may be - * used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS - * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE - * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED - * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN - * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include - -#include -#include -#include - -#if defined(CONFIG_TLS) && defined(CONFIG_SMP) - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_cpu_index - * - * Description: - * Return an index in the range of 0 through (CONFIG_SMP_NCPUS-1) that - * corresponds to the currently executing CPU. This is index is retained - * in the task TCB which is accessible via the tls_info_s structure. - * - * There is a race condition in that this thread could be swapped out and - * be running on a different CPU when the function returns. If that is a - * problem, then the calling function should disable pre-emption before - * calling this function. - * - * Input Parameters: - * None - * - * Returned Value: - * On success, an integer index is returned in the range of 0 through - * (CONFIG_SMP_NCPUS-1) that corresponds to the currently executing CPU. - * - ****************************************************************************/ - -int tls_cpu_index(void) -{ - FAR struct tls_info_s *info; - FAR struct tcb_s *tcb; - - /* Get the TLS info structure from the current threads stack */ - - info = up_tls_info(); - DEBUGASSERT(info != NULL && info->tl_tcb != NULL); - - /* Get the TCB from the TLS info. We expect the TCB state to indicate that - * the task is running (it must be because it is this thread). - */ - - tcb = info->tl_tcb; - DEBUGASSERT(tcb->task_state == TSTATE_TASK_RUNNING && - tcb->cpu <= (CONFIG_SMP_NCPUS-1)); - - return tcb->cpu; -} - -#endif /* CONFIG_TLS && CONFIG_SMP */