This is an automated email from the ASF dual-hosted git repository. gnutt pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit d374d55926592ce9571eb80971964aaa14124034 Author: Huang Qi <[email protected]> AuthorDate: Thu Apr 22 10:41:50 2021 +0800 pthread: Implement destructor of pthread_key_create Signed-off-by: Huang Qi <[email protected]> Change-Id: I6aafba9680257cba071bf1f72ae2ec2c475f5fb0 --- include/nuttx/sched.h | 8 ++- include/nuttx/tls.h | 76 ++++++++++++++++++++++ include/sys/syscall_lookup.h | 3 + libs/libc/pthread/pthread_exit.c | 5 ++ libs/libc/pthread/pthread_keycreate.c | 6 +- libs/libc/tls/Make.defs | 2 +- .../{pthread/pthread_exit.c => tls/tls_destruct.c} | 54 ++++++++++----- sched/group/Make.defs | 1 + .../group/group_tlsgetdtor.c | 46 ++++++++----- .../group/group_tlsgetset.c | 44 ++++++++----- .../group/group_tlssetdtor.c | 47 ++++++++----- sched/pthread/pthread_exit.c | 1 + syscall/syscall.csv | 3 + 13 files changed, 225 insertions(+), 71 deletions(-) diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h index a7d0c4f..f425e47 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 c370abc..d45230d 100644 --- a/include/nuttx/tls.h +++ b/include/nuttx/tls.h @@ -29,6 +29,7 @@ #include <nuttx/sched.h> #include <nuttx/lib/getopt.h> +#include <sys/types.h> /**************************************************************************** * Pre-processor Definitions @@ -228,6 +229,81 @@ 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 * * Description: diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h index 5a66d8f..2314908 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 ce1324c..086dc7f 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/libs/libc/pthread/pthread_exit.c @@ -28,6 +28,7 @@ #include <sched.h> #include <nuttx/pthread.h> +#include <nuttx/tls.h> /**************************************************************************** * 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 5765fb6..798cca7 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 504d2c6..67e830f 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/pthread/pthread_exit.c b/libs/libc/tls/tls_destruct.c similarity index 61% copy from libs/libc/pthread/pthread_exit.c copy to libs/libc/tls/tls_destruct.c index ce1324c..847dc8d 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/libs/libc/tls/tls_destruct.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/pthread/pthread_exit.c + * 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 @@ -24,37 +24,59 @@ #include <nuttx/config.h> -#include <debug.h> -#include <sched.h> +#include <stdint.h> +#include <assert.h> -#include <nuttx/pthread.h> +#include <nuttx/arch.h> +#include <nuttx/tls.h> +#include <arch/tls.h> + +#if CONFIG_TLS_NELEM > 0 /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: pthread_exit + * Name: tls_destruct * * Description: - * Terminate execution of a thread started with pthread_create. + * Destruct all TLS data element associated with allocated key * * Input Parameters: - * exit_value - The pointer of the pthread_exit parameter + * None * * Returned Value: - * None - * - * Assumptions: + * A set of allocated TLS index * ****************************************************************************/ -void pthread_exit(FAR void *exit_value) +void tls_destruct(void) { -#ifdef CONFIG_PTHREAD_CLEANUP - pthread_cleanup_popall(); -#endif + 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(); - nx_pthread_exit(exit_value); - PANIC(); + 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 14f1225..35eee89 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/libs/libc/pthread/pthread_exit.c b/sched/group/group_tlsgetdtor.c similarity index 65% copy from libs/libc/pthread/pthread_exit.c copy to sched/group/group_tlsgetdtor.c index ce1324c..2aa4145 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/sched/group/group_tlsgetdtor.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/pthread/pthread_exit.c + * 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 @@ -24,37 +24,51 @@ #include <nuttx/config.h> -#include <debug.h> -#include <sched.h> +#include <stdint.h> +#include <assert.h> -#include <nuttx/pthread.h> +#include <nuttx/arch.h> +#include <nuttx/tls.h> +#include <arch/tls.h> + +#include "sched/sched.h" +#include "group/group.h" + +#if CONFIG_TLS_NELEM > 0 /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: pthread_exit + * Name: tls_get_dtor * * Description: - * Terminate execution of a thread started with pthread_create. + * Get the TLS element destructor associated with the 'tlsindex' to 'destr' * * Input Parameters: - * exit_value - The pointer of the pthread_exit parameter + * tlsindex - Index of TLS data destructor to get * * Returned Value: - * None - * - * Assumptions: + * A non-null destruct function pointer. * ****************************************************************************/ -void pthread_exit(FAR void *exit_value) +tls_dtor_t tls_get_dtor(int tlsindex) { -#ifdef CONFIG_PTHREAD_CLEANUP - pthread_cleanup_popall(); -#endif + FAR struct tcb_s *rtcb = this_task(); + FAR struct task_group_s *group = rtcb->group; + irqstate_t flags; + tls_dtor_t destr; - nx_pthread_exit(exit_value); - PANIC(); + 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/libs/libc/pthread/pthread_exit.c b/sched/group/group_tlsgetset.c similarity index 70% copy from libs/libc/pthread/pthread_exit.c copy to sched/group/group_tlsgetset.c index ce1324c..55c5dac 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/sched/group/group_tlsgetset.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/pthread/pthread_exit.c + * 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 @@ -24,37 +24,49 @@ #include <nuttx/config.h> -#include <debug.h> -#include <sched.h> +#include <stdint.h> +#include <assert.h> -#include <nuttx/pthread.h> +#include <nuttx/arch.h> +#include <nuttx/tls.h> +#include <arch/tls.h> + +#include "sched/sched.h" +#include "group/group.h" + +#if CONFIG_TLS_NELEM > 0 /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: pthread_exit + * Name: tls_get_set * * Description: - * Terminate execution of a thread started with pthread_create. + * Get the set map of TLE element index. * * Input Parameters: - * exit_value - The pointer of the pthread_exit parameter * * Returned Value: - * None - * - * Assumptions: + * TLS element index set map. * ****************************************************************************/ -void pthread_exit(FAR void *exit_value) +tls_ndxset_t tls_get_set(void) { -#ifdef CONFIG_PTHREAD_CLEANUP - pthread_cleanup_popall(); -#endif + FAR struct tcb_s *rtcb = this_task(); + FAR struct task_group_s *group = rtcb->group; + irqstate_t flags; + tls_ndxset_t tlsset; - nx_pthread_exit(exit_value); - PANIC(); + 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/libs/libc/pthread/pthread_exit.c b/sched/group/group_tlssetdtor.c similarity index 62% copy from libs/libc/pthread/pthread_exit.c copy to sched/group/group_tlssetdtor.c index ce1324c..5e4447c 100644 --- a/libs/libc/pthread/pthread_exit.c +++ b/sched/group/group_tlssetdtor.c @@ -1,5 +1,5 @@ /**************************************************************************** - * libs/libc/pthread/pthread_exit.c + * 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 @@ -24,37 +24,54 @@ #include <nuttx/config.h> -#include <debug.h> -#include <sched.h> +#include <stdint.h> +#include <assert.h> -#include <nuttx/pthread.h> +#include <nuttx/arch.h> +#include <nuttx/tls.h> +#include <arch/tls.h> + +#include "sched/sched.h" +#include "group/group.h" + +#if CONFIG_TLS_NELEM > 0 /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** - * Name: pthread_exit + * Name: tls_set_dtor * * Description: - * Terminate execution of a thread started with pthread_create. + * Set the TLS element destructor associated with the 'tlsindex' to 'destr' * * Input Parameters: - * exit_value - The pointer of the pthread_exit parameter + * tlsindex - Index of TLS data destructor to set + * destr - The destr of TLS data element * * Returned Value: - * None + * Zero is returned on success, a negated errno value is return on + * failure: * - * Assumptions: + * EINVAL - tlsindex is not in range. * ****************************************************************************/ -void pthread_exit(FAR void *exit_value) +int tls_set_dtor(int tlsindex, tls_dtor_t destr) { -#ifdef CONFIG_PTHREAD_CLEANUP - pthread_cleanup_popall(); -#endif + 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); - nx_pthread_exit(exit_value); - PANIC(); + 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 4d55560..6805849 100644 --- a/sched/pthread/pthread_exit.c +++ b/sched/pthread/pthread_exit.c @@ -34,6 +34,7 @@ #include <nuttx/arch.h> #include <nuttx/signal.h> +#include <nuttx/tls.h> #include "sched/sched.h" #include "task/task.h" diff --git a/syscall/syscall.csv b/syscall/syscall.csv index c39442f..3f180b0 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 *"
