diff --git a/fs/procfs/fs_procfsproc.c b/fs/procfs/fs_procfsproc.c index 0d88d8e421d72..a01bfb48b45ad 100644 --- a/fs/procfs/fs_procfsproc.c +++ b/fs/procfs/fs_procfsproc.c @@ -44,7 +44,7 @@ #endif #include -#include +#include #include #include #include diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h index 23055d57e2786..ca4962ba88640 100644 --- a/include/nuttx/arch.h +++ b/include/nuttx/arch.h @@ -85,7 +85,6 @@ #include #include #include -#include /**************************************************************************** * Pre-processor definitions @@ -1826,14 +1825,6 @@ int up_timer_start(FAR const struct timespec *ts); * implementation provided here assume the arch has a "push down" stack. */ -#ifndef up_tls_info -# if defined(CONFIG_TLS_ALIGNED) && !defined(__KERNEL__) -# define up_tls_info() TLS_INFO((uintptr_t)up_getsp()) -# else -# define up_tls_info() tls_get_info() -# endif -#endif - /**************************************************************************** * Name: up_tls_size * diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h index a9ebf508aa7cc..257db022ec3ae 100644 --- a/include/nuttx/pthread.h +++ b/include/nuttx/pthread.h @@ -184,6 +184,7 @@ void nx_pthread_exit(FAR void *exit_value) noreturn_function; ****************************************************************************/ #ifdef CONFIG_PTHREAD_CLEANUP +struct tls_info_s; void pthread_cleanup_popall(FAR struct tls_info_s *tls); #endif diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index 9738724487aef..99bec382e801c 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -33,18 +33,16 @@ #include #include #include +#include #include #include #include -#include #include #include #include #include -#include - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ @@ -393,6 +391,8 @@ struct stackinfo_s * the struct task_group_s is free. */ +struct task_info_s; + #ifndef CONFIG_DISABLE_PTHREAD struct join_s; /* Forward reference */ /* Defined in sched/pthread/pthread.h */ diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index 27e031e3e1d3b..33d65ac445d4f 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -27,6 +27,7 @@ #include +#include #include #include @@ -209,88 +210,6 @@ struct tls_info_s * Public Function Prototypes ****************************************************************************/ -/**************************************************************************** - * Name: tls_alloc - * - * Description: - * Allocate a group-unique TLS data index - * - * Input Parameters: - * dtor - The destructor of TLS data element - * - * Returned Value: - * A TLS index that is unique for use within this task group. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -int tls_alloc(CODE void (*dtor)(FAR void *)); -#endif - -/**************************************************************************** - * Name: tls_free - * - * Description: - * Release a group-unique TLS data index previous obtained by tls_alloc() - * - * Input Parameters: - * 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: - * - * -EINVAL - the index to be freed is out of range. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -int tls_free(int tlsindex); -#endif - -/**************************************************************************** - * Name: tls_get_value - * - * Description: - * Return an the TLS data value associated with the 'tlsindx' - * - * Input Parameters: - * tlsindex - Index of TLS data element to return - * - * Returned Value: - * The value of TLS element associated with 'tlsindex'. Errors are not - * reported. Zero 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 tlsindex < 0 or tlsindex >=CONFIG_TLS_NELEM. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -uintptr_t tls_get_value(int tlsindex); -#endif - -/**************************************************************************** - * Name: tls_set_value - * - * Description: - * Set the TLS element associated with the 'tlsindex' to 'tlsvalue' - * - * Input Parameters: - * tlsindex - Index of TLS data element to set - * tlsvalue - The new value of the TLS data element - * - * Returned Value: - * Zero is returned on success, a negated errno value is return on - * failure: - * - * EINVAL - tlsindex is not in range. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -int tls_set_value(int tlsindex, uintptr_t tlsvalue); -#endif - #if CONFIG_TLS_TASK_NELEM > 0 /**************************************************************************** @@ -383,7 +302,11 @@ uintptr_t task_tls_get_value(int tlsindex); * ****************************************************************************/ -#if !defined(CONFIG_TLS_ALIGNED) || defined(__KERNEL__) +#if defined(up_tls_info) +# define tls_get_info() up_tls_info() +#elif defined(CONFIG_TLS_ALIGNED) +# define tls_get_info() TLS_INFO(up_getsp()) +#else FAR struct tls_info_s *tls_get_info(void); #endif diff --git a/libs/libc/errno/lib_errno.c b/libs/libc/errno/lib_errno.c index 87ecb0d5fe0a1..684b2bff92690 100644 --- a/libs/libc/errno/lib_errno.c +++ b/libs/libc/errno/lib_errno.c @@ -24,7 +24,6 @@ #include -#include #include /**************************************************************************** @@ -57,7 +56,7 @@ FAR int *__errno(void) { /* Get the TLS tls_info_s structure instance for this thread */ - FAR struct tls_info_s *tlsinfo = up_tls_info(); + FAR struct tls_info_s *tlsinfo = tls_get_info(); /* And return the return refernce to the error number */ diff --git a/libs/libc/pthread/pthread_cleanup.c b/libs/libc/pthread/pthread_cleanup.c index b8aca803adb61..2df925e68d783 100644 --- a/libs/libc/pthread/pthread_cleanup.c +++ b/libs/libc/pthread/pthread_cleanup.c @@ -28,7 +28,6 @@ #include #include -#include #include #include #include @@ -119,7 +118,7 @@ static void pthread_cleanup_pop_tls(FAR struct tls_info_s *tls, int execute) void pthread_cleanup_pop(int execute) { - FAR struct tls_info_s *tls = up_tls_info(); + FAR struct tls_info_s *tls = tls_get_info(); DEBUGASSERT(tls != NULL); @@ -135,7 +134,7 @@ void pthread_cleanup_pop(int execute) void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg) { - FAR struct tls_info_s *tls = up_tls_info(); + FAR struct tls_info_s *tls = tls_get_info(); DEBUGASSERT(tls != NULL); DEBUGASSERT(tls->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE); diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c index c68ef6a7fac5a..0c0f0a214be39 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/libs/libc/pthread/pthread_exit.c @@ -28,7 +28,6 @@ #include #include -#include #include #include @@ -64,7 +63,7 @@ void pthread_exit(FAR void *exit_value) #endif #ifdef CONFIG_PTHREAD_CLEANUP - pthread_cleanup_popall(up_tls_info()); + pthread_cleanup_popall(tls_get_info()); #endif #if CONFIG_TLS_NELEM > 0 diff --git a/libs/libc/pthread/pthread_getspecific.c b/libs/libc/pthread/pthread_getspecific.c index def22b91295f1..318ba01270a06 100644 --- a/libs/libc/pthread/pthread_getspecific.c +++ b/libs/libc/pthread/pthread_getspecific.c @@ -25,9 +25,12 @@ #include #include +#include #include +#if CONFIG_TLS_NELEM > 0 + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -59,5 +62,23 @@ FAR void *pthread_getspecific(pthread_key_t key) { - return (FAR void *)tls_get_value((int)key); + FAR struct tls_info_s *info; + FAR void *ret = NULL; + + DEBUGASSERT(key >= 0 && key < CONFIG_TLS_NELEM); + if (key >= 0 && key < CONFIG_TLS_NELEM) + { + /* Get the TLS info structure from the current threads stack */ + + info = tls_get_info(); + DEBUGASSERT(info != NULL); + + /* Get the element value from the TLS info. */ + + ret = (FAR void *)info->tl_elem[key]; + } + + return ret; } + +#endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/pthread/pthread_keycreate.c b/libs/libc/pthread/pthread_keycreate.c index fb9e458b8d8ca..478dedec1f1c8 100644 --- a/libs/libc/pthread/pthread_keycreate.c +++ b/libs/libc/pthread/pthread_keycreate.c @@ -26,7 +26,9 @@ #include #include +#include +#include #include #if CONFIG_TLS_NELEM > 0 @@ -70,23 +72,46 @@ int pthread_key_create(FAR pthread_key_t *key, CODE void (*destructor)(FAR void *)) { - int tlsindex; + FAR struct task_info_s *info = task_get_info(); + int candidate; + int ret; DEBUGASSERT(key != NULL); + DEBUGASSERT(info != NULL); - /* Allocate a TLS index */ + /* Search for an unused index. This is done in a critical section here to + * avoid concurrent modification of the group TLS index set. + */ - tlsindex = tls_alloc(destructor); + ret = _SEM_WAIT(&info->ta_sem); - /* Check if found a TLS index. */ + if (ret < 0) + { + ret = _SEM_ERRNO(ret); + return ret; + } + + ret = EAGAIN; - if (tlsindex >= 0) + for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) { - *key = tlsindex; - return OK; + /* Is this candidate index available? */ + + tls_ndxset_t mask = (tls_ndxset_t)1 << candidate; + if ((info->ta_tlsset & mask) == 0) + { + /* Yes.. allocate the index and break out of the loop */ + + info->ta_tlsset |= mask; + info->ta_tlsdtor[candidate] = destructor; + *key = candidate; + ret = OK; + break; + } } - return -tlsindex; + _SEM_POST(&info->ta_sem); + return ret; } #endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/pthread/pthread_keydelete.c b/libs/libc/pthread/pthread_keydelete.c index ad5ab06af417a..51693a4337221 100644 --- a/libs/libc/pthread/pthread_keydelete.c +++ b/libs/libc/pthread/pthread_keydelete.c @@ -25,9 +25,14 @@ #include #include +#include +#include +#include #include +#if CONFIG_TLS_NELEM > 0 + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -52,8 +57,33 @@ int pthread_key_delete(pthread_key_t key) { - /* Free the TLS index */ + FAR struct task_info_s *info = task_get_info(); + tls_ndxset_t mask; + int ret = EINVAL; + + DEBUGASSERT(info != NULL); + DEBUGASSERT(key >= 0 && key < CONFIG_TLS_NELEM); + if (key >= 0 && key < CONFIG_TLS_NELEM) + { + /* This is done while holding a semaphore here to avoid concurrent + * modification of the group TLS index set. + */ - int ret = tls_free((int)key); - return ret < 0 ? -ret : 0; + mask = (tls_ndxset_t)1 << key; + ret = _SEM_WAIT(&info->ta_sem); + if (ret == OK) + { + DEBUGASSERT((info->ta_tlsset & mask) != 0); + info->ta_tlsset &= ~mask; + _SEM_POST(&info->ta_sem); + } + else + { + ret = _SEM_ERRNO(ret); + } + } + + return ret; } + +#endif /* CONFIG_TLS_NELEM */ diff --git a/libs/libc/pthread/pthread_setspecific.c b/libs/libc/pthread/pthread_setspecific.c index 40ed44270f6df..53c543a6dafa5 100644 --- a/libs/libc/pthread/pthread_setspecific.c +++ b/libs/libc/pthread/pthread_setspecific.c @@ -25,6 +25,7 @@ #include #include +#include #include @@ -72,9 +73,23 @@ int pthread_setspecific(pthread_key_t key, FAR const void *value) { - int ret = tls_set_value((int)key, (uintptr_t)value); - return ret < 0 ? -ret : 0; + FAR struct tls_info_s *info; + + DEBUGASSERT(key >= 0 && key < CONFIG_TLS_NELEM); + if (key >= 0 && key < CONFIG_TLS_NELEM) + { + /* Get the TLS info structure from the current threads stack */ + + info = tls_get_info(); + DEBUGASSERT(info != NULL); + + /* Set the element value int the TLS info. */ + + info->tl_elem[key] = (uintptr_t)value; + return OK; + } + + return EINVAL; } #endif /* CONFIG_TLS_NELEM */ - diff --git a/libs/libc/tls/Kconfig b/libs/libc/tls/Kconfig index 171605d022b2a..511a3fb2e9594 100644 --- a/libs/libc/tls/Kconfig +++ b/libs/libc/tls/Kconfig @@ -63,7 +63,7 @@ config TLS_TASK_NELEM The number of unique Task Local Storage elements similar with Thread Local Storage. These can be accessed with task_tls_alloc/task_tls_get_value/task_tls_set_value. - NOTE that the 0 value of CONFIG_SCHED_TLS_NELEM disables these - TLS interfaces. + NOTE that the 0 value of CONFIG_SCHED_TLS_NELEM disables these + TLS interfaces. endmenu # Thread Local Storage (TLS) diff --git a/libs/libc/tls/Make.defs b/libs/libc/tls/Make.defs index 5cb0a7e54f083..f1e929b8e89fa 100644 --- a/libs/libc/tls/Make.defs +++ b/libs/libc/tls/Make.defs @@ -20,13 +20,15 @@ CSRCS += task_getinfo.c tls_getinfo.c +ifneq ($(CONFIG_TLS_TASK_NELEM),0) +CSRCS += task_tls.c +endif + ifneq ($(CONFIG_TLS_NELEM),0) -CSRCS += tls_alloc.c tls_free.c -CSRCS += tls_setvalue.c tls_getvalue.c tls_destruct.c +CSRCS += tls_destruct.c endif # Include tls build support DEPPATH += --dep-path tls VPATH += :tls - diff --git a/libs/libc/tls/task_getinfo.c b/libs/libc/tls/task_getinfo.c index 34800f33f3740..4bfad05c6efb0 100644 --- a/libs/libc/tls/task_getinfo.c +++ b/libs/libc/tls/task_getinfo.c @@ -24,7 +24,6 @@ #include -#include #include /**************************************************************************** @@ -48,7 +47,7 @@ FAR struct task_info_s *task_get_info(void) { - FAR struct tls_info_s *info = up_tls_info(); + FAR struct tls_info_s *info = tls_get_info(); return info->tl_task; } diff --git a/libs/libc/tls/tls_setvalue.c b/libs/libc/tls/task_tls.c similarity index 73% rename from libs/libc/tls/tls_setvalue.c rename to libs/libc/tls/task_tls.c index 6cf775df158b4..9c115eef55d34 100644 --- a/libs/libc/tls/tls_setvalue.c +++ b/libs/libc/tls/task_tls.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/tls/tls_setvalue.c + * libs/libc/tls/task_tls.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -24,61 +24,44 @@ #include -#include #include - -#include #include -#if CONFIG_TLS_NELEM > 0 +#if CONFIG_TLS_TASK_NELEM > 0 /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: tls_set_value + * Name: task_tls_get_value * * Description: - * Set the TLS element associated with the 'tlsindex' to 'tlsvalue' + * Return an the task local storage data value associated with 'tlsindx' * * Input Parameters: - * tlsindex - Index of TLS data element to set - * tlsvalue - The new value of the TLS data element + * tlsindex - Index of task local storage data element to return * * Returned Value: - * Zero is returned on success, a negated errno value is return on - * failure: - * - * EINVAL - tlsindex is not in range. + * The value of TLS element associated with 'tlsindex'. Errors are not + * reported. Zero 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 tlsindex < 0 or tlsindex >=CONFIG_TLS_TASK_NELEM. * ****************************************************************************/ -int tls_set_value(int tlsindex, uintptr_t tlsvalue) +uintptr_t task_tls_get_value(int tlsindex) { - FAR struct tls_info_s *info; + FAR struct task_info_s *info = task_get_info(); - DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - if (tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM) + if (tlsindex >= 0 && tlsindex < CONFIG_TLS_TASK_NELEM) { - /* Get the TLS info structure from the current threads stack */ - - info = up_tls_info(); - DEBUGASSERT(info != NULL); - - /* Set the element value int the TLS info. */ - - info->tl_elem[tlsindex] = tlsvalue; - return OK; + return info->ta_telem[tlsindex]; } - return -EINVAL; + return 0; } -#endif /* CONFIG_TLS_NELEM > 0 */ - -#if CONFIG_TLS_TASK_NELEM > 0 - /**************************************************************************** * Name: task_tls_set_value * diff --git a/libs/libc/tls/tls_destruct.c b/libs/libc/tls/tls_destruct.c index dfbfff53d54c4..b0ffc7bb28371 100644 --- a/libs/libc/tls/tls_destruct.c +++ b/libs/libc/tls/tls_destruct.c @@ -26,7 +26,6 @@ #include -#include #include #if CONFIG_TLS_NELEM > 0 @@ -52,7 +51,7 @@ void tls_destruct(void) { FAR struct task_info_s *info = task_get_info(); - FAR struct tls_info_s *tls = up_tls_info(); + FAR struct tls_info_s *tls = tls_get_info(); FAR void *tls_elem_ptr = NULL; tls_dtor_t destructor; tls_ndxset_t tlsset; diff --git a/libs/libc/tls/tls_getinfo.c b/libs/libc/tls/tls_getinfo.c index be111ccfcfc73..01804fefc4a69 100644 --- a/libs/libc/tls/tls_getinfo.c +++ b/libs/libc/tls/tls_getinfo.c @@ -30,7 +30,7 @@ #include #include -#if !defined(CONFIG_TLS_ALIGNED) || defined(__KERNEL__) +#if !defined(up_tls_info) && !defined(CONFIG_TLS_ALIGNED) /**************************************************************************** * Public Functions @@ -72,4 +72,4 @@ FAR struct tls_info_s *tls_get_info(void) return info; } -#endif /* !CONFIG_TLS_ALIGNED || __KERNEL__ */ +#endif /* !defined(up_tls_info) && !defined(CONFIG_TLS_ALIGNED) */ diff --git a/libs/libc/tls/tls_getvalue.c b/libs/libc/tls/tls_getvalue.c deleted file mode 100644 index d6204ebd89f2d..0000000000000 --- a/libs/libc/tls/tls_getvalue.c +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** - * libs/libc/tls/tls_getvalue.c - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the - * License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include - -#include -#include - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_get_value - * - * Description: - * Return an the TLS data value associated with the 'tlsindx' - * - * Input Parameters: - * tlsindex - Index of TLS data element to return - * - * Returned Value: - * The value of TLS element associated with 'tlsindex'. Errors are not - * reported. Zero 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 tlsindex < 0 or tlsindex >=CONFIG_TLS_NELEM. - * - ****************************************************************************/ - -uintptr_t tls_get_value(int tlsindex) -{ - FAR struct tls_info_s *info; - uintptr_t ret = 0; - - DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - if (tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM) - { - /* Get the TLS info structure from the current threads stack */ - - info = up_tls_info(); - DEBUGASSERT(info != NULL); - - /* Get the element value from the TLS info. */ - - ret = info->tl_elem[tlsindex]; - } - - return ret; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ - -#if CONFIG_TLS_TASK_NELEM > 0 - -/**************************************************************************** - * Name: task_tls_get_value - * - * Description: - * Return an the task local storage data value associated with 'tlsindx' - * - * Input Parameters: - * tlsindex - Index of task local storage data element to return - * - * Returned Value: - * The value of TLS element associated with 'tlsindex'. Errors are not - * reported. Zero 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 tlsindex < 0 or tlsindex >=CONFIG_TLS_TASK_NELEM. - * - ****************************************************************************/ - -uintptr_t task_tls_get_value(int tlsindex) -{ - FAR struct task_info_s *info = task_get_info(); - - if (tlsindex >= 0 && tlsindex < CONFIG_TLS_TASK_NELEM) - { - return info->ta_telem[tlsindex]; - } - - return 0; -} - -#endif diff --git a/sched/Makefile b/sched/Makefile index 9f7c7ca477446..f79387de7f95b 100644 --- a/sched/Makefile +++ b/sched/Makefile @@ -34,6 +34,7 @@ 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/group/group_create.c b/sched/group/group_create.c index e5347ff541c85..319eadffe3c82 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -35,10 +35,10 @@ #include #include #include -#include #include "sched/sched.h" #include "group/group.h" +#include "tls/tls.h" /**************************************************************************** * Pre-processor Definitions @@ -185,9 +185,8 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) /* Alloc task info for group */ - group->tg_info = (FAR struct task_info_s *) - group_zalloc(group, sizeof(struct task_info_s)); - if (!group->tg_info) + ret = task_init_info(group); + if (ret < 0) { goto errout_with_member; } @@ -200,10 +199,6 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) group_inherit_identity(group); - /* Initial user space semaphore */ - - nxsem_init(&group->tg_info->ta_sem, 0, 1); - /* Initialize file descriptors for the TCB */ files_initlist(&group->tg_filelist); diff --git a/sched/group/group_leave.c b/sched/group/group_leave.c index 935b3cfc91863..d4bda7d59965a 100644 --- a/sched/group/group_leave.c +++ b/sched/group/group_leave.c @@ -44,6 +44,7 @@ #include "pthread/pthread.h" #include "mqueue/mqueue.h" #include "group/group.h" +#include "tls/tls.h" /**************************************************************************** * Private Functions @@ -137,8 +138,7 @@ static inline void group_release(FAR struct task_group_s *group) task_tls_destruct(); #endif - nxsem_destroy(&group->tg_info->ta_sem); - group_free(group, group->tg_info); + task_uninit_info(group); #if defined(CONFIG_SCHED_HAVE_PARENT) && defined(CONFIG_SCHED_CHILD_STATUS) /* Free all un-reaped child exit status */ diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c index e80fe647b4eac..368240b7c3a49 100644 --- a/sched/pthread/pthread_cancel.c +++ b/sched/pthread/pthread_cancel.c @@ -89,7 +89,7 @@ int pthread_cancel(pthread_t thread) pthread_exit(PTHREAD_CANCELED); } - /* Refer to up_tls_info() */ + /* Refer to tls_get_info() */ #ifdef CONFIG_PTHREAD_CLEANUP pthread_cleanup_popall(tcb->stack_alloc_ptr); diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c index c0fd3dd5aa9f7..66bde29ce9914 100644 --- a/sched/pthread/pthread_create.c +++ b/sched/pthread/pthread_create.c @@ -40,12 +40,12 @@ #include #include #include -#include #include "sched/sched.h" #include "group/group.h" #include "clock/clock.h" #include "pthread/pthread.h" +#include "tls/tls.h" /**************************************************************************** * Public Data @@ -215,7 +215,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, pthread_startroutine_t entry, pthread_addr_t arg) { FAR struct pthread_tcb_s *ptcb; - FAR struct tls_info_s *info; FAR struct join_s *pjoin; struct sched_param param; int policy; @@ -291,8 +290,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, { /* Allocate the stack for the TCB */ - ret = up_create_stack((FAR struct tcb_s *)ptcb, - up_tls_size() + attr->stacksize, + ret = up_create_stack((FAR struct tcb_s *)ptcb, attr->stacksize, TCB_FLAG_TTYPE_PTHREAD); } @@ -304,21 +302,13 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread, /* Initialize thread local storage */ - info = up_stack_frame(&ptcb->cmn, up_tls_size()); - if (info == NULL) + ret = tls_init_info(&ptcb->cmn); + if (ret != OK) { - errcode = ENOMEM; + errcode = -ret; goto errout_with_join; } - DEBUGASSERT(info == ptcb->cmn.stack_alloc_ptr); - - up_tls_initialize(info); - - /* Attach per-task info in group to TLS */ - - info->tl_task = ptcb->cmn.group->tg_info; - /* Should we use the priority and scheduler specified in the pthread * attributes? Or should we use the current thread's priority and * scheduler? diff --git a/sched/task/task_init.c b/sched/task/task_init.c index 5cbb774fbab77..52bbdde774170 100644 --- a/sched/task/task_init.c +++ b/sched/task/task_init.c @@ -33,12 +33,12 @@ #include #include -#include #include "sched/sched.h" #include "environ/environ.h" #include "group/group.h" #include "task/task.h" +#include "tls/tls.h" /**************************************************************************** * Public Functions @@ -88,7 +88,6 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, FAR char * const envp[]) { uint8_t ttype = tcb->cmn.flags & TCB_FLAG_TTYPE_MASK; - FAR struct tls_info_s *info; int ret; #ifndef CONFIG_DISABLE_PTHREAD @@ -131,9 +130,7 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, { /* Allocate the stack for the TCB */ - ret = up_create_stack(&tcb->cmn, - up_tls_size() + stack_size, - ttype); + ret = up_create_stack(&tcb->cmn, stack_size, ttype); } if (ret < OK) @@ -143,19 +140,12 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority, /* Initialize thread local storage */ - info = up_stack_frame(&tcb->cmn, up_tls_size()); - if (info == NULL) + ret = tls_init_info(&tcb->cmn); + if (ret < OK) { - ret = -ENOMEM; goto errout_with_group; } - DEBUGASSERT(info == tcb->cmn.stack_alloc_ptr); - - info->tl_task = tcb->cmn.group->tg_info; - - up_tls_initialize(info); - /* 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 36adfbb3647c5..45965e879bc53 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" diff --git a/sched/task/task_start.c b/sched/task/task_start.c index 11af95dcd24da..745531ab9bf5e 100644 --- a/sched/task/task_start.c +++ b/sched/task/task_start.c @@ -32,6 +32,7 @@ #include #include +#include #include "group/group.h" #include "sched/sched.h" diff --git a/sched/task/task_vfork.c b/sched/task/task_vfork.c index f535614c6299f..a56f8c195d708 100644 --- a/sched/task/task_vfork.c +++ b/sched/task/task_vfork.c @@ -40,6 +40,7 @@ #include "environ/environ.h" #include "group/group.h" #include "task/task.h" +#include "tls/tls.h" /* vfork() requires architecture-specific support as well as waipid(). */ @@ -97,7 +98,6 @@ FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr) FAR struct tcb_s *ptcb = this_task(); FAR struct tcb_s *parent; FAR struct task_tcb_s *child; - FAR struct tls_info_s *info; size_t stack_size; uint8_t ttype; int priority; @@ -181,19 +181,12 @@ FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr) /* Setup thread local storage */ - info = up_stack_frame(&child->cmn, up_tls_size()); - if (info == NULL) + ret = tls_dup_info(&child->cmn, parent); + if (ret < OK) { - ret = -ENOMEM; goto errout_with_tcb; } - DEBUGASSERT(info == child->cmn.stack_alloc_ptr); - memcpy(info, parent->stack_alloc_ptr, sizeof(struct tls_info_s)); - info->tl_task = child->cmn.group->tg_info; - - up_tls_initialize(info); - /* Get the priority of the parent task */ #ifdef CONFIG_PRIORITY_INHERITANCE diff --git a/sched/tls/Make.defs b/sched/tls/Make.defs new file mode 100644 index 0000000000000..a5ea535f4de34 --- /dev/null +++ b/sched/tls/Make.defs @@ -0,0 +1,26 @@ +############################################################################ +# sched/tls/Make.defs +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. The +# ASF licenses this file to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance with the +# License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. +# +############################################################################ + +CSRCS += task_initinfo.c task_uninitinfo.c tls_initinfo.c tls_dupinfo.c + +# Include tls build support + +DEPPATH += --dep-path tls +VPATH += :tls diff --git a/sched/tls/task_initinfo.c b/sched/tls/task_initinfo.c new file mode 100644 index 0000000000000..4ccf1e9f7eeaa --- /dev/null +++ b/sched/tls/task_initinfo.c @@ -0,0 +1,69 @@ +/**************************************************************************** + * sched/tls/task_initinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include "tls.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_init_info + * + * Description: + * Allocate and initilize task_info_s structure. + * + * Input Parameters: + * - group: The group of new task + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int task_init_info(FAR struct task_group_s *group) +{ + FAR struct task_info_s *info; + + /* Allocate task info for group */ + + info = group_zalloc(group, sizeof(struct task_info_s)); + if (info == NULL) + { + return -ENOMEM; + } + + /* Initialize user space semaphore */ + + nxsem_init(&info->ta_sem, 0, 1); + group->tg_info = info; + + return OK; +} diff --git a/sched/tls/task_uninitinfo.c b/sched/tls/task_uninitinfo.c new file mode 100644 index 0000000000000..f4dca8903e395 --- /dev/null +++ b/sched/tls/task_uninitinfo.c @@ -0,0 +1,55 @@ +/**************************************************************************** + * sched/tls/task_uninitinfo.c + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +#include + +#include "tls.h" + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: task_uninit_info + * + * Description: + * Uninitilize and free task_info_s structure. + * + * Input Parameters: + * - group: The group of new task + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void task_uninit_info(FAR struct task_group_s *group) +{ + FAR struct task_info_s *info = group->tg_info; + + nxsem_destroy(&info->ta_sem); + group_free(group, info); +} diff --git a/sched/tls/tls.h b/sched/tls/tls.h new file mode 100644 index 0000000000000..e9adeacda0e37 --- /dev/null +++ b/sched/tls/tls.h @@ -0,0 +1,99 @@ +/**************************************************************************** + * sched/tls/tls.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + ****************************************************************************/ + +#ifndef __SCHED_TLS_TLS_H +#define __SCHED_TLS_TLS_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Name: task_init_info + * + * Description: + * Allocate and initilize task_info_s structure. + * + * Input Parameters: + * - group: The group of new task + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int task_init_info(FAR struct task_group_s *group); + +/**************************************************************************** + * Name: task_uninit_info + * + * Description: + * Uninitilize and free task_info_s structure. + * + * Input Parameters: + * - group: The group of new task + * + * Returned Value: + * None. + * + ****************************************************************************/ + +void task_uninit_info(FAR struct task_group_s *group); + +/**************************************************************************** + * Name: tls_init_info + * + * Description: + * Allocate and initilize tls_info_s structure. + * + * Input Parameters: + * - tcb: The TCB of new task + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int tls_init_info(FAR struct tcb_s *tcb); + +/**************************************************************************** + * Name: tls_dup_info + * + * Description: + * Allocate and duplicate tls_info_s structure. + * + * Input Parameters: + * - dst: The TCB of new task + * - src: The TCB of source task + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int tls_dup_info(FAR struct tcb_s *dst, FAR struct tcb_s *src); + +#endif /* __SCHED_TLS_TLS_H */ diff --git a/libs/libc/tls/tls_alloc.c b/sched/tls/tls_dupinfo.c similarity index 55% rename from libs/libc/tls/tls_alloc.c rename to sched/tls/tls_dupinfo.c index 46860d0eceba1..a22efd3d0c599 100644 --- a/libs/libc/tls/tls_alloc.c +++ b/sched/tls/tls_dupinfo.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/tls/tls_alloc.c + * sched/tls/tls_dupinfo.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -22,79 +22,54 @@ * Included Files ****************************************************************************/ -#include - -#include -#include #include -#include +#include +#include -#include +#include #include -#include -#if CONFIG_TLS_NELEM > 0 +#include "tls.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: tls_alloc + * Name: tls_dup_info * * Description: - * Allocate a group-unique TLS data index + * Allocate and duplicate tls_info_s structure. * * Input Parameters: - * None + * - dst: The TCB of new task + * - src: The TCB of source task * * 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. + * Zero (OK) on success; a negated errno value on failure. * ****************************************************************************/ -int tls_alloc(CODE void (*dtor)(FAR void *)) +int tls_dup_info(FAR struct tcb_s *dst, FAR struct tcb_s *src) { - FAR struct task_info_s *info = task_get_info(); - int candidate; - int ret; - - DEBUGASSERT(info); - - /* Search for an unused index. This is done in a critical section here to - * avoid concurrent modification of the group TLS index set. - */ + FAR struct tls_info_s *info; - ret = _SEM_WAIT(&info->ta_sem); + /* Allocate thread local storage */ - if (ret < 0) + info = up_stack_frame(dst, up_tls_size()); + if (info == NULL) { - ret = _SEM_ERRVAL(ret); - return ret; + return -ENOMEM; } - ret = -EAGAIN; + DEBUGASSERT(info == dst->stack_alloc_ptr); - for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) - { - /* Is this candidate index available? */ - - tls_ndxset_t mask = (tls_ndxset_t)1 << candidate; - if ((info->ta_tlsset & mask) == 0) - { - /* Yes.. allocate the index and break out of the loop */ + /* Copy thread local storage */ - info->ta_tlsset |= mask; - info->ta_tlsdtor[candidate] = dtor; - ret = candidate; - break; - } - } + memcpy(info, src->stack_alloc_ptr, sizeof(struct tls_info_s)); - _SEM_POST(&info->ta_sem); + /* Attach per-task info in group to TLS */ - return ret; + info->tl_task = dst->group->tg_info; + return OK; } - -#endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/libs/libc/tls/tls_free.c b/sched/tls/tls_initinfo.c similarity index 55% rename from libs/libc/tls/tls_free.c rename to sched/tls/tls_initinfo.c index e9f7eb576f73e..0b7e08ab996d0 100644 --- a/libs/libc/tls/tls_free.c +++ b/sched/tls/tls_initinfo.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/tls/tls_free.c + * sched/tls/tls_initinfo.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -22,69 +22,52 @@ * Included Files ****************************************************************************/ -#include - -#include -#include #include +#include -#include +#include #include -#include -#if CONFIG_TLS_NELEM > 0 +#include "tls.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: tls_free + * Name: tls_init_info * * Description: - * Release a group-unique TLS data index previous obtained by tls_alloc() + * Allocate and initilize tls_info_s structure. * * Input Parameters: - * tlsindex - The previously allocated TLS index to be freed + * - tcb: The TCB of new task * * Returned Value: - * OK is returned on success; - * If unsuccessful an errno value will be returned and set to errno. - * -EINVAL - the index to be freed is out of range. - * -EINTR - the wait operation interrupted by signal - * -ECANCELED - the thread was canceled during waiting + * Zero (OK) on success; a negated errno value on failure. * ****************************************************************************/ -int tls_free(int tlsindex) +int tls_init_info(FAR struct tcb_s *tcb) { - FAR struct task_info_s *info = task_get_info(); - tls_ndxset_t mask; - int ret = -EINVAL; + FAR struct tls_info_s *info; - DEBUGASSERT((unsigned)tlsindex < CONFIG_TLS_NELEM && info != NULL); - if ((unsigned)tlsindex < CONFIG_TLS_NELEM) + /* Allocate thread local storage */ + + info = up_stack_frame(tcb, up_tls_size()); + if (info == NULL) { - /* This is done while holding a semaphore here to avoid concurrent - * modification of the group TLS index set. - */ + return -ENOMEM; + } - mask = (1 << tlsindex); + DEBUGASSERT(info == tcb->stack_alloc_ptr); - ret = _SEM_WAIT(&info->ta_sem); - if (ret == OK) - { - DEBUGASSERT((info->ta_tlsset & mask) != 0); - info->ta_tlsset &= ~mask; - _SEM_POST(&info->ta_sem); - } - else - { - ret = _SEM_ERRVAL(ret); - } - } + /* Initialize thread local storage */ - return ret; -} + up_tls_initialize(info); -#endif /* CONFIG_TLS_NELEM > 0 */ + /* Attach per-task info in group to TLS */ + + info->tl_task = tcb->group->tg_info; + return OK; +}