diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index a7d0c4ffbe2..f425e47afd2 100644 --- a/include/nuttx/sched.h +++ b/include/nuttx/sched.h @@ -345,7 +345,7 @@ struct pthread_cleanup_s }; #endif -/* type tls_ndxset_t ************************************************************/ +/* type tls_ndxset_t & tls_dtor_t **********************************************/ /* Smallest addressable type that can hold the entire configured number of TLS * data indexes. @@ -361,6 +361,9 @@ struct pthread_cleanup_s # else typedef uint8_t tls_ndxset_t; # endif + +typedef CODE void (*tls_dtor_t)(FAR void *); + #endif /* struct dspace_s **************************************************************/ @@ -528,7 +531,8 @@ struct task_group_s /* Thread local storage *******************************************************/ #if CONFIG_TLS_NELEM > 0 - tls_ndxset_t tg_tlsset; /* Set of TLS data indexes allocated */ + 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 ************************************************/ diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h index c370abc635b..d45230dd066 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -29,6 +29,7 @@ #include #include +#include /**************************************************************************** * Pre-processor Definitions @@ -227,6 +228,81 @@ 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 + * + * Description: + * Destruct all TLS data element associated with allocated key + * + * Input Parameters: + * None + * + * Returned Value: + * A set of allocated TLS index + * + ****************************************************************************/ + +#if CONFIG_TLS_NELEM > 0 +void tls_destruct(void); +#endif + /**************************************************************************** * Name: task_get_info * diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 5a66d8f5177..23149086143 100644 --- a/include/sys/syscall_lookup.h +++ b/include/sys/syscall_lookup.h @@ -296,6 +296,9 @@ SYSCALL_LOOKUP(telldir, 1) #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 */ diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c index ce1324c5719..086dc7f59db 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/libs/libc/pthread/pthread_exit.c @@ -28,6 +28,7 @@ #include #include +#include /**************************************************************************** * Public Functions @@ -55,6 +56,10 @@ void pthread_exit(FAR void *exit_value) pthread_cleanup_popall(); #endif +#if CONFIG_TLS_NELEM > 0 + tls_destruct(); +#endif + nx_pthread_exit(exit_value); PANIC(); } diff --git a/libs/libc/pthread/pthread_keycreate.c b/libs/libc/pthread/pthread_keycreate.c index 5765fb694d6..798cca7d38f 100644 --- a/libs/libc/pthread/pthread_keycreate.c +++ b/libs/libc/pthread/pthread_keycreate.c @@ -53,8 +53,6 @@ * key - A pointer to the key to create. * destructor - An optional destructor() function that may be associated * with each key that is invoked when a thread exits. - * However, this argument is ignored in the current - * implementation. * * Returned Value: * If successful, the pthread_key_create() function will store the newly @@ -67,9 +65,6 @@ * has been exceeded * ENOMEM - Insufficient memory exist to create the key. * - * POSIX Compatibility: - * - The present implementation ignores the destructor argument. - * ****************************************************************************/ int pthread_key_create(FAR pthread_key_t *key, @@ -90,6 +85,7 @@ int pthread_key_create(FAR pthread_key_t *key, /* Yes.. Return the key value and success */ *key = (pthread_key_t)tlsindex; + tls_set_dtor(tlsindex, destructor); return OK; } diff --git a/libs/libc/tls/Make.defs b/libs/libc/tls/Make.defs index 504d2c6a0bf..67e830f71ac 100644 --- a/libs/libc/tls/Make.defs +++ b/libs/libc/tls/Make.defs @@ -21,7 +21,7 @@ CSRCS += task_getinfo.c ifneq ($(CONFIG_TLS_NELEM),0) -CSRCS += tls_setvalue.c tls_getvalue.c +CSRCS += tls_setvalue.c tls_getvalue.c tls_destruct.c endif ifneq ($(CONFIG_TLS_ALIGNED),y) diff --git a/libs/libc/tls/tls_destruct.c b/libs/libc/tls/tls_destruct.c new file mode 100644 index 00000000000..847dc8dbba3 --- /dev/null +++ b/libs/libc/tls/tls_destruct.c @@ -0,0 +1,82 @@ +/**************************************************************************** + * libs/libc/tls/tls_destruct.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 + +#if CONFIG_TLS_NELEM > 0 + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: tls_destruct + * + * Description: + * Destruct all TLS data element associated with allocated key + * + * Input Parameters: + * None + * + * Returned Value: + * A set of allocated TLS index + * + ****************************************************************************/ + +void tls_destruct(void) +{ + FAR struct tls_info_s *info = 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(); + + for (candidate = 0; candidate < CONFIG_TLS_NELEM; candidate++) + { + /* Is this candidate index available? */ + + tls_ndxset_t mask = (1 << candidate); + if (tlsset & mask) + { + tls_elem_ptr = (FAR void *)info->tl_elem[candidate]; + destructor = tls_get_dtor(candidate); + if (tls_elem_ptr && destructor) + { + destructor(tls_elem_ptr); + } + } + } +} + +#endif /* CONFIG_TLS_NELEM > 0 */ diff --git a/sched/group/Make.defs b/sched/group/Make.defs index 14f12257491..35eee897029 100644 --- a/sched/group/Make.defs +++ b/sched/group/Make.defs @@ -55,6 +55,7 @@ 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 diff --git a/sched/group/group_tlsgetdtor.c b/sched/group/group_tlsgetdtor.c new file mode 100644 index 00000000000..2aa41452835 --- /dev/null +++ b/sched/group/group_tlsgetdtor.c @@ -0,0 +1,74 @@ +/**************************************************************************** + * 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 "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 new file mode 100644 index 00000000000..55c5dac9a24 --- /dev/null +++ b/sched/group/group_tlsgetset.c @@ -0,0 +1,72 @@ +/**************************************************************************** + * 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 "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 new file mode 100644 index 00000000000..5e4447c3c39 --- /dev/null +++ b/sched/group/group_tlssetdtor.c @@ -0,0 +1,77 @@ +/**************************************************************************** + * 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 "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/sched/pthread/pthread_exit.c b/sched/pthread/pthread_exit.c index 4d55560f533..6805849ab95 100644 --- a/sched/pthread/pthread_exit.c +++ b/sched/pthread/pthread_exit.c @@ -34,6 +34,7 @@ #include #include +#include #include "sched/sched.h" #include "task/task.h" diff --git a/syscall/syscall.csv b/syscall/syscall.csv index c39442f30d2..3f180b0664d 100644 --- a/syscall/syscall.csv +++ b/syscall/syscall.csv @@ -179,6 +179,9 @@ "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_set","nuttx/tls.h","CONFIG_TLS_NELEM > 0","tls_ndxset_t" +"tls_get_dtor","nuttx/tls.h","CONFIG_TLS_NELEM > 0","tls_dtor_t","int" +"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 *"