diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 8f324402a7..fc196680fc 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -530,14 +530,6 @@ struct task_group_s FAR struct join_s *tg_jointail; /* Tail of a list of join data */ #endif - /* Thread local storage ***************************************************/ - -#if CONFIG_TLS_NELEM > 0 - tls_ndxset_t tg_tlsset; /* Set of TLS indexes allocated */ - - tls_dtor_t tg_tlsdestr[CONFIG_TLS_NELEM]; /* List of TLS destructors */ -#endif - /* POSIX Signal Control Fields ********************************************/ sq_queue_t tg_sigactionq; /* List of actions for signals */ diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index d45230dd06..6950751568 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -118,6 +118,13 @@ struct task_info_s struct tls_info_s ta_tls; /* Must be first field */ #ifndef CONFIG_BUILD_KERNEL struct getopt_s ta_getopt; /* Globals used by getopt() */ +#endif + /* Thread local storage ***************************************************/ + +#if CONFIG_TLS_NELEM > 0 + sem_t ta_tlssem; + tls_ndxset_t ta_tlsset; /* Set of TLS index allocated */ + tls_dtor_t ta_tlsdtor[CONFIG_TLS_NELEM]; /* List of TLS destructors */ #endif }; @@ -320,4 +327,20 @@ void tls_destruct(void); FAR struct task_info_s *task_get_info(void); +/**************************************************************************** + * Name: task_setup_info + * + * Description: + * Setup task_info_s for task + * + * Input Parameters: + * info - New created task_info_s + * + * Returned Value: + * OK on success; ERROR on failure + * + ****************************************************************************/ + +int task_setup_info(FAR struct task_info_s *info); + #endif /* __INCLUDE_NUTTX_TLS_H */ diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index a0e44d7dbd..03de33c0d2 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -294,14 +294,6 @@ SYSCALL_LOOKUP(telldir, 1) SYSCALL_LOOKUP(shmdt, 1) #endif -#if CONFIG_TLS_NELEM > 0 - SYSCALL_LOOKUP(tls_alloc, 0) - SYSCALL_LOOKUP(tls_free, 1) - SYSCALL_LOOKUP(tls_get_set, 1) - SYSCALL_LOOKUP(tls_get_dtor, 1) - SYSCALL_LOOKUP(tls_set_dtor, 2) -#endif - /* The following are defined if pthreads are enabled */ #ifndef CONFIG_DISABLE_PTHREAD diff --git a/libs/libc/pthread/pthread_keycreate.c b/libs/libc/pthread/pthread_keycreate.c index 798cca7d38..d162fbf8c0 100644 --- a/libs/libc/pthread/pthread_keycreate.c +++ b/libs/libc/pthread/pthread_keycreate.c @@ -89,7 +89,7 @@ int pthread_key_create(FAR pthread_key_t *key, return OK; } - return -tlsindex; + return ERROR; } #endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/tls/Make.defs b/libs/libc/tls/Make.defs index 67e830f71a..ab1da9069a 100644 --- a/libs/libc/tls/Make.defs +++ b/libs/libc/tls/Make.defs @@ -22,6 +22,9 @@ CSRCS += task_getinfo.c ifneq ($(CONFIG_TLS_NELEM),0) CSRCS += tls_setvalue.c tls_getvalue.c tls_destruct.c +CSRCS += tls_getdtor.c tls_setdtor.c +CSRCS += tls_alloc.c tls_free.c +CSRCS += tls_getset.c endif ifneq ($(CONFIG_TLS_ALIGNED),y) diff --git a/sched/group/group_tlsalloc.c b/libs/libc/tls/tls_alloc.c similarity index 85% rename from sched/group/group_tlsalloc.c rename to libs/libc/tls/tls_alloc.c index 5b09073abc..2630e7e415 100644 --- a/sched/group/group_tlsalloc.c +++ b/libs/libc/tls/tls_alloc.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/group/group_tlsalloc.c + * libs/libc/tls/tls_alloc.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -32,9 +32,6 @@ #include #include -#include "sched/sched.h" -#include "group/group.h" - #if CONFIG_TLS_NELEM > 0 /**************************************************************************** @@ -52,39 +49,45 @@ * * Returned Value: * A TLS index that is unique for use within this task group. + * If unsuccessful, an errno value will be returned and set to errno. * ****************************************************************************/ int tls_alloc(void) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; - irqstate_t flags; + FAR struct task_info_s *tinfo = task_get_info(); int candidate; int ret = -EAGAIN; - DEBUGASSERT(group != NULL); + DEBUGASSERT(tinfo != NULL); /* Search for an unused index. This is done in a critical section here to * avoid concurrent modification of the group TLS index set. */ - flags = spin_lock_irqsave(NULL); + ret = _SEM_WAIT(&tinfo->ta_tlssem); + + if (ERROR == ret) + { + ret = -get_errno(); + goto errout_with_errno; + } + for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) { /* Is this candidate index available? */ tls_ndxset_t mask = (1 << candidate); - if ((group->tg_tlsset & mask) == 0) + if ((tinfo->ta_tlsset & mask) == 0) { /* Yes.. allocate the index and break out of the loop */ - group->tg_tlsset |= mask; + tinfo->ta_tlsset |= mask; break; } } - spin_unlock_irqrestore(NULL, flags); + _SEM_POST(&tinfo->ta_tlssem); /* Check if found a valid TLS data index. */ @@ -95,6 +98,8 @@ int tls_alloc(void) ret = candidate; } +errout_with_errno: + return ret; } diff --git a/sched/group/group_tlsfree.c b/libs/libc/tls/tls_free.c similarity index 75% rename from sched/group/group_tlsfree.c rename to libs/libc/tls/tls_free.c index c1eccaf25d..7455e08cb3 100644 --- a/sched/group/group_tlsfree.c +++ b/libs/libc/tls/tls_free.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/group/group_tlsfree.c + * libs/libc/tls/tls_free.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -31,9 +31,6 @@ #include #include -#include "sched/sched.h" -#include "group/group.h" - #if CONFIG_TLS_NELEM > 0 /**************************************************************************** @@ -50,36 +47,40 @@ * tlsindex - The previously allocated TLS index to be freed * * Returned Value: - * OK is returned on success; a negated errno value will be returned on - * failure: + * OK is returned on success; a negated errno value will be returned and + * set to errno on failure: * - * -EINVAL - the index to be freed is out of range. + * -EINVAL - the index to be freed is out of range. + * -EINTR - the wait operation interrupted by signal + * -ECANCELED - the thread was canceled during waiting * ****************************************************************************/ int tls_free(int tlsindex) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; + FAR struct task_info_s *tinfo = task_get_info(); tls_ndxset_t mask; - irqstate_t flags; int ret = -EINVAL; - DEBUGASSERT((unsigned)tlsindex < CONFIG_TLS_NELEM && group != NULL); + DEBUGASSERT((unsigned)tlsindex < CONFIG_TLS_NELEM && tinfo != NULL); if ((unsigned)tlsindex < CONFIG_TLS_NELEM) { - /* This is done in a critical section here to avoid concurrent + /* This is done while holding a semaphore here to avoid concurrent * modification of the group TLS index set. */ mask = (1 << tlsindex); - flags = spin_lock_irqsave(NULL); - - DEBUGASSERT((group->tg_tlsset & mask) != 0); - group->tg_tlsset &= ~mask; - spin_unlock_irqrestore(NULL, flags); - - ret = OK; + ret = _SEM_WAIT(&tinfo->ta_tlssem); + if (OK == ret) + { + DEBUGASSERT((tinfo->ta_tlsset & mask) != 0); + tinfo->ta_tlsset &= ~mask; + _SEM_POST(&tinfo->ta_tlssem); + } + else + { + ret = -get_errno(); + } } return ret; diff --git a/sched/group/group_tlsgetdtor.c b/libs/libc/tls/tls_getdtor.c similarity index 84% rename from sched/group/group_tlsgetdtor.c rename to libs/libc/tls/tls_getdtor.c index c6e25f3f70..1e33b327d1 100644 --- a/sched/group/group_tlsgetdtor.c +++ b/libs/libc/tls/tls_getdtor.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/group/group_tlsgetdtor.c + * libs/libc/tls/tls_getdtor.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -32,9 +32,6 @@ #include #include -#include "sched/sched.h" -#include "group/group.h" - #if CONFIG_TLS_NELEM > 0 /**************************************************************************** @@ -45,7 +42,7 @@ * Name: tls_get_dtor * * Description: - * Get the TLS element destructor associated with the 'tlsindex' to 'destr' + * Get the TLS element destructor associated with the 'tlsindex' to 'dtor' * * Input Parameters: * tlsindex - Index of TLS data destructor to get @@ -57,19 +54,15 @@ tls_dtor_t tls_get_dtor(int tlsindex) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; - irqstate_t flags; - tls_dtor_t destr; + FAR struct task_info_s *tinfo = task_get_info(); + tls_dtor_t dtor; - DEBUGASSERT(group != NULL); + DEBUGASSERT(tinfo != NULL); DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - flags = spin_lock_irqsave(NULL); - destr = group->tg_tlsdestr[tlsindex]; - spin_unlock_irqrestore(NULL, flags); + dtor = tinfo->ta_tlsdtor[tlsindex]; - return destr; + return dtor; } #endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/sched/group/group_tlsgetset.c b/libs/libc/tls/tls_getset.c similarity index 85% rename from sched/group/group_tlsgetset.c rename to libs/libc/tls/tls_getset.c index a3405c44a5..cb3c9587a9 100644 --- a/sched/group/group_tlsgetset.c +++ b/libs/libc/tls/tls_getset.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/group/group_tlsgetset.c + * libs/libc/tls/tls_getset.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -32,9 +32,6 @@ #include #include -#include "sched/sched.h" -#include "group/group.h" - #if CONFIG_TLS_NELEM > 0 /**************************************************************************** @@ -56,16 +53,12 @@ tls_ndxset_t tls_get_set(void) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; - irqstate_t flags; + FAR struct task_info_s *tinfo = task_get_info(); tls_ndxset_t tlsset; - DEBUGASSERT(group != NULL); + DEBUGASSERT(tinfo != NULL); - flags = spin_lock_irqsave(NULL); - tlsset = group->tg_tlsset; - spin_unlock_irqrestore(NULL, flags); + tlsset = tinfo->ta_tlsset; return tlsset; } diff --git a/sched/group/group_tlssetdtor.c b/libs/libc/tls/tls_setdtor.c similarity index 82% rename from sched/group/group_tlssetdtor.c rename to libs/libc/tls/tls_setdtor.c index 040ff65822..4ed813b393 100644 --- a/sched/group/group_tlssetdtor.c +++ b/libs/libc/tls/tls_setdtor.c @@ -1,5 +1,5 @@ /**************************************************************************** - * sched/group/group_tlssetdtor.c + * libs/libc/tls/tls_setdtor.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -32,9 +32,6 @@ #include #include -#include "sched/sched.h" -#include "group/group.h" - #if CONFIG_TLS_NELEM > 0 /**************************************************************************** @@ -45,11 +42,11 @@ * Name: tls_set_dtor * * Description: - * Set the TLS element destructor associated with the 'tlsindex' to 'destr' + * Set the TLS element destructor associated with the 'tlsindex' to 'dtor' * * Input Parameters: * tlsindex - Index of TLS data destructor to set - * destr - The destr of TLS data element + * dtor - The dtor of TLS data element * * Returned Value: * Zero is returned on success, a negated errno value is return on @@ -59,18 +56,14 @@ * ****************************************************************************/ -int tls_set_dtor(int tlsindex, tls_dtor_t destr) +int tls_set_dtor(int tlsindex, tls_dtor_t dtor) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; - irqstate_t flags; + FAR struct task_info_s *tinfo = task_get_info(); - DEBUGASSERT(group != NULL); + DEBUGASSERT(tinfo != NULL); DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - flags = spin_lock_irqsave(NULL); - group->tg_tlsdestr[tlsindex] = destr; - spin_unlock_irqrestore(NULL, flags); + tinfo->ta_tlsdtor[tlsindex] = dtor; return OK; } diff --git a/sched/group/Make.defs b/sched/group/Make.defs index 35eee89702..b0a2cf7e13 100644 --- a/sched/group/Make.defs +++ b/sched/group/Make.defs @@ -53,11 +53,6 @@ ifneq ($(CONFIG_BUILD_FLAT),y) CSRCS += group_malloc.c group_zalloc.c group_free.c endif -ifneq ($(CONFIG_TLS_NELEM),0) -CSRCS += group_tlsalloc.c group_tlsfree.c -CSRCS += group_tlsgetset.c group_tlsgetdtor.c group_tlssetdtor.c -endif - # Include group build support DEPPATH += --dep-path group diff --git a/sched/task/task_init.c b/sched/task/task_init.c index dfd7c7f1dc..fd774ec1f4 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -142,6 +142,14 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, DEBUGASSERT(info == tcb->cmn.stack_alloc_ptr); + ret = task_setup_info(info); + + if (ret < OK) + { + ret = -EINVAL; + goto errout_with_group; + } + /* Initialize the task control block */ ret = nxtask_setup_scheduler(tcb, priority, nxtask_start, diff --git a/sched/task/task_setup.c b/sched/task/task_setup.c index 73f681512a..830754614e 100644 --- a/sched/task/task_setup.c +++ b/sched/task/task_setup.c @@ -35,6 +35,7 @@ #include #include #include +#include #include "sched/sched.h" #include "pthread/pthread.h" @@ -721,3 +722,28 @@ int nxtask_setup_arguments(FAR struct task_tcb_s *tcb, FAR const char *name, return nxtask_setup_stackargs(tcb, argv); } + +/**************************************************************************** + * Name: task_setup_info + * + * Description: + * Setup task_info_s for task + * + * Input Parameters: + * info - New created task_info_s + * + * Returned Value: + * OK on success; ERROR on failure + * + ****************************************************************************/ + +int task_setup_info(FAR struct task_info_s *info) +{ + int ret = OK; + +#if CONFIG_TLS_NELEM > 0 + ret = _SEM_INIT(&info->ta_tlssem, 0, 1); +#endif + + return ret; +} diff --git a/syscall/syscall.csv b/syscall/syscall.csv index 523806cf3c..0f96f4ed95 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -177,11 +177,6 @@ "timer_getoverrun","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t" "timer_gettime","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t","FAR struct itimerspec *" "timer_settime","time.h","!defined(CONFIG_DISABLE_POSIX_TIMERS)","int","timer_t","int","FAR const struct itimerspec *","FAR struct itimerspec *" -"tls_alloc","nuttx/tls.h","CONFIG_TLS_NELEM > 0","int" -"tls_free","nuttx/tls.h","CONFIG_TLS_NELEM > 0","int","int" -"tls_get_dtor","nuttx/tls.h","CONFIG_TLS_NELEM > 0","tls_dtor_t","int" -"tls_get_set","nuttx/tls.h","CONFIG_TLS_NELEM > 0","tls_ndxset_t" -"tls_set_dtor","nuttx/tls.h","CONFIG_TLS_NELEM > 0","int","int","tls_dtor_t" "umount2","sys/mount.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *","unsigned int" "unlink","unistd.h","!defined(CONFIG_DISABLE_MOUNTPOINT)","int","FAR const char *" "unsetenv","stdlib.h","!defined(CONFIG_DISABLE_ENVIRON)","int","FAR const char *"