You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2021/05/22 04:47:10 UTC

[incubator-nuttx] 07/09: pthread: Implement destructor of pthread_key_create

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 <hu...@xiaomi.com>
AuthorDate: Thu Apr 22 10:41:50 2021 +0800

    pthread: Implement destructor of pthread_key_create
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
    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 *"