TLS: Simplify

This commit is contained in:
Gregory Nutt 2016-03-11 07:17:32 -06:00
parent 934069e422
commit 24468128de
13 changed files with 91 additions and 219 deletions

4
TODO
View File

@ -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

2
arch

@ -1 +1 @@
Subproject commit 42309e169e94db92096afb8f4b6957e84c6b6fc8
Subproject commit bc619710ab72168bc8ad658deb344e68caf7dcf4

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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 /)

View File

@ -1,5 +1,5 @@
############################################################################
# sched/tls/Make.defs
# libc/tls/Make.defs
#
# Copyright (C) 2016 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
@ -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

View File

@ -44,8 +44,9 @@
#include <nuttx/arch.h>
#include <nuttx/tls.h>
#include <arch/tls.h>
#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 */

View File

@ -44,8 +44,9 @@
#include <nuttx/arch.h>
#include <nuttx/tls.h>
#include <arch/tls.h>
#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 */

View File

@ -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

View File

@ -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

View File

@ -1,97 +0,0 @@
/****************************************************************************
* libc/fixedmath/tls_cpuindex.c
*
* Copyright (C) 2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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 <nuttx/config.h>
#include <assert.h>
#include <nuttx/arch.h>
#include <nuttx/sched.h>
#include <nuttx/tls.h>
#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 */