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:05 UTC

[incubator-nuttx] 02/09: libc: Move pthread_exit to userspace

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 54eef9f639476ced38a46559fad218811bd9e3c9
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Thu Apr 29 17:56:28 2021 +0800

    libc: Move pthread_exit to userspace
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 include/nuttx/pthread.h          | 35 +++++++++++++++++++
 include/sys/syscall_lookup.h     |  3 +-
 libs/libc/pthread/Make.defs      |  2 +-
 libs/libc/pthread/pthread_exit.c | 72 ++++++++++++++++++++++++++++++++++++++++
 sched/pthread/pthread_cleanup.c  | 53 +++++++++++++++++++++++++++++
 sched/pthread/pthread_exit.c     |  8 +----
 syscall/syscall.csv              |  3 +-
 7 files changed, 166 insertions(+), 10 deletions(-)

diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h
index 8dc21d9..477cf2c 100644
--- a/include/nuttx/pthread.h
+++ b/include/nuttx/pthread.h
@@ -149,6 +149,41 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
                       FAR const pthread_attr_t *attr,
                       pthread_startroutine_t entry, pthread_addr_t arg);
 
+/****************************************************************************
+ * Name: nx_pthread_exit
+ *
+ * Description:
+ *   Terminate execution of a thread started with pthread_create.
+ *
+ * Input Parameters:
+ *   exit_valie
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+void nx_pthread_exit(FAR void *exit_value) noreturn_function;
+
+/****************************************************************************
+ * Name: pthread_cleanup_poplist
+ *
+ * Description:
+ *   The pthread_cleanup_poplist() is function that will pop all clean-up
+ *   functions.  This function is only called from within the pthread_exit()
+ *
+ * Input Parameters:
+ *   cleanup - The array of struct pthread_cleanup_s to fetch callbacks
+ *
+ * Returned Value:
+ *   The index to the next available entry at the top of the stack
+ *
+ ****************************************************************************/
+
+int pthread_cleanup_poplist(FAR struct pthread_cleanup_s *cleanup);
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index c3f3dea..d59467a 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -307,7 +307,7 @@ SYSCALL_LOOKUP(telldir,                    1)
   SYSCALL_LOOKUP(pthread_cond_wait,        2)
   SYSCALL_LOOKUP(nx_pthread_create,        5)
   SYSCALL_LOOKUP(pthread_detach,           1)
-  SYSCALL_LOOKUP(pthread_exit,             1)
+  SYSCALL_LOOKUP(nx_pthread_exit,          1)
   SYSCALL_LOOKUP(pthread_getschedparam,    3)
   SYSCALL_LOOKUP(pthread_join,             2)
   SYSCALL_LOOKUP(pthread_mutex_destroy,    1)
@@ -330,6 +330,7 @@ SYSCALL_LOOKUP(telldir,                    1)
 #ifdef CONFIG_PTHREAD_CLEANUP
   SYSCALL_LOOKUP(pthread_cleanup_push,     2)
   SYSCALL_LOOKUP(pthread_cleanup_pop,      1)
+  SYSCALL_LOOKUP(pthread_cleanup_poplist,  1)
 #endif
 #endif
 
diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs
index 21497bf..bbdb75b 100644
--- a/libs/libc/pthread/Make.defs
+++ b/libs/libc/pthread/Make.defs
@@ -40,7 +40,7 @@ CSRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
 CSRCS += pthread_condattr_init.c pthread_condattr_destroy.c
 CSRCS += pthread_condattr_setclock.c pthread_condattr_getclock.c
 CSRCS += pthread_condinit.c pthread_conddestroy.c pthread_condtimedwait.c
-CSRCS += pthread_create.c
+CSRCS += pthread_create.c pthread_exit.c
 CSRCS += pthread_get_stackaddr_np.c pthread_get_stacksize_np.c
 CSRCS += pthread_mutexattr_init.c pthread_mutexattr_destroy.c
 CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c
diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c
new file mode 100644
index 0000000..71271d9
--- /dev/null
+++ b/libs/libc/pthread/pthread_exit.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * libs/libc/pthread/pthread_exit.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 <nuttx/config.h>
+
+#include <debug.h>
+#include <sched.h>
+
+#include <nuttx/pthread.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_exit
+ *
+ * Description:
+ *   Terminate execution of a thread started with pthread_create.
+ *
+ * Input Parameters:
+ *   exit_valie
+ *
+ * Returned Value:
+ *   None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+void pthread_exit(FAR void *exit_value)
+{
+#ifdef CONFIG_PTHREAD_CLEANUP
+  int cnt;
+  struct pthread_cleanup_s cleanup[CONFIG_PTHREAD_CLEANUP_STACKSIZE];
+  cnt = pthread_cleanup_poplist(cleanup);
+
+  sched_lock();
+  while (cnt-- > 0)
+    {
+      struct pthread_cleanup_s cp = cleanup[cnt];
+      if (cp.pc_cleaner)
+        cp.pc_cleaner(cp.pc_arg);
+    }
+
+  sched_unlock();
+#endif
+
+  nx_pthread_exit(exit_value);
+  PANIC();
+}
diff --git a/sched/pthread/pthread_cleanup.c b/sched/pthread/pthread_cleanup.c
index e735b15..8c5dbaf 100644
--- a/sched/pthread/pthread_cleanup.c
+++ b/sched/pthread/pthread_cleanup.c
@@ -208,4 +208,57 @@ void pthread_cleanup_popall(FAR struct tcb_s *tcb)
     }
 }
 
+/****************************************************************************
+ * Name: pthread_cleanup_poplist
+ *
+ * Description:
+ *   The pthread_cleanup_poplist() is function that will pop all clean-up
+ *   functions.  This function is only called from within the pthread_exit()
+ *
+ * Input Parameters:
+ *   cleanup - The array of struct pthread_cleanup_s to fetch callbacks
+ *
+ * Returned Value:
+ *   The index to the next available entry at the top of the stack
+ *
+ ****************************************************************************/
+
+int pthread_cleanup_poplist(FAR struct pthread_cleanup_s *cleanup)
+{
+  uint8_t tos = 0;
+  uint8_t ndx = 0;
+  FAR struct tcb_s *tcb = this_task();
+
+  DEBUGASSERT(cleanup != NULL);
+  DEBUGASSERT(tcb != NULL);
+  DEBUGASSERT(tcb->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
+
+  tos = tcb->tos;
+
+  /* Kernel threads do not support pthread APIs */
+
+  if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
+    {
+      /* Pop cleanup routine list
+       *
+       * sched_lock() should provide sufficient protection.  We only need to
+       * have this TCB stationary; the pthread cleanup stack should never be
+       * modified by interrupt level logic.
+       */
+
+      sched_lock();
+      while (tcb->tos > 0)
+        {
+          ndx = tcb->tos - 1;
+          DEBUGASSERT(ndx >= 0 && ndx < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
+          cleanup[ndx] = tcb->stack[ndx];
+          tcb->tos = ndx;
+        }
+
+      sched_unlock();
+    }
+
+  return tos;
+}
+
 #endif /* CONFIG_PTHREAD_CLEANUP */
diff --git a/sched/pthread/pthread_exit.c b/sched/pthread/pthread_exit.c
index bc6086f..a7704ab 100644
--- a/sched/pthread/pthread_exit.c
+++ b/sched/pthread/pthread_exit.c
@@ -59,7 +59,7 @@
  *
  ****************************************************************************/
 
-void pthread_exit(FAR void *exit_value)
+void nx_pthread_exit(FAR void *exit_value)
 {
   FAR struct tcb_s *tcb = this_task();
   sigset_t set = ALL_SIGNAL_SET;
@@ -87,12 +87,6 @@ void pthread_exit(FAR void *exit_value)
   tcb->cpcount = 0;
 #endif
 
-#ifdef CONFIG_PTHREAD_CLEANUP
-  /* Perform any stack pthread clean-up callbacks */
-
-  pthread_cleanup_popall(tcb);
-#endif
-
   /* Complete pending join operations */
 
   status = pthread_completejoin(getpid(), exit_value);
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index a9c4658..e88cf9e 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -84,13 +84,14 @@
 "pselect","sys/select.h","","int","int","FAR fd_set *","FAR fd_set *","FAR fd_set *","FAR const struct timespec *","FAR const sigset_t *"
 "pthread_cancel","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
 "pthread_cleanup_pop","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","int"
+"pthread_cleanup_poplist","nuttx/pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","int","struct pthread_cleanup_s *"
 "pthread_cleanup_push","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","pthread_cleanup_t","FAR void *"
 "pthread_cond_broadcast","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *"
 "pthread_cond_clockwait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *","clockid_t","FAR const struct timespec *"
 "pthread_cond_signal","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *"
 "pthread_cond_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *"
 "pthread_detach","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
-"pthread_exit","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","noreturn","pthread_addr_t"
+"nx_pthread_exit","nuttx/pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","noreturn","pthread_addr_t"
 "pthread_getaffinity_np","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SMP)","int","pthread_t","size_t","FAR cpu_set_t*"
 "pthread_getschedparam","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR int *","FAR struct sched_param *"
 "pthread_join","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR pthread_addr_t *"