diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index 3814aa5d86..a7d28f3d3d 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -63,6 +63,13 @@ struct task_info_s { + sem_t ta_sem; + +#if CONFIG_TLS_NELEM > 0 + tls_ndxset_t ta_tlsset; /* Set of TLS indexes allocated */ + tls_dtor_t ta_tlsdtor[CONFIG_TLS_NELEM]; /* List of TLS destructors */ +#endif + #ifndef CONFIG_BUILD_KERNEL struct getopt_s ta_getopt; /* Globals used by getopt() */ #endif @@ -105,6 +112,7 @@ struct task_info_s struct tls_info_s { FAR struct task_info_s * tl_task; + #if CONFIG_TLS_NELEM > 0 uintptr_t tl_elem[CONFIG_TLS_NELEM]; /* TLS elements */ #endif @@ -132,7 +140,7 @@ struct tls_info_s * Allocate a group-unique TLS data index * * Input Parameters: - * None + * dtor - The destructor of TLS data element * * Returned Value: * A TLS index that is unique for use within this task group. @@ -140,7 +148,7 @@ struct tls_info_s ****************************************************************************/ #if CONFIG_TLS_NELEM > 0 -int tls_alloc(void); +int tls_alloc(CODE void (*dtor)(FAR void *)); #endif /**************************************************************************** @@ -228,63 +236,6 @@ int tls_set_value(int tlsindex, uintptr_t tlsvalue); FAR struct tls_info_s *tls_get_info(void); #endif -/**************************************************************************** - * Name: tls_set_dtor - * - * Description: - * Set the TLS element destructor associated with the 'tlsindex' to 'destr' - * - * Input Parameters: - * tlsindex - Index of TLS data destructor to set - * destr - The destr of 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_dtor(int tlsindex, tls_dtor_t destr); -#endif - -/**************************************************************************** - * Name: tls_get_dtor - * - * Description: - * Get the TLS element destructor associated with the 'tlsindex' to 'destr' - * - * Input Parameters: - * tlsindex - Index of TLS data destructor to get - * - * Returned Value: - * A non-null destruct function pointer. - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -tls_dtor_t tls_get_dtor(int tlsindex); -#endif - -/**************************************************************************** - * Name: tls_get_set - * - * Description: - * Get the TLS element index set map - * - * Input Parameters: - * - * Returned Value: - * A set of allocated TLS index - * - ****************************************************************************/ - -#if CONFIG_TLS_NELEM > 0 -tls_ndxset_t tls_get_set(void); -#endif - /**************************************************************************** * Name: tls_destruct * 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..fb9e458b8d 100644 --- a/libs/libc/pthread/pthread_keycreate.c +++ b/libs/libc/pthread/pthread_keycreate.c @@ -76,16 +76,13 @@ int pthread_key_create(FAR pthread_key_t *key, /* Allocate a TLS index */ - tlsindex = tls_alloc(); + tlsindex = tls_alloc(destructor); /* Check if found a TLS index. */ if (tlsindex >= 0) { - /* Yes.. Return the key value and success */ - - *key = (pthread_key_t)tlsindex; - tls_set_dtor(tlsindex, destructor); + *key = tlsindex; return OK; } diff --git a/libs/libc/tls/Make.defs b/libs/libc/tls/Make.defs index 67e830f71a..8cc8e83f80 100644 --- a/libs/libc/tls/Make.defs +++ b/libs/libc/tls/Make.defs @@ -21,6 +21,7 @@ CSRCS += task_getinfo.c ifneq ($(CONFIG_TLS_NELEM),0) +CSRCS += tls_alloc.c tls_free.c CSRCS += tls_setvalue.c tls_getvalue.c tls_destruct.c endif diff --git a/sched/group/group_tlsalloc.c b/libs/libc/tls/tls_alloc.c similarity index 80% rename from sched/group/group_tlsalloc.c rename to libs/libc/tls/tls_alloc.c index 5b09073abc..7563d3834f 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 @@ -31,9 +31,7 @@ #include #include - -#include "sched/sched.h" -#include "group/group.h" +#include #if CONFIG_TLS_NELEM > 0 @@ -52,48 +50,49 @@ * * 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) +int tls_alloc(CODE void (*dtor)(FAR void *)) { - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; - irqstate_t flags; + FAR struct task_info_s *info = task_get_info(); int candidate; - int ret = -EAGAIN; + int ret; - DEBUGASSERT(group != NULL); + 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. */ - flags = spin_lock_irqsave(NULL); + ret = _SEM_WAIT(&info->ta_sem); + + if (ret < 0) + { + ret = _SEM_ERRVAL(ret); + return ret; + } + + ret = -EAGAIN; + 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 ((info->ta_tlsset & mask) == 0) { /* Yes.. allocate the index and break out of the loop */ - group->tg_tlsset |= mask; + info->ta_tlsset |= mask; + info->ta_tlsdtor[candidate] = dtor; + ret = candidate; break; } } - spin_unlock_irqrestore(NULL, flags); - - /* Check if found a valid TLS data index. */ - - if (candidate < CONFIG_TLS_NELEM) - { - /* Yes.. Return the TLS index and success */ - - ret = candidate; - } + _SEM_POST(&info->ta_sem); return ret; } diff --git a/libs/libc/tls/tls_destruct.c b/libs/libc/tls/tls_destruct.c index 847dc8dbba..c63f05d2c9 100644 --- a/libs/libc/tls/tls_destruct.c +++ b/libs/libc/tls/tls_destruct.c @@ -53,14 +53,15 @@ void tls_destruct(void) { - FAR struct tls_info_s *info = up_tls_info(); + FAR struct task_info_s *info = task_get_info(); + FAR struct tls_info_s *tls = up_tls_info(); FAR void *tls_elem_ptr = NULL; tls_dtor_t destructor; tls_ndxset_t tlsset; int candidate; DEBUGASSERT(info != NULL); - tlsset = tls_get_set(); + tlsset = info->ta_tlsset; for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) { @@ -69,8 +70,8 @@ void tls_destruct(void) tls_ndxset_t mask = (1 << candidate); if (tlsset & mask) { - tls_elem_ptr = (FAR void *)info->tl_elem[candidate]; - destructor = tls_get_dtor(candidate); + tls_elem_ptr = (FAR void *)tls->tl_elem[candidate]; + destructor = info->ta_tlsdtor[candidate]; if (tls_elem_ptr && destructor) { destructor(tls_elem_ptr); diff --git a/sched/group/group_tlsfree.c b/libs/libc/tls/tls_free.c similarity index 72% rename from sched/group/group_tlsfree.c rename to libs/libc/tls/tls_free.c index c1eccaf25d..e9f7eb576f 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 @@ -30,9 +30,7 @@ #include #include - -#include "sched/sched.h" -#include "group/group.h" +#include #if CONFIG_TLS_NELEM > 0 @@ -50,36 +48,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: - * - * -EINVAL - the index to be freed is out of range. + * 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 * ****************************************************************************/ 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 *info = 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 && info != 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(&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); + } } return ret; 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/group/group_create.c b/sched/group/group_create.c index 791edbb835..6fbfcf8800 100644 --- a/sched/group/group_create.c +++ b/sched/group/group_create.c @@ -180,6 +180,10 @@ int group_allocate(FAR struct task_tcb_s *tcb, uint8_t ttype) goto errout_with_stream; } + /* Initial user space semaphore */ + + nxsem_init(&group->tg_info->ta_sem, 0, 1); + /* Attach the group to the TCB */ tcb->cmn.group = group; @@ -242,6 +246,7 @@ void group_deallocate(FAR struct task_group_s *group) { if (group->tg_info) { + nxsem_destroy(&group->tg_info->ta_sem); group_free(group, group->tg_info); } diff --git a/sched/group/group_tlsgetdtor.c b/sched/group/group_tlsgetdtor.c deleted file mode 100644 index c6e25f3f70..0000000000 --- a/sched/group/group_tlsgetdtor.c +++ /dev/null @@ -1,75 +0,0 @@ -/**************************************************************************** - * sched/group/group_tlsgetdtor.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 -#include -#include - -#include "sched/sched.h" -#include "group/group.h" - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_get_dtor - * - * Description: - * Get the TLS element destructor associated with the 'tlsindex' to 'destr' - * - * Input Parameters: - * tlsindex - Index of TLS data destructor to get - * - * Returned Value: - * A non-null destruct function pointer. - * - ****************************************************************************/ - -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; - - DEBUGASSERT(group != NULL); - DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - - flags = spin_lock_irqsave(NULL); - destr = group->tg_tlsdestr[tlsindex]; - spin_unlock_irqrestore(NULL, flags); - - return destr; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/sched/group/group_tlsgetset.c b/sched/group/group_tlsgetset.c deleted file mode 100644 index a3405c44a5..0000000000 --- a/sched/group/group_tlsgetset.c +++ /dev/null @@ -1,73 +0,0 @@ -/**************************************************************************** - * sched/group/group_tlsgetset.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 -#include -#include - -#include "sched/sched.h" -#include "group/group.h" - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_get_set - * - * Description: - * Get the set map of TLE element index. - * - * Input Parameters: - * - * Returned Value: - * TLS element index set map. - * - ****************************************************************************/ - -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; - tls_ndxset_t tlsset; - - DEBUGASSERT(group != NULL); - - flags = spin_lock_irqsave(NULL); - tlsset = group->tg_tlsset; - spin_unlock_irqrestore(NULL, flags); - - return tlsset; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/sched/group/group_tlssetdtor.c b/sched/group/group_tlssetdtor.c deleted file mode 100644 index 040ff65822..0000000000 --- a/sched/group/group_tlssetdtor.c +++ /dev/null @@ -1,78 +0,0 @@ -/**************************************************************************** - * sched/group/group_tlssetdtor.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 -#include -#include - -#include "sched/sched.h" -#include "group/group.h" - -#if CONFIG_TLS_NELEM > 0 - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: tls_set_dtor - * - * Description: - * Set the TLS element destructor associated with the 'tlsindex' to 'destr' - * - * Input Parameters: - * tlsindex - Index of TLS data destructor to set - * destr - The destr of TLS data element - * - * Returned Value: - * Zero is returned on success, a negated errno value is return on - * failure: - * - * EINVAL - tlsindex is not in range. - * - ****************************************************************************/ - -int tls_set_dtor(int tlsindex, tls_dtor_t destr) -{ - FAR struct tcb_s *rtcb = this_task(); - FAR struct task_group_s *group = rtcb->group; - irqstate_t flags; - - DEBUGASSERT(group != NULL); - DEBUGASSERT(tlsindex >= 0 && tlsindex < CONFIG_TLS_NELEM); - - flags = spin_lock_irqsave(NULL); - group->tg_tlsdestr[tlsindex] = destr; - spin_unlock_irqrestore(NULL, flags); - - return OK; -} - -#endif /* CONFIG_TLS_NELEM > 0 */ 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 *"