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

[incubator-nuttx] branch master updated (a876f02 -> a294153)

This is an automated email from the ASF dual-hosted git repository.

gnutt pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git.


    from a876f02  net/tcp: recounter the ack counter during obtain newdata
     new bb9b58b  libc: Move pthread_create to user space
     new 54eef9f  libc: Move pthread_exit to userspace
     new 103925b  boards/risc-v/c906: Remove unneeded pthread_start
     new f1a92e9  libc: Move pthread_cleanup to user space
     new 81a01d0  libc/pthread: Fix comment and document issue
     new f4a0b7a  libc: Call pthread_exit in user-space by up_pthread_exit
     new d374d55  pthread: Implement destructor of pthread_key_create
     new 9dbeaa3  nuttx/sched.h: Fix nxstyle
     new a294153  pthread: Avoid recursive pthread_exit call

The 9 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/a1x/Make.defs                         |   1 +
 arch/arm/src/am335x/Make.defs                      |   1 +
 arch/arm/src/armv6-m/arm_svcall.c                  |  51 ++-
 arch/arm/src/armv6-m/svcall.h                      |  27 +-
 arch/arm/src/armv7-a/arm_syscall.c                 |  45 +-
 arch/arm/src/armv7-a/svcall.h                      |  31 +-
 arch/arm/src/armv7-m/arm_svcall.c                  |  51 ++-
 arch/arm/src/armv7-m/svcall.h                      |  33 +-
 arch/arm/src/armv7-r/arm_syscall.c                 |  45 +-
 arch/arm/src/armv7-r/svcall.h                      |  20 +-
 arch/arm/src/armv8-m/arm_svcall.c                  |  51 ++-
 arch/arm/src/armv8-m/svcall.h                      |  20 +-
 .../{arm_pthread_start.c => arm_pthread_exit.c}    |  28 +-
 arch/arm/src/common/arm_pthread_start.c            |  11 +-
 arch/arm/src/cxd56xx/Make.defs                     |   1 +
 arch/arm/src/efm32/Make.defs                       |   1 +
 arch/arm/src/eoss3/Make.defs                       |   1 +
 arch/arm/src/imx6/Make.defs                        |   1 +
 arch/arm/src/imxrt/Make.defs                       |   1 +
 arch/arm/src/kinetis/Make.defs                     |   1 +
 arch/arm/src/kl/Make.defs                          |   1 +
 arch/arm/src/lc823450/Make.defs                    |   1 +
 arch/arm/src/lpc17xx_40xx/Make.defs                |   1 +
 arch/arm/src/lpc43xx/Make.defs                     |   1 +
 arch/arm/src/lpc54xx/Make.defs                     |   1 +
 arch/arm/src/max326xx/Make.defs                    |   1 +
 arch/arm/src/nrf52/Make.defs                       |   1 +
 arch/arm/src/nuc1xx/Make.defs                      |   1 +
 arch/arm/src/rp2040/Make.defs                      |   1 +
 arch/arm/src/s32k1xx/Make.defs                     |   1 +
 arch/arm/src/sam34/Make.defs                       |   1 +
 arch/arm/src/sama5/Make.defs                       |   1 +
 arch/arm/src/samd2l2/Make.defs                     |   1 +
 arch/arm/src/samd5e5/Make.defs                     |   1 +
 arch/arm/src/samv7/Make.defs                       |   1 +
 arch/arm/src/stm32/Make.defs                       |   2 +-
 arch/arm/src/stm32f0l0g0/Make.defs                 |   1 +
 arch/arm/src/stm32f7/Make.defs                     |   1 +
 arch/arm/src/stm32h7/Make.defs                     |   1 +
 arch/arm/src/stm32l4/Make.defs                     |   1 +
 arch/arm/src/stm32l5/Make.defs                     |   1 +
 arch/arm/src/tiva/Make.defs                        |   1 +
 arch/arm/src/tms570/Make.defs                      |   1 +
 arch/arm/src/xmc4/Make.defs                        |   1 +
 arch/or1k/src/common/up_pthread_start.c            |   8 +-
 arch/risc-v/src/c906/Make.defs                     |   1 +
 .../risc-v/src/common/riscv_pthread_exit.c         |  44 +-
 arch/risc-v/src/common/riscv_pthread_start.c       |  11 +-
 arch/risc-v/src/k210/Make.defs                     |   3 +-
 arch/risc-v/src/rv64gc/riscv_swint.c               |  55 ++-
 arch/risc-v/src/rv64gc/svcall.h                    |  34 +-
 .../arm/imxrt/imxrt1050-evk/configs/knsh/defconfig |   2 +-
 .../imxrt/imxrt1050-evk/kernel/imxrt_userspace.c   |   3 -
 .../arm/imxrt/imxrt1060-evk/configs/knsh/defconfig |   2 +-
 .../imxrt/imxrt1060-evk/kernel/imxrt_userspace.c   |   3 -
 .../arm/imxrt/imxrt1064-evk/configs/knsh/defconfig |   2 +-
 .../lc823450/lc823450-xgevk/configs/knsh/defconfig |   2 +-
 .../lc823450-xgevk/configs/kostest/defconfig       |   2 +-
 .../lc823450-xgevk/configs/krndis/defconfig        |   2 +-
 .../lc823450-xgevk/kernel/lc823450_userspace.c     |   3 -
 .../lpc4088-devkit/configs/knsh/defconfig          |   2 +-
 .../lpc4088-devkit/kernel/lpc17_40_userspace.c     |   3 -
 .../lpc4088-quickstart/configs/knsh/defconfig      |   2 +-
 .../lpc4088-quickstart/kernel/lpc17_40_userspace.c |   3 -
 .../lpc17xx_40xx/open1788/configs/knsh/defconfig   |   2 +-
 .../open1788/configs/knxterm/defconfig             |   2 +-
 .../open1788/kernel/lpc17_40_userspace.c           |   3 -
 .../lpc17xx_40xx/pnev5180b/configs/knsh/defconfig  |   2 +-
 .../pnev5180b/kernel/lpc17_40_userspace.c          |   3 -
 .../lpc43xx/bambino-200e/configs/knsh/defconfig    |   2 +-
 .../lpc43xx/bambino-200e/kernel/lpc43_userspace.c  |   3 -
 boards/arm/sam34/sam3u-ek/configs/knsh/defconfig   |   2 +-
 boards/arm/sam34/sam3u-ek/kernel/sam_userspace.c   |   3 -
 boards/arm/sama5/sama5d4-ek/configs/knsh/defconfig |   2 +-
 .../samv7/same70-xplained/kernel/sam_userspace.c   |   3 -
 .../arm/samv7/samv71-xult/configs/knsh/defconfig   |   2 +-
 .../arm/samv7/samv71-xult/kernel/sam_userspace.c   |   3 -
 .../stm32/clicker2-stm32/configs/knsh/defconfig    |   2 +-
 .../stm32/clicker2-stm32/kernel/stm32_userspace.c  |   3 -
 .../stm32/mikroe-stm32f4/configs/kostest/defconfig |   2 +-
 .../stm32/mikroe-stm32f4/kernel/stm32_userspace.c  |   3 -
 .../stm32/olimex-stm32-p407/configs/kelf/defconfig |   2 +-
 .../olimex-stm32-p407/configs/kmodule/defconfig    |   2 +-
 .../stm32/olimex-stm32-p407/configs/knsh/defconfig |   2 +-
 .../olimex-stm32-p407/kernel/stm32_userspace.c     |   3 -
 .../arm/stm32/omnibusf4/kernel/stm32_userspace.c   |   3 -
 .../stm32/stm3240g-eval/configs/knxwm/defconfig    |   2 +-
 .../stm32/stm3240g-eval/kernel/stm32_userspace.c   |   3 -
 .../stm32f4discovery/configs/kostest/defconfig     |   2 +-
 .../stm32f4discovery/kernel/stm32_userspace.c      |   3 -
 .../stm32f746g-disco/kernel/stm32_userspace.c      |   3 -
 .../stm32f769i-disco/kernel/stm32_userspace.c      |   3 -
 .../stm32h7/nucleo-h743zi/kernel/stm32_userspace.c |   3 -
 .../stm32h747i-disco/kernel/stm32_userspace.c      |   3 -
 .../stm32l476vg-disco/configs/knsh/defconfig       |   2 +-
 .../stm32l476vg-disco/kernel/stm32l4_userspace.c   |   3 -
 .../stm32l4r9ai-disco/configs/knsh/defconfig       |   2 +-
 .../stm32l4r9ai-disco/kernel/stm32l4_userspace.c   |   3 -
 .../lm3s6965-ek/configs/qemu-protected/defconfig   |   2 +-
 boards/arm/tiva/lm3s6965-ek/kernel/lm_userspace.c  |   3 -
 .../risc-v/c906/smartl-c906/configs/knsh/defconfig |   2 +-
 .../c906/smartl-c906/kernel/c906_userspace.c       |   3 -
 boards/risc-v/k210/maix-bit/configs/knsh/defconfig |   2 +-
 .../k210/maix-bit/configs/knsh_smp/defconfig       |   2 +-
 .../risc-v/k210/maix-bit/configs/kostest/defconfig |   2 +-
 .../risc-v/k210/maix-bit/kernel/k210_userspace.c   |   3 -
 include/nuttx/arch.h                               |  29 +-
 include/nuttx/pthread.h                            |  70 +++-
 include/nuttx/sched.h                              | 457 +++++++++++----------
 include/nuttx/tls.h                                |  87 ++++
 include/nuttx/userspace.h                          |  26 +-
 include/pthread.h                                  |   4 +
 include/sys/syscall_lookup.h                       |  11 +-
 libs/libc/pthread/Make.defs                        |  14 +-
 {sched => libs/libc}/pthread/pthread_cleanup.c     |  76 ++--
 .../libc/pthread/pthread_create.c                  |  75 ++--
 .../{pthread_condattr_init.c => pthread_exit.c}    |  37 +-
 libs/libc/pthread/pthread_keycreate.c              |   6 +-
 libs/libc/pthread/pthread_startup.c                |  93 -----
 libs/libc/tls/Make.defs                            |   2 +-
 libs/libc/tls/{tls_setvalue.c => tls_destruct.c}   |  49 +--
 sched/group/Make.defs                              |   1 +
 .../group/group_tlsgetdtor.c                       |  41 +-
 .../sched_getstreams.c => group/group_tlsgetset.c} |  41 +-
 .../group/group_tlssetdtor.c                       |  36 +-
 sched/pthread/Make.defs                            |   4 -
 sched/pthread/pthread.h                            |   4 -
 sched/pthread/pthread_cancel.c                     |  22 +-
 sched/pthread/pthread_create.c                     |  71 ++--
 sched/pthread/pthread_exit.c                       |  11 +-
 sched/signal/sig_default.c                         |   9 +-
 sched/task/exit.c                                  |   6 -
 sched/task/task_cancelpt.c                         |  15 +
 sched/task/task_setcancelstate.c                   |   7 +
 sched/task/task_setcanceltype.c                    |   7 +
 syscall/syscall.csv                                |   9 +-
 136 files changed, 1136 insertions(+), 922 deletions(-)
 copy arch/arm/src/common/{arm_pthread_start.c => arm_pthread_exit.c} (68%)
 copy libs/libc/pthread/pthread_condattr_setclock.c => arch/risc-v/src/common/riscv_pthread_exit.c (68%)
 rename {sched => libs/libc}/pthread/pthread_cleanup.c (77%)
 copy sched/group/group_continue.c => libs/libc/pthread/pthread_create.c (60%)
 copy libs/libc/pthread/{pthread_condattr_init.c => pthread_exit.c} (78%)
 delete mode 100644 libs/libc/pthread/pthread_startup.c
 copy libs/libc/tls/{tls_setvalue.c => tls_destruct.c} (68%)
 copy libs/libc/tls/tls_setvalue.c => sched/group/group_tlsgetdtor.c (70%)
 copy sched/{sched/sched_getstreams.c => group/group_tlsgetset.c} (75%)
 copy libs/libc/tls/tls_setvalue.c => sched/group/group_tlssetdtor.c (75%)

[incubator-nuttx] 03/09: boards/risc-v/c906: Remove unneeded pthread_start

Posted by gn...@apache.org.
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 103925b2b7eda8e023cbd74bad67dfba757b69a4
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Fri Apr 30 12:42:02 2021 +0800

    boards/risc-v/c906: Remove unneeded pthread_start
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 boards/risc-v/c906/smartl-c906/kernel/c906_userspace.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/boards/risc-v/c906/smartl-c906/kernel/c906_userspace.c b/boards/risc-v/c906/smartl-c906/kernel/c906_userspace.c
index 1f5a2f3..9f24ab1 100644
--- a/boards/risc-v/c906/smartl-c906/kernel/c906_userspace.c
+++ b/boards/risc-v/c906/smartl-c906/kernel/c906_userspace.c
@@ -99,9 +99,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 

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

Posted by gn...@apache.org.
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 *"

[incubator-nuttx] 09/09: pthread: Avoid recursive pthread_exit call

Posted by gn...@apache.org.
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 a2941532bdacba9b8e69dfae4b365aff33f0503a
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Mon May 17 17:31:13 2021 +0800

    pthread: Avoid recursive pthread_exit call
    
    pthread_exit will be called recursive when pthread_cancel
    or other cleanup operation with syscalls that support
    cancellation, to avoid this by mark current tcb flag as
    TCB_FLAG_CANCEL_DOING instead of TCB_FLAG_CANCEL_PENDING.
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 sched/pthread/pthread_cancel.c   |  3 +--
 sched/signal/sig_default.c       |  3 +--
 sched/task/task_cancelpt.c       |  6 ++----
 sched/task/task_setcancelstate.c |  3 +--
 sched/task/task_setcanceltype.c  | 11 +++++------
 5 files changed, 10 insertions(+), 16 deletions(-)

diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c
index e4088ba..adc2b7e 100644
--- a/sched/pthread/pthread_cancel.c
+++ b/sched/pthread/pthread_cancel.c
@@ -84,10 +84,9 @@ int pthread_cancel(pthread_t thread)
 
   if (tcb == this_task())
     {
-#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
       tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
       tcb->flags |= TCB_FLAG_CANCEL_DOING;
-
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
       up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
                       PTHREAD_CANCELED);
 #else
diff --git a/sched/signal/sig_default.c b/sched/signal/sig_default.c
index 7e87089..0078f47 100644
--- a/sched/signal/sig_default.c
+++ b/sched/signal/sig_default.c
@@ -224,10 +224,9 @@ static void nxsig_abnormal_termination(int signo)
        * REVISIT:  This will not work if HAVE_GROUP_MEMBERS is not set.
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
       rtcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
       rtcb->flags |= TCB_FLAG_CANCEL_DOING;
-
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
       up_pthread_exit(((FAR struct pthread_tcb_s *)rtcb)->exit,
                                   PTHREAD_CANCELED);
 #else
diff --git a/sched/task/task_cancelpt.c b/sched/task/task_cancelpt.c
index 659e5db..228e90e 100644
--- a/sched/task/task_cancelpt.c
+++ b/sched/task/task_cancelpt.c
@@ -140,10 +140,9 @@ bool enter_cancellation_point(void)
               if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
                   TCB_FLAG_TTYPE_PTHREAD)
                 {
-#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
                   tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
                   tcb->flags |= TCB_FLAG_CANCEL_DOING;
-
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
                   up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
                                   PTHREAD_CANCELED);
 #else
@@ -235,10 +234,9 @@ void leave_cancellation_point(void)
               if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
                   TCB_FLAG_TTYPE_PTHREAD)
                 {
-#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
                   tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
                   tcb->flags |= TCB_FLAG_CANCEL_DOING;
-
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
                   up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
                                   PTHREAD_CANCELED);
 #else
diff --git a/sched/task/task_setcancelstate.c b/sched/task/task_setcancelstate.c
index 6b61632..63f3ef3 100644
--- a/sched/task/task_setcancelstate.c
+++ b/sched/task/task_setcancelstate.c
@@ -112,10 +112,9 @@ int task_setcancelstate(int state, FAR int *oldstate)
               if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
                   TCB_FLAG_TTYPE_PTHREAD)
                 {
-#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
                   tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
                   tcb->flags |= TCB_FLAG_CANCEL_DOING;
-
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
                   up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
                                   PTHREAD_CANCELED);
 #else
diff --git a/sched/task/task_setcanceltype.c b/sched/task/task_setcanceltype.c
index d57cc64..f33aeb1 100644
--- a/sched/task/task_setcanceltype.c
+++ b/sched/task/task_setcanceltype.c
@@ -100,14 +100,13 @@ int task_setcanceltype(int type, FAR int *oldtype)
 #ifndef CONFIG_DISABLE_PTHREAD
           if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
             {
+              tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+              tcb->flags |= TCB_FLAG_CANCEL_DOING;
 #if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
-                  tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
-                  tcb->flags |= TCB_FLAG_CANCEL_DOING;
-
-                  up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
-                                  PTHREAD_CANCELED);
+              up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
+                               PTHREAD_CANCELED);
 #else
-                  pthread_exit(PTHREAD_CANCELED);
+              pthread_exit(PTHREAD_CANCELED);
 #endif
             }
           else

[incubator-nuttx] 08/09: nuttx/sched.h: Fix nxstyle

Posted by gn...@apache.org.
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 9dbeaa3b1f0c388987f29d9967ad2c3fa134fd05
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Fri May 14 17:47:48 2021 +0800

    nuttx/sched.h: Fix nxstyle
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 include/nuttx/sched.h | 431 +++++++++++++++++++++++++-------------------------
 1 file changed, 219 insertions(+), 212 deletions(-)

diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index f425e47..5e841c1 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -1,4 +1,4 @@
-/********************************************************************************
+/****************************************************************************
  * include/nuttx/sched.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -16,14 +16,14 @@
  * License for the specific language governing permissions and limitations
  * under the License.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifndef __INCLUDE_NUTTX_SCHED_H
 #define __INCLUDE_NUTTX_SCHED_H
 
-/********************************************************************************
+/****************************************************************************
  * Included Files
- ********************************************************************************/
+ ****************************************************************************/
 
 #include <nuttx/config.h>
 
@@ -44,11 +44,11 @@
 
 #include <arch/arch.h>
 
-/********************************************************************************
+/****************************************************************************
  * Pre-processor Definitions
- ********************************************************************************/
+ ****************************************************************************/
 
-/* Configuration ****************************************************************/
+/* Configuration ************************************************************/
 
 /* Task groups currently only supported for retention of child status */
 
@@ -74,7 +74,7 @@
 #  define CONFIG_SCHED_SPORADIC_MAXREPL 3
 #endif
 
-/* Task Management Definitions **************************************************/
+/* Task Management Definitions **********************************************/
 
 /* Special task IDS.  Any negative PID is invalid. */
 
@@ -182,18 +182,18 @@
 #  error "CONFIG_SCHED_EXIT_MAX < 1"
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Public Type Definitions
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifndef __ASSEMBLY__
 
-/* General Task Management Types ************************************************/
+/* General Task Management Types ********************************************/
 
 /* This is the type of the task_state field of the TCB. NOTE: the order and
- * content of this enumeration is critical since there are some OS tables indexed
- * by these values.  The range of values is assumed to fit into a uint8_t in
- * struct tcb_s.
+ * content of this enumeration is critical since there are some OS tables
+ * indexed by these values.
+ * The range of values is assumed to fit into a uint8_t in struct tcb_s.
  */
 
 enum tstate_e
@@ -258,8 +258,8 @@ typedef union entry_u entry_t;
 typedef CODE void (*starthook_t)(FAR void *arg);
 #endif
 
-/* These are the types of the functions that are executed with exit() is called
- * (if registered via atexit() on on_exit()).
+/* These are the types of the functions that are executed with exit() is
+ * called (if registered via atexit() on on_exit()).
  */
 
 #ifdef CONFIG_SCHED_ATEXIT
@@ -270,7 +270,7 @@ typedef CODE void (*atexitfunc_t)(void);
 typedef CODE void (*onexitfunc_t)(int exitcode, FAR void *arg);
 #endif
 
-/* struct sporadic_s ************************************************************/
+/* struct sporadic_s ********************************************************/
 
 #ifdef CONFIG_SCHED_SPORADIC
 
@@ -288,10 +288,10 @@ struct replenishment_s
 };
 
 /* This structure is an allocated "plug-in" to the main TCB structure.  It is
- * allocated when the sporadic scheduling policy is assigned to a thread.  Thus,
- * in the context of numerous threads of varying policies, there the overhead
- * from this significant allocation is only borne by the threads with the
- * sporadic scheduling policy.
+ * allocated when the sporadic scheduling policy is assigned to a thread.
+ * Thus, in the context of numerous threads of varying policies, there the
+ * overhead from this significant allocation is only borne by the threads
+ * with the sporadic scheduling policy.
  */
 
 struct sporadic_s
@@ -316,10 +316,11 @@ struct sporadic_s
 
 #endif /* CONFIG_SCHED_SPORADIC */
 
-/* struct child_status_s ********************************************************/
+/* struct child_status_s ****************************************************/
 
-/* This structure is used to maintain information about child tasks.  pthreads
- * work differently, they have join information.  This is only for child tasks.
+/* This structure is used to maintain information about child tasks.
+ * pthreads work differently, they have join information.
+ * This is only for child tasks.
  */
 
 #ifdef CONFIG_SCHED_CHILD_STATUS
@@ -333,7 +334,7 @@ struct child_status_s
 };
 #endif
 
-/* struct pthread_cleanup_s *****************************************************/
+/* struct pthread_cleanup_s *************************************************/
 
 /* This structure describes one element of the pthread cleanup stack */
 
@@ -345,10 +346,10 @@ struct pthread_cleanup_s
 };
 #endif
 
-/* type tls_ndxset_t & tls_dtor_t **********************************************/
+/* type tls_ndxset_t & tls_dtor_t *******************************************/
 
-/* Smallest addressable type that can hold the entire configured number of TLS
- * data indexes.
+/* Smallest addressable type that can hold the entire configured number of
+ * TLS data indexes.
  */
 
 #if CONFIG_TLS_NELEM > 0
@@ -366,11 +367,11 @@ typedef CODE void (*tls_dtor_t)(FAR void *);
 
 #endif
 
-/* struct dspace_s **************************************************************/
+/* struct dspace_s **********************************************************/
 
-/* This structure describes a reference counted D-Space region.  This must be a
- * separately allocated "break-away" structure that can be owned by a task and
- * any pthreads created by the task.
+/* This structure describes a reference counted D-Space region.
+ * This must be a separately allocated "break-away" structure that
+ * can be owned by a task and any pthreads created by the task.
  */
 
 #ifdef CONFIG_PIC
@@ -385,15 +386,15 @@ struct dspace_s
   uint16_t crefs;
 
   /* This is the allocated D-Space memory region.  This may be a physical
-   * address allocated with kmm_malloc(), or it may be virtual address associated
-   * with an address environment (if CONFIG_ARCH_ADDRENV=y).
+   * address allocated with kmm_malloc(), or it may be virtual address
+   * associated with an address environment (if CONFIG_ARCH_ADDRENV=y).
    */
 
   FAR uint8_t *region;
 };
 #endif
 
-/* struct stackinfo_s ***********************************************************/
+/* struct stackinfo_s *******************************************************/
 
 /* Used to report stack information */
 
@@ -409,7 +410,7 @@ struct stackinfo_s
                                          /* from the stack.                     */
 };
 
-/* struct exitinfo_s ************************************************************/
+/* struct exitinfo_s ********************************************************/
 
 struct exitinfo_s
 {
@@ -427,15 +428,15 @@ struct exitinfo_s
 #endif
 };
 
-/* struct task_group_s **********************************************************/
+/* struct task_group_s ******************************************************/
 
 /* All threads created by pthread_create belong in the same task group (along
  * with the thread of the original task).  struct task_group_s is a shared
- * structure referenced by the TCB of each thread that is a member of the task
- * group.
+ * structure referenced by the TCB of each thread that is a member of the
+ * task group.
  *
- * This structure should contain *all* resources shared by tasks and threads that
- * belong to the same task group:
+ * This structure should contain *all* resources shared by tasks and threads
+ * that belong to the same task group:
  *
  *   Child exit status
  *   Environment variables
@@ -445,11 +446,11 @@ struct exitinfo_s
  *   Sockets
  *   Address environments.
  *
- * Each instance of struct task_group_s is reference counted. Each instance is
- * created with a reference count of one.  The reference incremented when each
- * thread joins the group and decremented when each thread exits, leaving the
- * group.  When the reference count decrements to zero, the struct task_group_s
- * is free.
+ * Each instance of struct task_group_s is reference counted. Each instance
+ * is created with a reference count of one.  The reference incremented when
+ * each thread joins the group and decremented when each thread exits,
+ * leaving the group.  When the reference count decrements to zero,
+ * the struct task_group_s is free.
  */
 
 #ifndef CONFIG_DISABLE_PTHREAD
@@ -470,14 +471,14 @@ struct task_group_s
   pid_t tg_ppid;                    /* This is the ID of the parent thread      */
   uint8_t tg_flags;                 /* See GROUP_FLAG_* definitions             */
 
-  /* User identity **************************************************************/
+  /* User identity **********************************************************/
 
 #ifdef CONFIG_SCHED_USER_IDENTITY
   uid_t   tg_uid;                   /* User identity                            */
   gid_t   tg_gid;                   /* User group identity                      */
 #endif
 
-  /* Group membership ***********************************************************/
+  /* Group membership *******************************************************/
 
   uint8_t    tg_nmembers;           /* Number of members in the group           */
 #ifdef HAVE_GROUP_MEMBERS
@@ -485,20 +486,20 @@ struct task_group_s
   FAR pid_t *tg_members;            /* Members of the group                     */
 #endif
 
-  /* [at|on]exit support ********************************************************/
+  /* [at|on]exit support ****************************************************/
 
 #ifdef CONFIG_SCHED_EXIT_MAX
   struct exitinfo_s tg_exit[CONFIG_SCHED_EXIT_MAX];
 #endif
 
 #ifdef CONFIG_BINFMT_LOADABLE
-  /* Loadable module support ****************************************************/
+  /* Loadable module support ************************************************/
 
   FAR struct binary_s *tg_bininfo;  /* Describes resources used by program      */
 #endif
 
 #ifdef CONFIG_SCHED_HAVE_PARENT
-  /* Child exit status **********************************************************/
+  /* Child exit status ******************************************************/
 
 #ifdef CONFIG_SCHED_CHILD_STATUS
   FAR struct child_status_s *tg_children; /* Head of a list of child status     */
@@ -508,34 +509,35 @@ struct task_group_s
 #endif /* CONFIG_SCHED_HAVE_PARENT */
 
 #if defined(CONFIG_SCHED_WAITPID) && !defined(CONFIG_SCHED_HAVE_PARENT)
-  /* waitpid support ************************************************************/
+  /* waitpid support ********************************************************/
 
-  /* Simple mechanism used only when there is no support for SIGCHLD            */
+  /* Simple mechanism used only when there is no support for SIGCHLD        */
 
-  uint8_t tg_nwaiters;              /* Number of waiters                        */
-  uint8_t tg_waitflags;             /* User flags for waitpid behavior          */
-  sem_t tg_exitsem;                 /* Support for waitpid                      */
-  FAR int *tg_statloc;              /* Location to return exit status           */
+  uint8_t tg_nwaiters;              /* Number of waiters                    */
+  uint8_t tg_waitflags;             /* User flags for waitpid behavior      */
+  sem_t tg_exitsem;                 /* Support for waitpid                  */
+  FAR int *tg_statloc;              /* Location to return exit status       */
 #endif
 
 #ifndef CONFIG_DISABLE_PTHREAD
-  /* Pthreads *******************************************************************/
+  /* Pthreads ***************************************************************/
 
-                                    /* Pthread join Info:                       */
+                              /* Pthread join Info:                         */
 
-  sem_t tg_joinsem;                 /*   Mutually exclusive access to join data */
-  FAR struct join_s *tg_joinhead;   /*   Head of a list of join data            */
-  FAR struct join_s *tg_jointail;   /*   Tail of a list of join data            */
+  sem_t tg_joinsem;               /* Mutually exclusive access to join data */
+  FAR struct join_s *tg_joinhead; /* Head of a list of join data            */
+  FAR struct join_s *tg_jointail; /* Tail of a list of join data            */
 #endif
 
-  /* Thread local storage *******************************************************/
+  /* Thread local storage ***************************************************/
 
 #if CONFIG_TLS_NELEM > 0
-  tls_ndxset_t tg_tlsset;                     /* Set of TLS indexes allocated   */
-  tls_dtor_t  tg_tlsdestr[CONFIG_TLS_NELEM]; /* List of TLS destructors        */
+  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 ************************************************/
+  /* POSIX Signal Control Fields ********************************************/
 
   sq_queue_t tg_sigactionq;         /* List of actions for signals              */
   sq_queue_t tg_sigpendingq;        /* List of pending signals                  */
@@ -544,158 +546,159 @@ struct task_group_s
 #endif
 
 #ifndef CONFIG_DISABLE_ENVIRON
-  /* Environment variables ******************************************************/
+  /* Environment variables **************************************************/
 
   size_t     tg_envsize;            /* Size of environment string allocation    */
   FAR char  *tg_envp;               /* Allocated environment strings            */
 #endif
 
 #ifndef CONFIG_DISABLE_POSIX_TIMERS
-  /* Interval timer *************************************************************/
+  /* Interval timer *********************************************************/
 
   timer_t itimer;
 #endif
 
-  /* PIC data space and address environments ************************************/
+  /* PIC data space and address environments ********************************/
 
   /* Logically the PIC data space belongs here (see struct dspace_s).  The
    * current logic needs review:  There are differences in the away that the
    * life of the PIC data is managed.
    */
 
-  /* File descriptors ***********************************************************/
+  /* File descriptors *******************************************************/
 
-  struct filelist tg_filelist;      /* Maps file descriptor to file             */
+  struct filelist tg_filelist;      /* Maps file descriptor to file         */
 
 #ifdef CONFIG_FILE_STREAM
-  /* FILE streams ***************************************************************/
+  /* FILE streams ***********************************************************/
 
   /* In a flat, single-heap build.  The stream list is allocated with this
-   * structure.  But kernel mode with a kernel allocator, it must be separately
-   * allocated using a user-space allocator.
+   * structure.  But kernel mode with a kernel allocator,
+  * it must be separately allocated using a user-space allocator.
    */
 
 #ifdef CONFIG_MM_KERNEL_HEAP
   FAR struct streamlist *tg_streamlist;
 #else
-  struct streamlist tg_streamlist;  /* Holds C buffered I/O info                */
+  struct streamlist tg_streamlist;  /* Holds C buffered I/O info            */
 #endif
 #endif
 
 #ifdef CONFIG_ARCH_ADDRENV
-  /* Address Environment ********************************************************/
+  /* Address Environment ****************************************************/
 
-  group_addrenv_t tg_addrenv;       /* Task group address environment           */
+  group_addrenv_t tg_addrenv;       /* Task group address environment       */
 #endif
 
 #ifdef CONFIG_MM_SHM
-  /* Shared Memory **************************************************************/
+  /* Shared Memory **********************************************************/
 
-  struct group_shm_s tg_shm;        /* Task shared memory logic                 */
+  struct group_shm_s tg_shm;        /* Task shared memory logic             */
 #endif
 };
 
-/* struct tcb_s *****************************************************************/
+/* struct tcb_s *************************************************************/
 
-/* This is the common part of the task control block (TCB).  The TCB is the heart
- * of the NuttX task-control logic.  Each task or thread is represented by a TCB
- * that includes these common definitions.
+/* This is the common part of the task control block (TCB).
+ * The TCB is the heart of the NuttX task-control logic.
+ * Each task or thread is represented by a TCB that includes these common
+ * definitions.
  */
 
 struct tcb_s
 {
-  /* Fields used to support list management *************************************/
+  /* Fields used to support list management *********************************/
 
-  FAR struct tcb_s *flink;               /* Doubly linked list                  */
+  FAR struct tcb_s *flink;               /* Doubly linked list              */
   FAR struct tcb_s *blink;
 
-  /* Task Group *****************************************************************/
+  /* Task Group *************************************************************/
 
-  FAR struct task_group_s *group;        /* Pointer to shared task group data   */
+  FAR struct task_group_s *group;      /* Pointer to shared task group data */
 
-  /* Task Management Fields *****************************************************/
+  /* Task Management Fields *************************************************/
 
-  pid_t    pid;                          /* This is the ID of the thread        */
-  start_t  start;                        /* Thread start function               */
-  entry_t  entry;                        /* Entry Point into the thread         */
-  uint8_t  sched_priority;               /* Current priority of the thread      */
-  uint8_t  init_priority;                /* Initial priority of the thread      */
+  pid_t    pid;                          /* This is the ID of the thread    */
+  start_t  start;                        /* Thread start function           */
+  entry_t  entry;                        /* Entry Point into the thread     */
+  uint8_t  sched_priority;               /* Current priority of the thread  */
+  uint8_t  init_priority;                /* Initial priority of the thread  */
 
 #ifdef CONFIG_PRIORITY_INHERITANCE
 #if CONFIG_SEM_NNESTPRIO > 0
-  uint8_t  npend_reprio;                 /* Number of nested reprioritizations  */
+  uint8_t  npend_reprio;             /* Number of nested reprioritizations  */
   uint8_t  pend_reprios[CONFIG_SEM_NNESTPRIO];
 #endif
-  uint8_t  base_priority;                /* "Normal" priority of the thread     */
+  uint8_t  base_priority;                /* "Normal" priority of the thread */
 #endif
 
-  uint8_t  task_state;                   /* Current state of the thread         */
+  uint8_t  task_state;                   /* Current state of the thread     */
 #ifdef CONFIG_SMP
-  uint8_t  cpu;                          /* CPU index if running or assigned    */
-  cpu_set_t affinity;                    /* Bit set of permitted CPUs           */
+  uint8_t  cpu;                          /* CPU index if running/assigned   */
+  cpu_set_t affinity;                    /* Bit set of permitted CPUs       */
 #endif
-  uint16_t flags;                        /* Misc. general status flags          */
-  int16_t  lockcount;                    /* 0=preemptible (not-locked)          */
+  uint16_t flags;                        /* Misc. general status flags      */
+  int16_t  lockcount;                    /* 0=preemptible (not-locked)      */
 #ifdef CONFIG_IRQCOUNT
-  int16_t  irqcount;                     /* 0=Not in critical section           */
+  int16_t  irqcount;                     /* 0=Not in critical section       */
 #endif
 #ifdef CONFIG_CANCELLATION_POINTS
-  int16_t  cpcount;                      /* Nested cancellation point count     */
+  int16_t  cpcount;                      /* Nested cancellation point count */
 #endif
-  int16_t  errcode;                      /* Used to pass error information      */
+  int16_t  errcode;                      /* Used to pass error information  */
 
 #if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_SPORADIC)
-  int32_t  timeslice;                    /* RR timeslice OR Sporadic budget     */
-                                         /* interval remaining                  */
+  int32_t  timeslice;                    /* RR timeslice OR Sporadic budget */
+                                         /* interval remaining              */
 #endif
 #ifdef CONFIG_SCHED_SPORADIC
-  FAR struct sporadic_s *sporadic;       /* Sporadic scheduling parameters      */
+  FAR struct sporadic_s *sporadic;       /* Sporadic scheduling parameters  */
 #endif
 
-  struct wdog_s waitdog;                 /* All timed waits use this timer      */
+  struct wdog_s waitdog;                 /* All timed waits use this timer  */
 
-  /* Stack-Related Fields *******************************************************/
+  /* Stack-Related Fields ***************************************************/
 
-  size_t    adj_stack_size;              /* Stack size after adjustment         */
-                                         /* for hardware, processor, etc.       */
-                                         /* (for debug purposes only)           */
-  FAR void *stack_alloc_ptr;             /* Pointer to allocated stack          */
-                                         /* Needed to deallocate stack          */
-  FAR void *stack_base_ptr;              /* Adjusted initial stack pointer      */
-                                         /* after the frame has been removed    */
-                                         /* from the stack.                     */
+  size_t    adj_stack_size;              /* Stack size after adjustment     */
+                                         /* for hardware, processor, etc.   */
+                                         /* (for debug purposes only)       */
+  FAR void *stack_alloc_ptr;             /* Pointer to allocated stack      */
+                                         /* Needed to deallocate stack      */
+  FAR void *stack_base_ptr;              /* Adjusted initial stack pointer  */
+                                         /* after the frame has been        */
+                                         /* removed from the stack.         */
 
-  /* External Module Support ****************************************************/
+  /* External Module Support ************************************************/
 
 #ifdef CONFIG_PIC
   FAR struct dspace_s *dspace;           /* Allocated area for .bss and .data   */
 #endif
 
-  /* POSIX Semaphore Control Fields *********************************************/
+  /* POSIX Semaphore Control Fields *****************************************/
 
-  sem_t *waitsem;                        /* Semaphore ID waiting on             */
+  sem_t *waitsem;                        /* Semaphore ID waiting on         */
 
-  /* POSIX Signal Control Fields ************************************************/
+  /* POSIX Signal Control Fields ********************************************/
 
-  sigset_t   sigprocmask;                /* Signals that are blocked            */
-  sigset_t   sigwaitmask;                /* Waiting for pending signals         */
-  sq_queue_t sigpendactionq;             /* List of pending signal actions      */
-  sq_queue_t sigpostedq;                 /* List of posted signals              */
-  siginfo_t  sigunbinfo;                 /* Signal info when task unblocked     */
+  sigset_t   sigprocmask;                /* Signals that are blocked        */
+  sigset_t   sigwaitmask;                /* Waiting for pending signals     */
+  sq_queue_t sigpendactionq;             /* List of pending signal actions  */
+  sq_queue_t sigpostedq;                 /* List of posted signals          */
+  siginfo_t  sigunbinfo;                 /* Signal info when task unblocked */
 
-  /* POSIX Named Message Queue Fields *******************************************/
+  /* POSIX Named Message Queue Fields ***************************************/
 
 #ifndef CONFIG_DISABLE_MQUEUE
-  FAR struct mqueue_inode_s *msgwaitq;   /* Waiting for this message queue      */
+  FAR struct mqueue_inode_s *msgwaitq;   /* Waiting for this message queue  */
 #endif
 
-  /* Robust mutex support *******************************************************/
+  /* Robust mutex support ***************************************************/
 
 #if !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_PTHREAD_MUTEX_UNSAFE)
-  FAR struct pthread_mutex_s *mhead;     /* List of mutexes held by thread      */
+  FAR struct pthread_mutex_s *mhead;     /* List of mutexes held by thread  */
 #endif
 
-  /* Pre-emption monitor support ************************************************/
+  /* Pre-emption monitor support ********************************************/
 
 #ifdef CONFIG_SCHED_CRITMONITOR
   uint32_t premp_start;                  /* Time when preemption disabled       */
@@ -704,65 +707,66 @@ struct tcb_s
   uint32_t crit_max;                     /* Max time in critical section        */
 #endif
 
-  /* State save areas ***********************************************************/
+  /* State save areas *******************************************************/
 
-  /* The form and content of these fields are platform-specific.                */
+  /* The form and content of these fields are platform-specific.            */
 
-  struct xcptcontext xcp;                /* Interrupt register save area        */
+  struct xcptcontext xcp;                /* Interrupt register save area    */
 
 #if CONFIG_TASK_NAME_SIZE > 0
-  char name[CONFIG_TASK_NAME_SIZE + 1];  /* Task name (with NUL terminator)     */
+  char name[CONFIG_TASK_NAME_SIZE + 1];  /* Task name (with NUL terminator  */
 #endif
 };
 
-/* struct task_tcb_s ************************************************************/
+/* struct task_tcb_s ********************************************************/
 
-/* This is the particular form of the task control block (TCB) structure used by
- * tasks (and kernel threads).  There are two TCB forms:  one for pthreads and
- * one for tasks.  Both share the common TCB fields (which must appear at the
- * top of the structure) plus additional fields unique to tasks and threads.
- * Having separate structures for tasks and pthreads adds some complexity, but
- * saves memory in that it prevents pthreads from being burdened with the
+/* This is the particular form of the task control block (TCB) structure used
+ * by tasks (and kernel threads).  There are two TCB forms:  one for pthreads
+ * and one for tasks.
+ * Both share the common TCB fields (which must appear at the top of the
+ * structure) plus additional fields unique to tasks and threads.
+ * Having separate structures for tasks and pthreads adds some complexity,
+ * but saves memory in that it prevents pthreads from being burdened with the
  * overhead required for tasks (and vice versa).
  */
 
 struct task_tcb_s
 {
-  /* Common TCB fields **********************************************************/
+  /* Common TCB fields ******************************************************/
 
   struct tcb_s cmn;                      /* Common TCB fields                   */
 
-  /* Task Management Fields *****************************************************/
+  /* Task Management Fields *************************************************/
 
 #ifdef CONFIG_SCHED_STARTHOOK
   starthook_t starthook;                 /* Task startup function               */
   FAR void *starthookarg;                /* The argument passed to the function */
 #endif
 
-  /* [Re-]start name + start-up parameters **************************************/
+  /* [Re-]start name + start-up parameters **********************************/
 
-  FAR char **argv;                       /* Name+start-up parameters            */
+  FAR char **argv;                       /* Name+start-up parameters        */
 };
 
-/* struct pthread_tcb_s *********************************************************/
+/* struct pthread_tcb_s *****************************************************/
 
-/* This is the particular form of the task control block (TCB) structure used by
- * pthreads.  There are two TCB forms:  one for pthreads and one for tasks.  Both
- * share the common TCB fields (which must appear at the top of the structure)
- * plus additional fields unique to tasks and threads.  Having separate
- * structures for tasks and pthreads adds some complexity,  but saves memory in
- * that it prevents pthreads from being burdened with the overhead required for
- * tasks (and vice versa).
+/* This is the particular form of the task control block (TCB) structure used
+ * by pthreads. There are two TCB forms:  one for pthreads and one for tasks.
+ * Both share the common TCB fields (which must appear at the top of the
+ * structure) plus additional fields unique to tasks and threads.
+ * Having separate structures for tasks and pthreads adds some complexity,
+ * but saves memory in that it prevents pthreads from being burdened with
+ * the overhead required for tasks (and vice versa).
  */
 
 #ifndef CONFIG_DISABLE_PTHREAD
 struct pthread_tcb_s
 {
-  /* Common TCB fields **********************************************************/
+  /* Common TCB fields ******************************************************/
 
-  struct tcb_s cmn;                      /* Common TCB fields                   */
+  struct tcb_s cmn;                      /* Common TCB fields               */
 
-  /* Task Management Fields *****************************************************/
+  /* Task Management Fields *************************************************/
 
   pthread_trampoline_t trampoline;       /* User-space pthread startup function */
   pthread_addr_t arg;                    /* Startup argument                    */
@@ -777,9 +781,9 @@ typedef CODE void (*nxsched_foreach_t)(FAR struct tcb_s *tcb, FAR void *arg);
 
 #endif /* __ASSEMBLY__ */
 
-/********************************************************************************
+/****************************************************************************
  * Public Data
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifndef __ASSEMBLY__
 #undef EXTERN
@@ -803,11 +807,11 @@ EXTERN uint32_t g_crit_max[1];
 #endif
 #endif /* CONFIG_SCHED_CRITMONITOR */
 
-/********************************************************************************
+/****************************************************************************
  * Public Function Prototypes
- ********************************************************************************/
+ ****************************************************************************/
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_self
  *
  * Description:
@@ -815,11 +819,11 @@ EXTERN uint32_t g_crit_max[1];
  *   head of the ready-to-run list and manages access to the TCB from outside
  *   of the sched/ sub-directory.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 FAR struct tcb_s *nxsched_self(void);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_foreach
  *
  * Description:
@@ -840,11 +844,11 @@ FAR struct tcb_s *nxsched_self(void);
  * Returned Value:
  *   None
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 void nxsched_foreach(nxsched_foreach_t handler, FAR void *arg);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_get_tcb
  *
  * Description:
@@ -858,25 +862,25 @@ void nxsched_foreach(nxsched_foreach_t handler, FAR void *arg);
  *   should establish the critical section BEFORE calling this function and
  *   hold that critical section as long as necessary.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 FAR struct tcb_s *nxsched_get_tcb(pid_t pid);
 
-/********************************************************************************
+/****************************************************************************
  * Name:  nxsched_releasepid
  *
  * Description:
  *   When a task is destroyed, this function must be called to make its
  *   process ID available for re-use.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 int nxsched_release_tcb(FAR struct tcb_s *tcb, uint8_t ttype);
 
-/* File system helpers **********************************************************/
+/* File system helpers ******************************************************/
 
-/* These functions all extract lists from the group structure associated with the
- * currently executing task.
+/* These functions all extract lists from the group structure associated with
+ * the currently executing task.
  */
 
 FAR struct filelist *nxsched_get_files(void);
@@ -884,7 +888,7 @@ FAR struct filelist *nxsched_get_files(void);
 FAR struct streamlist *nxsched_get_streams(void);
 #endif /* CONFIG_FILE_STREAM */
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxtask_init
  *
  * Description:
@@ -920,13 +924,13 @@ FAR struct streamlist *nxsched_get_streams(void);
  *   nxsched_release_tcb() to free the TCB (which could be in most any
  *   state).
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
                 FAR void *stack, uint32_t stack_size, main_t entry,
                 FAR char * const argv[]);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxtask_uninit
  *
  * Description:
@@ -943,11 +947,11 @@ int nxtask_init(FAR struct task_tcb_s *tcb, const char *name, int priority,
  * Returned Value:
  *   OK on success; negative error value on failure appropriately.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 void nxtask_uninit(FAR struct task_tcb_s *tcb);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxtask_activate
  *
  * Description:
@@ -962,11 +966,11 @@ void nxtask_uninit(FAR struct task_tcb_s *tcb);
  * Returned Value:
  *   None
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 void nxtask_activate(FAR struct tcb_s *tcb);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxtask_starthook
  *
  * Description:
@@ -983,14 +987,14 @@ void nxtask_activate(FAR struct tcb_s *tcb);
  * Returned Value:
  *   None
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_SCHED_STARTHOOK
 void nxtask_starthook(FAR struct task_tcb_s *tcb, starthook_t starthook,
                       FAR void *arg);
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxtask_startup
  *
  * Description:
@@ -1004,20 +1008,20 @@ void nxtask_starthook(FAR struct task_tcb_s *tcb, starthook_t starthook,
  * Returned Value:
  *   None.  This function does not return.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifndef CONFIG_BUILD_KERNEL
 void nxtask_startup(main_t entrypt, int argc, FAR char *argv[]);
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Internal vfork support.  The overall sequence is:
  *
  * 1) User code calls vfork().  vfork() is provided in architecture-specific
  *    code.
  * 2) vfork()and calls nxtask_setup_vfork().
- * 3) nxtask_setup_vfork() allocates and configures the child task's TCB.  This
- *    consists of:
+ * 3) nxtask_setup_vfork() allocates and configures the child task's TCB.
+ *    This consists of:
  *    - Allocation of the child task's TCB.
  *    - Initialization of file descriptors and streams
  *    - Configuration of environment variables
@@ -1030,15 +1034,16 @@ void nxtask_startup(main_t entrypt, int argc, FAR char *argv[]);
  * 5) vfork() then calls nxtask_start_vfork()
  * 6) nxtask_start_vfork() then executes the child thread.
  *
- * nxtask_abort_vfork() may be called if an error occurs between steps 3 and 6.
+ * nxtask_abort_vfork() may be called if an error occurs between
+ * steps 3 and 6.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 FAR struct task_tcb_s *nxtask_setup_vfork(start_t retaddr);
 pid_t nxtask_start_vfork(FAR struct task_tcb_s *child);
 void nxtask_abort_vfork(FAR struct task_tcb_s *child, int errcode);
 
-/********************************************************************************
+/****************************************************************************
  * Name: group_exitinfo
  *
  * Description:
@@ -1056,18 +1061,19 @@ void nxtask_abort_vfork(FAR struct task_tcb_s *child, int errcode);
  *   0 (OK) is returned on success and a negated errno is returned on
  *   failure.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_BINFMT_LOADABLE
 struct binary_s;  /* Forward reference */
 int group_exitinfo(pid_t pid, FAR struct binary_s *bininfo);
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_resume_scheduler
  *
  * Description:
- *   Called by architecture specific implementations that block task execution.
+ *   Called by architecture specific implementations that block task
+ *   execution.
  *   This function prepares the scheduler for the thread that is about to be
  *   restarted.
  *
@@ -1077,7 +1083,7 @@ int group_exitinfo(pid_t pid, FAR struct binary_s *bininfo);
  * Returned Value:
  *   None
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #if CONFIG_RR_INTERVAL > 0 || defined(CONFIG_SCHED_RESUMESCHEDULER)
 void nxsched_resume_scheduler(FAR struct tcb_s *tcb);
@@ -1085,13 +1091,14 @@ void nxsched_resume_scheduler(FAR struct tcb_s *tcb);
 #  define nxsched_resume_scheduler(tcb)
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_suspend_scheduler
  *
  * Description:
- *   Called by architecture specific implementations to resume task execution.
- *   This function performs scheduler operations for the thread that is about to
- *   be suspended.
+ *   Called by architecture specific implementations to resume task
+ *   execution.
+ *   This function performs scheduler operations for the thread that is about
+ *   to be suspended.
  *
  * Input Parameters:
  *   tcb - The TCB of the thread to be restarted.
@@ -1099,7 +1106,7 @@ void nxsched_resume_scheduler(FAR struct tcb_s *tcb);
  * Returned Value:
  *   None
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_SCHED_SUSPENDSCHEDULER
 void nxsched_suspend_scheduler(FAR struct tcb_s *tcb);
@@ -1107,7 +1114,7 @@ void nxsched_suspend_scheduler(FAR struct tcb_s *tcb);
 #  define nxsched_suspend_scheduler(tcb)
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_get_param
  *
  * Description:
@@ -1133,12 +1140,12 @@ void nxsched_suspend_scheduler(FAR struct tcb_s *tcb);
  *   This function can fail if param is null (EINVAL) or if pid does
  *   not correspond to any task (ESRCH).
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 struct sched_param;  /* Forward reference */
 int nxsched_get_param (pid_t pid, FAR struct sched_param *param);
 
-/********************************************************************************
+/****************************************************************************
  * Name:  nxsched_set_param
  *
  * Description:
@@ -1170,12 +1177,12 @@ int nxsched_get_param (pid_t pid, FAR struct sched_param *param);
  *   EPERM  The calling task does not have appropriate privileges.
  *   ESRCH  The task whose ID is pid could not be found.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 struct sched_param;  /* Forward reference */
 int nxsched_set_param(pid_t pid, FAR const struct sched_param *param);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_get_scheduler
  *
  * Description:
@@ -1202,11 +1209,11 @@ int nxsched_set_param(pid_t pid, FAR const struct sched_param *param);
  *
  *      ESRCH  The task whose ID is pid could not be found.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 int nxsched_get_scheduler(pid_t pid);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_set_scheduler
  *
  * Description:
@@ -1238,12 +1245,12 @@ int nxsched_get_scheduler(pid_t pid);
  *   EINVAL The scheduling policy is not one of the recognized policies.
  *   ESRCH  The task whose ID is pid could not be found.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 int nxsched_set_scheduler(pid_t pid, int policy,
                           FAR const struct sched_param *param);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_get_affinity
  *
  * Description:
@@ -1270,13 +1277,13 @@ int nxsched_set_scheduler(pid_t pid, int policy,
  *
  *     ESRCH  The task whose ID is pid could not be found.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_SMP
 int nxsched_get_affinity(pid_t pid, size_t cpusetsize, FAR cpu_set_t *mask);
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_set_affinity
  *
  * Description:
@@ -1306,14 +1313,14 @@ int nxsched_get_affinity(pid_t pid, size_t cpusetsize, FAR cpu_set_t *mask);
  *
  *     ESRCH  The task whose ID is pid could not be found.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_SMP
 int nxsched_set_affinity(pid_t pid, size_t cpusetsize,
                          FAR const cpu_set_t *mask);
 #endif
 
-/********************************************************************************
+/****************************************************************************
  * Name: nxsched_get_stackinfo
  *
  * Description:
@@ -1331,13 +1338,13 @@ int nxsched_set_affinity(pid_t pid, size_t cpusetsize,
  *     -EACCES  The calling thread does not have privileges to access the
  *              stack of the thread associated with the pid.
  *
- ********************************************************************************/
+ ****************************************************************************/
 
 int nxsched_get_stackinfo(pid_t pid, FAR struct stackinfo_s *stackinfo);
 
-/********************************************************************************
+/****************************************************************************
  * Name: nx_wait/nx_waitid/nx_waitpid
- ********************************************************************************/
+ ****************************************************************************/
 
 #ifdef CONFIG_SCHED_WAITPID
 pid_t nx_wait(FAR int *stat_loc);

[incubator-nuttx] 05/09: libc/pthread: Fix comment and document issue

Posted by gn...@apache.org.
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 81a01d089b7fa3be3ed94971712ac97500dfdb87
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Thu May 6 16:01:16 2021 +0800

    libc/pthread: Fix comment and document issue
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 arch/arm/src/armv7-a/arm_syscall.c           |  2 +-
 arch/arm/src/armv7-r/arm_syscall.c           |  2 +-
 arch/risc-v/src/common/riscv_pthread_start.c |  2 +-
 include/nuttx/pthread.h                      | 16 +++++++++-------
 libs/libc/pthread/pthread_exit.c             |  2 +-
 sched/pthread/pthread_create.c               | 12 +++++++-----
 sched/pthread/pthread_exit.c                 |  2 +-
 7 files changed, 21 insertions(+), 17 deletions(-)

diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c
index e71a6b0..985dc63 100644
--- a/arch/arm/src/armv7-a/arm_syscall.c
+++ b/arch/arm/src/armv7-a/arm_syscall.c
@@ -293,7 +293,7 @@ uint32_t *arm_syscall(uint32_t *regs)
 #if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
-          /* Set up to return to the user-space pthread start-up function in
+          /* Set up to enter the user-space pthread start-up function in
            * unprivileged mode. We need:
            *
            *   R0   = entrypt
diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c
index ea827bf..29095d0 100644
--- a/arch/arm/src/armv7-r/arm_syscall.c
+++ b/arch/arm/src/armv7-r/arm_syscall.c
@@ -288,7 +288,7 @@ uint32_t *arm_syscall(uint32_t *regs)
 #if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
-          /* Set up to return to the user-space pthread start-up function in
+          /* Set up to enter the user-space pthread start-up function in
            * unprivileged mode. We need:
            *
            *   R0   = startup
diff --git a/arch/risc-v/src/common/riscv_pthread_start.c b/arch/risc-v/src/common/riscv_pthread_start.c
index 723f7ca..20b5608 100644
--- a/arch/risc-v/src/common/riscv_pthread_start.c
+++ b/arch/risc-v/src/common/riscv_pthread_start.c
@@ -64,7 +64,7 @@
 void up_pthread_start(pthread_trampoline_t startup,
                       pthread_startroutine_t entrypt, pthread_addr_t arg)
 {
-  /* Let sys_call2() do all of the work */
+  /* Let sys_call3() do all of the work */
 
   sys_call3(SYS_pthread_start, (uintptr_t)startup, (uintptr_t)entrypt,
             (uintptr_t)arg);
diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h
index aa21cd6..d8e30aa 100644
--- a/include/nuttx/pthread.h
+++ b/include/nuttx/pthread.h
@@ -133,11 +133,13 @@ EXTERN const pthread_attr_t g_default_pthread_attr;
  *   attributes.
  *
  * Input Parameters:
- *    trampoline
- *    thread
- *    attr
- *    start_routine
- *    arg
+ *    trampoline - The user space startup function
+ *    thread     - The pthread handle to be used
+ *    attr       - It points to a pthread_attr_t structure whose contents are
+ *                 used at thread creation time to determine attributes
+ *                 for the new thread
+ *    entry      - The new thread starts execution by invoking entry
+ *    arg        - It is passed as the sole argument of entry
  *
  * Returned Value:
  *   OK (0) on success; a (non-negated) errno value on failure. The errno
@@ -156,7 +158,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
  *   Terminate execution of a thread started with pthread_create.
  *
  * Input Parameters:
- *   exit_valie
+ *   exit_value
  *
  * Returned Value:
  *   None
@@ -176,7 +178,7 @@ void nx_pthread_exit(FAR void *exit_value) noreturn_function;
  *   within the pthread_exit() and pthread_cancellation() logic
  *
  * Input Parameters:
- *   tcb - The TCB of the pthread that is exiting or being canceled.
+ *   None
  *
  * Returned Value:
  *   None
diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c
index 740a325..2e456b6 100644
--- a/libs/libc/pthread/pthread_exit.c
+++ b/libs/libc/pthread/pthread_exit.c
@@ -40,7 +40,7 @@
  *   Terminate execution of a thread started with pthread_create.
  *
  * Input Parameters:
- *   exit_valie
+ *   exit_value
  *
  * Returned Value:
  *   None
diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c
index 22cd008..ade4dc6 100644
--- a/sched/pthread/pthread_create.c
+++ b/sched/pthread/pthread_create.c
@@ -208,11 +208,13 @@ static void pthread_start(void)
  *   attributes.
  *
  * Input Parameters:
- *    trampoline
- *    thread
- *    attr
- *    start_routine
- *    arg
+ *    trampoline - The user space startup function
+ *    thread     - The pthread handle to be used
+ *    attr       - It points to a pthread_attr_t structure whose contents are
+ *                 used at thread creation time to determine attributes
+ *                 for the new thread
+ *    entry      - The new thread starts execution by invoking entry
+ *    arg        - It is passed as the sole argument of entry
  *
  * Returned Value:
  *   OK (0) on success; a (non-negated) errno value on failure. The errno
diff --git a/sched/pthread/pthread_exit.c b/sched/pthread/pthread_exit.c
index a7704ab..4d55560 100644
--- a/sched/pthread/pthread_exit.c
+++ b/sched/pthread/pthread_exit.c
@@ -50,7 +50,7 @@
  *   Terminate execution of a thread started with pthread_create.
  *
  * Input Parameters:
- *   exit_valie
+ *   exit_value
  *
  * Returned Value:
  *   None

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

Posted by gn...@apache.org.
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 *"

[incubator-nuttx] 01/09: libc: Move pthread_create to user space

Posted by gn...@apache.org.
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 bb9b58bddea2d7e188edbecfbbf38f420c2d5ad9
Author: Gregory Nutt <gn...@nuttx.org>
AuthorDate: Mon Jun 29 08:26:29 2020 -0600

    libc: Move pthread_create to user space
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
    Change-Id: I5c447d94077debc79158686935f288e4c8e51e01
---
 arch/arm/src/armv6-m/arm_svcall.c                  | 12 ++--
 arch/arm/src/armv6-m/svcall.h                      | 21 +++---
 arch/arm/src/armv7-a/arm_syscall.c                 | 12 ++--
 arch/arm/src/armv7-a/svcall.h                      | 20 +++---
 arch/arm/src/armv7-m/arm_svcall.c                  | 12 ++--
 arch/arm/src/armv7-m/svcall.h                      | 20 +++---
 arch/arm/src/armv7-r/arm_syscall.c                 |  6 +-
 arch/arm/src/armv7-r/svcall.h                      | 20 +++---
 arch/arm/src/armv8-m/arm_svcall.c                  | 10 +--
 arch/arm/src/armv8-m/svcall.h                      | 20 +++---
 arch/arm/src/common/arm_pthread_start.c            | 11 +--
 arch/or1k/src/common/up_pthread_start.c            |  6 +-
 arch/risc-v/src/common/riscv_pthread_start.c       |  9 ++-
 arch/risc-v/src/rv64gc/riscv_swint.c               | 12 ++--
 arch/risc-v/src/rv64gc/svcall.h                    | 21 +++---
 .../imxrt/imxrt1050-evk/kernel/imxrt_userspace.c   |  3 -
 .../imxrt/imxrt1060-evk/kernel/imxrt_userspace.c   |  3 -
 .../lc823450-xgevk/kernel/lc823450_userspace.c     |  3 -
 .../lpc4088-devkit/kernel/lpc17_40_userspace.c     |  3 -
 .../lpc4088-quickstart/kernel/lpc17_40_userspace.c |  3 -
 .../open1788/kernel/lpc17_40_userspace.c           |  3 -
 .../pnev5180b/kernel/lpc17_40_userspace.c          |  3 -
 .../lpc43xx/bambino-200e/kernel/lpc43_userspace.c  |  3 -
 boards/arm/sam34/sam3u-ek/kernel/sam_userspace.c   |  3 -
 .../samv7/same70-xplained/kernel/sam_userspace.c   |  3 -
 .../arm/samv7/samv71-xult/kernel/sam_userspace.c   |  3 -
 .../stm32/clicker2-stm32/kernel/stm32_userspace.c  |  3 -
 .../stm32/mikroe-stm32f4/kernel/stm32_userspace.c  |  3 -
 .../olimex-stm32-p407/kernel/stm32_userspace.c     |  3 -
 .../arm/stm32/omnibusf4/kernel/stm32_userspace.c   |  3 -
 .../stm32/stm3240g-eval/kernel/stm32_userspace.c   |  3 -
 .../stm32f4discovery/kernel/stm32_userspace.c      |  3 -
 .../stm32f746g-disco/kernel/stm32_userspace.c      |  3 -
 .../stm32f769i-disco/kernel/stm32_userspace.c      |  3 -
 .../stm32h7/nucleo-h743zi/kernel/stm32_userspace.c |  3 -
 .../stm32h747i-disco/kernel/stm32_userspace.c      |  3 -
 .../stm32l476vg-disco/kernel/stm32l4_userspace.c   |  3 -
 .../stm32l4r9ai-disco/kernel/stm32l4_userspace.c   |  3 -
 boards/arm/tiva/lm3s6965-ek/kernel/lm_userspace.c  |  3 -
 .../risc-v/k210/maix-bit/kernel/k210_userspace.c   |  3 -
 include/nuttx/arch.h                               |  6 +-
 include/nuttx/pthread.h                            | 30 +++++++-
 include/nuttx/sched.h                              |  1 +
 include/nuttx/userspace.h                          | 26 +------
 include/pthread.h                                  |  2 +
 include/sys/syscall_lookup.h                       |  2 +-
 libs/libc/pthread/Make.defs                        | 14 ++--
 .../{pthread_startup.c => pthread_create.c}        | 80 +++++++++++-----------
 sched/pthread/pthread_create.c                     | 50 ++++++++------
 syscall/syscall.csv                                |  2 +-
 50 files changed, 235 insertions(+), 265 deletions(-)

diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c
index d7b5430..0339ccc 100644
--- a/arch/arm/src/armv6-m/arm_svcall.c
+++ b/arch/arm/src/armv6-m/arm_svcall.c
@@ -310,22 +310,22 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
        *   R2 = arg
        */
 
-#if defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_DISABLE_PTHREAD)
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode.
            */
 
-          regs[REG_PC]         = (uint32_t)USERSPACE->pthread_startup;
+          regs[REG_PC]         = (uint32_t)regs[REG_R1]; /* startup */
           regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
 
-          /* Change the parameter ordering to match the expectation of struct
-           * userpace_s pthread_startup:
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
            */
 
-          regs[REG_R0]         = regs[REG_R1]; /* pthread entry */
-          regs[REG_R1]         = regs[REG_R2]; /* arg */
+          regs[REG_R0]         = regs[REG_R2]; /* pthread entry */
+          regs[REG_R1]         = regs[REG_R3]; /* arg */
         }
         break;
 #endif
diff --git a/arch/arm/src/armv6-m/svcall.h b/arch/arm/src/armv6-m/svcall.h
index 7f2f45f..a790f58 100644
--- a/arch/arm/src/armv6-m/svcall.h
+++ b/arch/arm/src/armv6-m/svcall.h
@@ -89,6 +89,7 @@
 
 #define SYS_syscall_return        (3)
 
+#ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_BUILD_PROTECTED
 /* SYS call 4:
  *
@@ -98,15 +99,6 @@
 
 #define SYS_task_start            (4)
 
-/* SYS call 5:
- *
- * void up_pthread_start(pthread_startroutine_t entrypt,
- *                       pthread_addr_t arg)
- *        noreturn_function
- */
-
-#define SYS_pthread_start         (5)
-
 /* SYS call 6:
  *
  * void signal_handler(_sa_sigaction_t sighand, int signo,
@@ -124,6 +116,17 @@
 #define SYS_signal_handler_return (7)
 
 #endif /* CONFIG_BUILD_PROTECTED */
+
+/* SYS call 5:
+ *
+ * void up_pthread_start(pthread_startroutine_t startup,
+ *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (5)
+
+#endif /* !CONFIG_BUILD_FLAT */
 #endif /* CONFIG_LIB_SYSCALL */
 
 /****************************************************************************
diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c
index ea6b31e..e71a6b0 100644
--- a/arch/arm/src/armv7-a/arm_syscall.c
+++ b/arch/arm/src/armv7-a/arm_syscall.c
@@ -290,19 +290,21 @@ uint32_t *arm_syscall(uint32_t *regs)
        *   R2 = arg
        */
 
-#if defined(CONFIG_BUILD_KERNEL) && !defined(CONFIG_DISABLE_PTHREAD)
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode. We need:
            *
-           *   R0   = arg
-           *   PC   = entrypt
+           *   R0   = entrypt
+           *   R1   = arg
+           *   PC   = startup
            *   CSPR = user mode
            */
 
-          regs[REG_PC]   = regs[REG_R1];
-          regs[REG_R0]   = regs[REG_R2];
+          regs[REG_PC]   = regs[REG_R0];
+          regs[REG_R0]   = regs[REG_R1];
+          regs[REG_R1]   = regs[REG_R2];
 
           cpsr           = regs[REG_CPSR] & ~PSR_MODE_MASK;
           regs[REG_CPSR] = cpsr | PSR_MODE_USR;
diff --git a/arch/arm/src/armv7-a/svcall.h b/arch/arm/src/armv7-a/svcall.h
index f0bb700..27dc875 100644
--- a/arch/arm/src/armv7-a/svcall.h
+++ b/arch/arm/src/armv7-a/svcall.h
@@ -65,6 +65,7 @@
 
 #define SYS_syscall_return        (0)
 
+#ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_BUILD_KERNEL
 /* SYS call 1:
  *
@@ -81,14 +82,6 @@
 
 #define SYS_task_start            (2)
 
-/* SYS call 3:
- *
- * void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
- *        noreturn_function
- */
-
-#define SYS_pthread_start         (3)
-
 /* SYS call 4:
  *
  * void signal_handler(_sa_sigaction_t sighand,
@@ -105,6 +98,17 @@
 
 #define SYS_signal_handler_return (5)
 
+#endif /* !CONFIG_BUILD_FLAT */
+
+/* SYS call 3:
+ *
+ * void up_pthread_start(pthread_startroutine_t startup,
+ *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (3)
+
 #endif /* CONFIG_BUILD_KERNEL */
 
 /****************************************************************************
diff --git a/arch/arm/src/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c
index 2112ea7..6119ee6 100644
--- a/arch/arm/src/armv7-m/arm_svcall.c
+++ b/arch/arm/src/armv7-m/arm_svcall.c
@@ -324,22 +324,22 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
        *   R2 = arg
        */
 
-#if defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_DISABLE_PTHREAD)
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode.
            */
 
-          regs[REG_PC]         = (uint32_t)USERSPACE->pthread_startup & ~1;
+          regs[REG_PC]         = (uint32_t)regs[REG_R1] & ~1;  /* startup */
           regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
 
-          /* Change the parameter ordering to match the expectation of struct
-           * userpace_s pthread_startup:
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
            */
 
-          regs[REG_R0]         = regs[REG_R1]; /* pthread entry */
-          regs[REG_R1]         = regs[REG_R2]; /* arg */
+          regs[REG_R0]         = regs[REG_R2]; /* pthread entry */
+          regs[REG_R1]         = regs[REG_R3]; /* arg */
         }
         break;
 #endif
diff --git a/arch/arm/src/armv7-m/svcall.h b/arch/arm/src/armv7-m/svcall.h
index 9f3b977..98a574e 100644
--- a/arch/arm/src/armv7-m/svcall.h
+++ b/arch/arm/src/armv7-m/svcall.h
@@ -81,6 +81,7 @@
 
 #define SYS_switch_context        (2)
 
+#ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_LIB_SYSCALL
 /* SYS call 3:
  *
@@ -98,14 +99,6 @@
 
 #define SYS_task_start            (4)
 
-/* SYS call 5:
- *
- * void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
- *        noreturn_function
- */
-
-#define SYS_pthread_start         (5)
-
 /* SYS call 6:
  *
  * void signal_handler(_sa_sigaction_t sighand,
@@ -123,6 +116,17 @@
 #define SYS_signal_handler_return (7)
 
 #endif /* CONFIG_BUILD_PROTECTED */
+
+/* SYS call 5:
+ *
+ * void up_pthread_start((pthread_startroutine_t startup,
+ *                        pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (5)
+
+#endif /* !CONFIG_BUILD_FLAT */
 #endif /* CONFIG_LIB_SYSCALL */
 
 /****************************************************************************
diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c
index ff49468..ea827bf 100644
--- a/arch/arm/src/armv7-r/arm_syscall.c
+++ b/arch/arm/src/armv7-r/arm_syscall.c
@@ -285,19 +285,21 @@ uint32_t *arm_syscall(uint32_t *regs)
        *   R2 = arg
        */
 
-#if defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_DISABLE_PTHREAD)
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode. We need:
            *
-           *   R0   = arg
+           *   R0   = startup
+           *   R1   = arg
            *   PC   = entrypt
            *   CSPR = user mode
            */
 
           regs[REG_PC]   = regs[REG_R1];
           regs[REG_R0]   = regs[REG_R2];
+          regs[REG_R1]   = regs[REG_R3];
 
           cpsr           = regs[REG_CPSR] & ~PSR_MODE_MASK;
           regs[REG_CPSR] = cpsr | PSR_MODE_USR;
diff --git a/arch/arm/src/armv7-r/svcall.h b/arch/arm/src/armv7-r/svcall.h
index ffd8737..2470da7 100644
--- a/arch/arm/src/armv7-r/svcall.h
+++ b/arch/arm/src/armv7-r/svcall.h
@@ -66,6 +66,7 @@
 
 #define SYS_syscall_return        (0)
 
+#ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_BUILD_PROTECTED
 /* SYS call 1:
  *
@@ -82,14 +83,6 @@
 
 #define SYS_task_start            (2)
 
-/* SYS call 3:
- *
- * void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
- *        noreturn_function
- */
-
-#define SYS_pthread_start         (3)
-
 /* SYS call 4:
  *
  * void signal_handler(_sa_sigaction_t sighand, int signo,
@@ -108,6 +101,17 @@
 
 #endif /* CONFIG_BUILD_PROTECTED */
 
+/* SYS call 3:
+ *
+ * void up_pthread_start(pthread_startroutine_t startup,
+ *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (3)
+
+#endif /* !CONFIG_BUILD_FLAT */
+
 /****************************************************************************
  * Inline Functions
  ****************************************************************************/
diff --git a/arch/arm/src/armv8-m/arm_svcall.c b/arch/arm/src/armv8-m/arm_svcall.c
index ed28937..f0757c7 100644
--- a/arch/arm/src/armv8-m/arm_svcall.c
+++ b/arch/arm/src/armv8-m/arm_svcall.c
@@ -323,21 +323,21 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
        *   R2 = arg
        */
 
-#if defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_DISABLE_PTHREAD)
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode.
            */
 
-          regs[REG_PC]         = (uint32_t)USERSPACE->pthread_startup & ~1;
+          regs[REG_PC]         = (uint32_t)regs[REG_R1] & ~1;  /* startup */
           regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
 
-          /* Change the parameter ordering to match the expectation of struct
-           * userpace_s pthread_startup:
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
            */
 
-          regs[REG_R0]         = regs[REG_R1]; /* pthread entry */
+          regs[REG_R0]         = regs[REG_R2]; /* pthread entry */
           regs[REG_R1]         = regs[REG_R2]; /* arg */
         }
         break;
diff --git a/arch/arm/src/armv8-m/svcall.h b/arch/arm/src/armv8-m/svcall.h
index 77a1f92..7213084 100644
--- a/arch/arm/src/armv8-m/svcall.h
+++ b/arch/arm/src/armv8-m/svcall.h
@@ -88,6 +88,7 @@
 
 #define SYS_syscall_return        (3)
 
+#ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_BUILD_PROTECTED
 /* SYS call 4:
  *
@@ -97,14 +98,6 @@
 
 #define SYS_task_start            (4)
 
-/* SYS call 5:
- *
- * void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
- *        noreturn_function
- */
-
-#define SYS_pthread_start         (5)
-
 /* SYS call 6:
  *
  * void signal_handler(_sa_sigaction_t sighand,
@@ -122,6 +115,17 @@
 #define SYS_signal_handler_return (7)
 
 #endif /* CONFIG_BUILD_PROTECTED */
+
+/* SYS call 5:
+ *
+ * void up_pthread_start(pthread_startroutine_t startup,
+ *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (5)
+
+#endif /* !CONFIG_BUILD_FLAT */
 #endif /* CONFIG_LIB_SYSCALL */
 
 /****************************************************************************
diff --git a/arch/arm/src/common/arm_pthread_start.c b/arch/arm/src/common/arm_pthread_start.c
index f96c4a5..7e7e8e7 100644
--- a/arch/arm/src/common/arm_pthread_start.c
+++ b/arch/arm/src/common/arm_pthread_start.c
@@ -47,9 +47,10 @@
  *   pthread.
  *
  *   Normally the a user-mode start-up stub will also execute before the
- *   pthread actually starts.  See libc/pthread/pthread_startup.c
+ *   pthread actually starts.  See libc/pthread/pthread_create.c
  *
  * Input Parameters:
+ *   startup - The user-space pthread startup function
  *   entrypt - The user-space address of the pthread entry point
  *   arg     - Standard argument for the pthread entry point
  *
@@ -60,11 +61,13 @@
  *
  ****************************************************************************/
 
-void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
+void up_pthread_start(pthread_trampoline_t startup,
+                      pthread_startroutine_t entrypt, pthread_addr_t arg)
 {
-  /* Let sys_call2() do all of the work */
+  /* Let sys_call3() do all of the work */
 
-  sys_call2(SYS_pthread_start, (uintptr_t)entrypt, (uintptr_t)arg);
+  sys_call3(SYS_pthread_start, (uintptr_t)startup, (uintptr_t)entrypt,
+            (uintptr_t)arg);
 
   PANIC();
 }
diff --git a/arch/or1k/src/common/up_pthread_start.c b/arch/or1k/src/common/up_pthread_start.c
index f32c4bb..8edbd06 100644
--- a/arch/or1k/src/common/up_pthread_start.c
+++ b/arch/or1k/src/common/up_pthread_start.c
@@ -47,9 +47,10 @@
  *   pthread.
  *
  *   Normally the a user-mode start-up stub will also execute before the
- *   pthread actually starts.  See libc/pthread/pthread_startup.c
+ *   pthread actually starts.  See libc/pthread/pthread_create.c
  *
  * Input Parameters:
+ *   startup - The user-space pthread startup function
  *   entrypt - The user-space address of the pthread entry point
  *   arg     - Standard argument for the pthread entry point
  *
@@ -66,7 +67,8 @@ void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
 
   sinfo("entry %p arg %p\n", entrypt, arg);
 
-  sys_call2(SYS_pthread_start, (uintptr_t)entrypt, (uintptr_t)arg);
+  sys_call3(SYS_pthread_start, (uintptr_t)startup, (uintptr_t)entrypt,
+            (uintptr_t)arg);
 
   PANIC();
 }
diff --git a/arch/risc-v/src/common/riscv_pthread_start.c b/arch/risc-v/src/common/riscv_pthread_start.c
index f66b174..723f7ca 100644
--- a/arch/risc-v/src/common/riscv_pthread_start.c
+++ b/arch/risc-v/src/common/riscv_pthread_start.c
@@ -47,9 +47,10 @@
  *   pthread.
  *
  *   Normally the a user-mode start-up stub will also execute before the
- *   pthread actually starts.  See libc/pthread/pthread_startup.c
+ *   pthread actually starts.  See libc/pthread/pthread_create.c
  *
  * Input Parameters:
+ *   startup - The user-space pthread startup function
  *   entrypt - The user-space address of the pthread entry point
  *   arg     - Standard argument for the pthread entry point
  *
@@ -60,11 +61,13 @@
  *
  ****************************************************************************/
 
-void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
+void up_pthread_start(pthread_trampoline_t startup,
+                      pthread_startroutine_t entrypt, pthread_addr_t arg)
 {
   /* Let sys_call2() do all of the work */
 
-  sys_call2(SYS_pthread_start, (uintptr_t)entrypt, (uintptr_t)arg);
+  sys_call3(SYS_pthread_start, (uintptr_t)startup, (uintptr_t)entrypt,
+            (uintptr_t)arg);
 
   PANIC();
 }
diff --git a/arch/risc-v/src/rv64gc/riscv_swint.c b/arch/risc-v/src/rv64gc/riscv_swint.c
index 23de0e7..7e6d90b 100644
--- a/arch/risc-v/src/rv64gc/riscv_swint.c
+++ b/arch/risc-v/src/rv64gc/riscv_swint.c
@@ -294,21 +294,21 @@ int riscv_swint(int irq, FAR void *context, FAR void *arg)
        *   R2 = arg
        */
 
-#if defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_DISABLE_PTHREAD)
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode.
            */
 
-          regs[REG_EPC]      = (uintptr_t)USERSPACE->pthread_startup & ~1;
+          regs[REG_EPC]      = (uintptr_t)regs[REG_A1] & ~1;  /* startup */
 
-          /* Change the parameter ordering to match the expectation of struct
-           * userpace_s pthread_startup:
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
            */
 
-          regs[REG_A0]       = regs[REG_A1];  /* pthread entry */
-          regs[REG_A1]       = regs[REG_A2];  /* arg */
+          regs[REG_A0]       = regs[REG_A2];  /* pthread entry */
+          regs[REG_A1]       = regs[REG_A3];  /* arg */
           regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
         }
         break;
diff --git a/arch/risc-v/src/rv64gc/svcall.h b/arch/risc-v/src/rv64gc/svcall.h
index 690f562..80c8c15 100644
--- a/arch/risc-v/src/rv64gc/svcall.h
+++ b/arch/risc-v/src/rv64gc/svcall.h
@@ -82,6 +82,7 @@
 
 #define SYS_switch_context        (2)
 
+#ifndef CONFIG_BUILD_FLAT
 #ifdef CONFIG_LIB_SYSCALL
 /* SYS call 3:
  *
@@ -98,15 +99,6 @@
  */
 
 #define SYS_task_start            (4)
-
-/* SYS call 5:
- *
- * void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
- *        noreturn_function
- */
-
-#define SYS_pthread_start         (5)
-
 /* SYS call 6:
  *
  * void signal_handler(_sa_sigaction_t sighand, int signo,
@@ -123,6 +115,17 @@
 #define SYS_signal_handler_return (7)
 
 #endif /* CONFIG_BUILD_PROTECTED */
+
+/* SYS call 5:
+ *
+ * void up_pthread_start(pthread_startroutine_t startup,
+ *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
+ *        noreturn_function
+ */
+
+#define SYS_pthread_start         (5)
+
+#endif /* !CONFIG_BUILD_FLAT */
 #endif /* CONFIG_LIB_SYSCALL */
 
 #endif /* __ARCH_RISCV_SRC_RV64GC_SVCALL_H */
diff --git a/boards/arm/imxrt/imxrt1050-evk/kernel/imxrt_userspace.c b/boards/arm/imxrt/imxrt1050-evk/kernel/imxrt_userspace.c
index 2654b3b..0f0ee11 100644
--- a/boards/arm/imxrt/imxrt1050-evk/kernel/imxrt_userspace.c
+++ b/boards/arm/imxrt/imxrt1050-evk/kernel/imxrt_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/imxrt/imxrt1060-evk/kernel/imxrt_userspace.c b/boards/arm/imxrt/imxrt1060-evk/kernel/imxrt_userspace.c
index 3a706f3..e2557c7 100644
--- a/boards/arm/imxrt/imxrt1060-evk/kernel/imxrt_userspace.c
+++ b/boards/arm/imxrt/imxrt1060-evk/kernel/imxrt_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/lc823450/lc823450-xgevk/kernel/lc823450_userspace.c b/boards/arm/lc823450/lc823450-xgevk/kernel/lc823450_userspace.c
index c6ce154..7eedb98 100644
--- a/boards/arm/lc823450/lc823450-xgevk/kernel/lc823450_userspace.c
+++ b/boards/arm/lc823450/lc823450-xgevk/kernel/lc823450_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/lpc17xx_40xx/lpc4088-devkit/kernel/lpc17_40_userspace.c b/boards/arm/lpc17xx_40xx/lpc4088-devkit/kernel/lpc17_40_userspace.c
index 4298a0f..2af4c85 100644
--- a/boards/arm/lpc17xx_40xx/lpc4088-devkit/kernel/lpc17_40_userspace.c
+++ b/boards/arm/lpc17xx_40xx/lpc4088-devkit/kernel/lpc17_40_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/lpc17xx_40xx/lpc4088-quickstart/kernel/lpc17_40_userspace.c b/boards/arm/lpc17xx_40xx/lpc4088-quickstart/kernel/lpc17_40_userspace.c
index 2af012c..4f5c33c 100644
--- a/boards/arm/lpc17xx_40xx/lpc4088-quickstart/kernel/lpc17_40_userspace.c
+++ b/boards/arm/lpc17xx_40xx/lpc4088-quickstart/kernel/lpc17_40_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/lpc17xx_40xx/open1788/kernel/lpc17_40_userspace.c b/boards/arm/lpc17xx_40xx/open1788/kernel/lpc17_40_userspace.c
index a09ab2d..09450ec 100644
--- a/boards/arm/lpc17xx_40xx/open1788/kernel/lpc17_40_userspace.c
+++ b/boards/arm/lpc17xx_40xx/open1788/kernel/lpc17_40_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/lpc17xx_40xx/pnev5180b/kernel/lpc17_40_userspace.c b/boards/arm/lpc17xx_40xx/pnev5180b/kernel/lpc17_40_userspace.c
index 21b4c18..8a8451c 100644
--- a/boards/arm/lpc17xx_40xx/pnev5180b/kernel/lpc17_40_userspace.c
+++ b/boards/arm/lpc17xx_40xx/pnev5180b/kernel/lpc17_40_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/lpc43xx/bambino-200e/kernel/lpc43_userspace.c b/boards/arm/lpc43xx/bambino-200e/kernel/lpc43_userspace.c
index 72600e0..e59fd01 100644
--- a/boards/arm/lpc43xx/bambino-200e/kernel/lpc43_userspace.c
+++ b/boards/arm/lpc43xx/bambino-200e/kernel/lpc43_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/sam34/sam3u-ek/kernel/sam_userspace.c b/boards/arm/sam34/sam3u-ek/kernel/sam_userspace.c
index 55fa413..da2e8d8 100644
--- a/boards/arm/sam34/sam3u-ek/kernel/sam_userspace.c
+++ b/boards/arm/sam34/sam3u-ek/kernel/sam_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/samv7/same70-xplained/kernel/sam_userspace.c b/boards/arm/samv7/same70-xplained/kernel/sam_userspace.c
index e77b252..2cd4003 100644
--- a/boards/arm/samv7/same70-xplained/kernel/sam_userspace.c
+++ b/boards/arm/samv7/same70-xplained/kernel/sam_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/samv7/samv71-xult/kernel/sam_userspace.c b/boards/arm/samv7/samv71-xult/kernel/sam_userspace.c
index a63cc7c..01be17d 100644
--- a/boards/arm/samv7/samv71-xult/kernel/sam_userspace.c
+++ b/boards/arm/samv7/samv71-xult/kernel/sam_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32/clicker2-stm32/kernel/stm32_userspace.c b/boards/arm/stm32/clicker2-stm32/kernel/stm32_userspace.c
index 791543d..2a2521c 100644
--- a/boards/arm/stm32/clicker2-stm32/kernel/stm32_userspace.c
+++ b/boards/arm/stm32/clicker2-stm32/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32/mikroe-stm32f4/kernel/stm32_userspace.c b/boards/arm/stm32/mikroe-stm32f4/kernel/stm32_userspace.c
index fb63a4a..25af38e 100644
--- a/boards/arm/stm32/mikroe-stm32f4/kernel/stm32_userspace.c
+++ b/boards/arm/stm32/mikroe-stm32f4/kernel/stm32_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32/olimex-stm32-p407/kernel/stm32_userspace.c b/boards/arm/stm32/olimex-stm32-p407/kernel/stm32_userspace.c
index a6d3a3f..efe32d8 100644
--- a/boards/arm/stm32/olimex-stm32-p407/kernel/stm32_userspace.c
+++ b/boards/arm/stm32/olimex-stm32-p407/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32/omnibusf4/kernel/stm32_userspace.c b/boards/arm/stm32/omnibusf4/kernel/stm32_userspace.c
index a3ffc8d..08c02ae 100644
--- a/boards/arm/stm32/omnibusf4/kernel/stm32_userspace.c
+++ b/boards/arm/stm32/omnibusf4/kernel/stm32_userspace.c
@@ -112,9 +112,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32/stm3240g-eval/kernel/stm32_userspace.c b/boards/arm/stm32/stm3240g-eval/kernel/stm32_userspace.c
index 2faeb54..4eafb03 100644
--- a/boards/arm/stm32/stm3240g-eval/kernel/stm32_userspace.c
+++ b/boards/arm/stm32/stm3240g-eval/kernel/stm32_userspace.c
@@ -94,9 +94,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32/stm32f4discovery/kernel/stm32_userspace.c b/boards/arm/stm32/stm32f4discovery/kernel/stm32_userspace.c
index 1ec35a3..ff60953 100644
--- a/boards/arm/stm32/stm32f4discovery/kernel/stm32_userspace.c
+++ b/boards/arm/stm32/stm32f4discovery/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32f7/stm32f746g-disco/kernel/stm32_userspace.c b/boards/arm/stm32f7/stm32f746g-disco/kernel/stm32_userspace.c
index 6061bb2..0ee9fa1 100644
--- a/boards/arm/stm32f7/stm32f746g-disco/kernel/stm32_userspace.c
+++ b/boards/arm/stm32f7/stm32f746g-disco/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32f7/stm32f769i-disco/kernel/stm32_userspace.c b/boards/arm/stm32f7/stm32f769i-disco/kernel/stm32_userspace.c
index 4a66cd7..f85466e 100644
--- a/boards/arm/stm32f7/stm32f769i-disco/kernel/stm32_userspace.c
+++ b/boards/arm/stm32f7/stm32f769i-disco/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32h7/nucleo-h743zi/kernel/stm32_userspace.c b/boards/arm/stm32h7/nucleo-h743zi/kernel/stm32_userspace.c
index d696786..54fb39e 100644
--- a/boards/arm/stm32h7/nucleo-h743zi/kernel/stm32_userspace.c
+++ b/boards/arm/stm32h7/nucleo-h743zi/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32h7/stm32h747i-disco/kernel/stm32_userspace.c b/boards/arm/stm32h7/stm32h747i-disco/kernel/stm32_userspace.c
index 84079d2..4dfafe8 100644
--- a/boards/arm/stm32h7/stm32h747i-disco/kernel/stm32_userspace.c
+++ b/boards/arm/stm32h7/stm32h747i-disco/kernel/stm32_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32l4/stm32l476vg-disco/kernel/stm32l4_userspace.c b/boards/arm/stm32l4/stm32l476vg-disco/kernel/stm32l4_userspace.c
index f274947..548d619 100644
--- a/boards/arm/stm32l4/stm32l476vg-disco/kernel/stm32l4_userspace.c
+++ b/boards/arm/stm32l4/stm32l476vg-disco/kernel/stm32l4_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/stm32l4/stm32l4r9ai-disco/kernel/stm32l4_userspace.c b/boards/arm/stm32l4/stm32l4r9ai-disco/kernel/stm32l4_userspace.c
index 802c1a3..ae474c6 100644
--- a/boards/arm/stm32l4/stm32l4r9ai-disco/kernel/stm32l4_userspace.c
+++ b/boards/arm/stm32l4/stm32l4r9ai-disco/kernel/stm32l4_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/arm/tiva/lm3s6965-ek/kernel/lm_userspace.c b/boards/arm/tiva/lm3s6965-ek/kernel/lm_userspace.c
index 6873dc1..1e6ae7b 100644
--- a/boards/arm/tiva/lm3s6965-ek/kernel/lm_userspace.c
+++ b/boards/arm/tiva/lm3s6965-ek/kernel/lm_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/boards/risc-v/k210/maix-bit/kernel/k210_userspace.c b/boards/risc-v/k210/maix-bit/kernel/k210_userspace.c
index 0933520..f7ff8e5 100644
--- a/boards/risc-v/k210/maix-bit/kernel/k210_userspace.c
+++ b/boards/risc-v/k210/maix-bit/kernel/k210_userspace.c
@@ -95,9 +95,6 @@ const struct userspace_s userspace __attribute__ ((section (".userspace"))) =
   /* Task/thread startup routines */
 
   .task_startup     = nxtask_startup,
-#ifndef CONFIG_DISABLE_PTHREAD
-  .pthread_startup  = pthread_startup,
-#endif
 
   /* Signal handler trampoline */
 
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index 9bf8dd5..d3ef3d6 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -569,9 +569,10 @@ void up_task_start(main_t taskentry, int argc, FAR char *argv[])
  *   pthread by calling this function.
  *
  *   Normally the a user-mode start-up stub will also execute before the
- *   pthread actually starts.  See libc/pthread/pthread_startup.c
+ *   pthread actually starts.  See libc/pthread/pthread_create.c
  *
  * Input Parameters:
+ *   startup - The user-space pthread startup function
  *   entrypt - The user-space address of the pthread entry point
  *   arg     - Standard argument for the pthread entry point
  *
@@ -584,7 +585,8 @@ void up_task_start(main_t taskentry, int argc, FAR char *argv[])
 
 #if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) && \
     !defined(CONFIG_DISABLE_PTHREAD)
-void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
+void up_pthread_start(pthread_trampoline_t startup,
+                      pthread_startroutine_t entrypt, pthread_addr_t arg);
        noreturn_function;
 #endif
 
diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h
index e92b207..8dc21d9 100644
--- a/include/nuttx/pthread.h
+++ b/include/nuttx/pthread.h
@@ -100,7 +100,7 @@
 #endif
 
 /****************************************************************************
- * Public Data
+ * Public Types
  ****************************************************************************/
 
 #ifdef __cplusplus
@@ -111,6 +111,10 @@ extern "C"
 #define EXTERN extern
 #endif
 
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
 /* Default pthread attributes.  This global can only be shared within the
  * kernel- or within the user- address space.
  */
@@ -121,6 +125,30 @@ EXTERN const pthread_attr_t g_default_pthread_attr;
  * Public Function Prototypes
  ****************************************************************************/
 
+/****************************************************************************
+ * Name:  nx_pthread_create
+ *
+ * Description:
+ *   This function creates and activates a new thread with specified
+ *   attributes.
+ *
+ * Input Parameters:
+ *    trampoline
+ *    thread
+ *    attr
+ *    start_routine
+ *    arg
+ *
+ * Returned Value:
+ *   OK (0) on success; a (non-negated) errno value on failure. The errno
+ *   variable is not set.
+ *
+ ****************************************************************************/
+
+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);
+
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 4f7f647..f40a2cd 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -770,6 +770,7 @@ struct pthread_tcb_s
 
   /* Task Management Fields *****************************************************/
 
+  pthread_trampoline_t trampoline;       /* User-space pthread startup function */
   pthread_addr_t arg;                    /* Startup argument                    */
   FAR void *joininfo;                    /* Detach-able info to support join    */
 };
diff --git a/include/nuttx/userspace.h b/include/nuttx/userspace.h
index 23cb033..4c9811a 100644
--- a/include/nuttx/userspace.h
+++ b/include/nuttx/userspace.h
@@ -100,13 +100,9 @@ struct userspace_s
 
   FAR struct mm_heap_s *us_heap;
 
-  /* Task/thread startup routines */
+  /* Task startup routine */
 
   CODE void (*task_startup)(main_t entrypt, int argc, FAR char *argv[]);
-#ifndef CONFIG_DISABLE_PTHREAD
-  CODE void (*pthread_startup)(pthread_startroutine_t entrypt,
-    pthread_addr_t arg);
-#endif
 
   /* Signal handler trampoline */
 
@@ -136,26 +132,6 @@ extern "C"
  * Public Function Prototypes
  ****************************************************************************/
 
-/****************************************************************************
- * Name: pthread_startup
- *
- * Description:
- *   This function is the user-space, pthread startup function.  It is called
- *   from up_pthread_start() in user-mode.
- *
- * Input Parameters:
- *   entrypt - The user-space address of the pthread entry point
- *   arg     - Standard argument for the pthread entry point
- *
- * Returned Value:
- *   None.  This function does not return.
- *
- ****************************************************************************/
-
-#if !defined(__KERNEL__) && !defined(CONFIG_DISABLE_PTHREAD)
-void pthread_startup(pthread_startroutine_t entrypt, pthread_addr_t arg);
-#endif
-
 #undef EXTERN
 #ifdef __cplusplus
 }
diff --git a/include/pthread.h b/include/pthread.h
index 1474f93..fb8a458 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -225,6 +225,8 @@ typedef FAR void *pthread_addr_t;
 typedef CODE pthread_addr_t (*pthread_startroutine_t)(pthread_addr_t);
 typedef pthread_startroutine_t pthread_func_t;
 
+typedef void (*pthread_trampoline_t)(pthread_startroutine_t, pthread_addr_t);
+
 struct pthread_attr_s
 {
   uint8_t priority;            /* Priority of the pthread */
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index ba5c04f..c3f3dea 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -305,7 +305,7 @@ SYSCALL_LOOKUP(telldir,                    1)
   SYSCALL_LOOKUP(pthread_cond_broadcast,   1)
   SYSCALL_LOOKUP(pthread_cond_signal,      1)
   SYSCALL_LOOKUP(pthread_cond_wait,        2)
-  SYSCALL_LOOKUP(pthread_create,           4)
+  SYSCALL_LOOKUP(nx_pthread_create,        5)
   SYSCALL_LOOKUP(pthread_detach,           1)
   SYSCALL_LOOKUP(pthread_exit,             1)
   SYSCALL_LOOKUP(pthread_getschedparam,    3)
diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs
index 3f62e4e..21497bf 100644
--- a/libs/libc/pthread/Make.defs
+++ b/libs/libc/pthread/Make.defs
@@ -38,19 +38,20 @@ CSRCS += pthread_barrierattr_init.c pthread_barrierattr_destroy.c
 CSRCS += pthread_barrierattr_getpshared.c pthread_barrierattr_setpshared.c
 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_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
 CSRCS += pthread_mutexattr_setprotocol.c pthread_mutexattr_getprotocol.c
 CSRCS += pthread_mutexattr_settype.c pthread_mutexattr_gettype.c
 CSRCS += pthread_mutexattr_setrobust.c pthread_mutexattr_getrobust.c
 CSRCS += pthread_mutex_lock.c
+CSRCS += pthread_once.c pthread_yield.c
+CSRCS += pthread_rwlock.c pthread_rwlock_rdlock.c pthread_rwlock_wrlock.c
 CSRCS += pthread_setcancelstate.c pthread_setcanceltype.c
 CSRCS += pthread_testcancel.c
-CSRCS += pthread_rwlock.c pthread_rwlock_rdlock.c pthread_rwlock_wrlock.c
-CSRCS += pthread_once.c pthread_yield.c
-CSRCS += pthread_get_stackaddr_np.c pthread_get_stacksize_np.c
-CSRCS += pthread_condattr_setclock.c pthread_condattr_getclock.c
 
 ifeq ($(CONFIG_SMP),y)
 CSRCS += pthread_attr_getaffinity.c pthread_attr_setaffinity.c
@@ -60,14 +61,9 @@ ifeq ($(CONFIG_PTHREAD_SPINLOCKS),y)
 CSRCS += pthread_spinlock.c
 endif
 
-ifeq ($(CONFIG_BUILD_PROTECTED),y)
-CSRCS += pthread_startup.c
-endif
-
 endif # CONFIG_DISABLE_PTHREAD
 
 # Add the pthread directory to the build
 
 DEPPATH += --dep-path pthread
 VPATH += :pthread
-
diff --git a/libs/libc/pthread/pthread_startup.c b/libs/libc/pthread/pthread_create.c
similarity index 57%
rename from libs/libc/pthread/pthread_startup.c
rename to libs/libc/pthread/pthread_create.c
index 53be032..e81c63e 100644
--- a/libs/libc/pthread/pthread_startup.c
+++ b/libs/libc/pthread/pthread_create.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * libs/libc/pthread/pthread_startup.c
+ * libs/libc/pthread/pthread_create.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,70 +24,68 @@
 
 #include <nuttx/config.h>
 
-#include <pthread.h>
-#include <assert.h>
+#include <debug.h>
 
-#include <nuttx/userspace.h>
-
-#if !defined(CONFIG_BUILD_FLAT) && !defined(__KERNEL__)
-
-/****************************************************************************
- * Pre-processor Definitions
- ****************************************************************************/
+#include <nuttx/pthread.h>
 
 /****************************************************************************
- * Private Type Declarations
+ * Private Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Public Data
+ * Name: pthread_startup
+ *
+ * Description:
+ *   This function is the user space pthread startup function.  Its purpose
+ *   is to catch the return from the pthread main function so that
+ *   pthread_exit() can be called from user space
+ *
+ * Input Parameters:
+ *   entry - The user-space address of the pthread entry point
+ *   arg   - Standard argument for the pthread entry point
+ *
+ * Returned Value:
+ *   None.  This function does not return.
+ *
  ****************************************************************************/
 
-/****************************************************************************
- * Private Data
- ****************************************************************************/
+static void pthread_startup(pthread_startroutine_t entry,
+                            pthread_addr_t arg)
+{
+  DEBUGASSERT(entry != NULL);
 
-/****************************************************************************
- * Private Function Prototypes
- ****************************************************************************/
+  /* Pass control to the thread entry point.  Handle any returned value. */
 
-/****************************************************************************
- * Private Functions
- ****************************************************************************/
+  pthread_exit(entry(arg));
+}
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pthread_startup
+ * Name:  pthread_create
  *
  * Description:
- *   This function is the user-space, pthread startup function.  It is called
- *   from up_pthread_start() in user-mode.
+ *   This function creates and activates a new thread with specified
+ *   attributes.  It is simply a wrapper around the nx_pthread_create system
+ *   call.
  *
  * Input Parameters:
- *   entrypt - The user-space address of the pthread entry point
- *   arg     - Standard argument for the pthread entry point
+ *    thread
+ *    attr
+ *    pthread_entry
+ *    arg
  *
  * Returned Value:
- *   None.  This function does not return.
+ *   OK (0) on success; a (non-negated) errno value on failure. The errno
+ *   variable is not set.
  *
  ****************************************************************************/
 
-void pthread_startup(pthread_startroutine_t entrypt, pthread_addr_t arg)
+int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
+                   pthread_startroutine_t pthread_entry, pthread_addr_t arg)
 {
-  pthread_addr_t exit_status;
-
-  DEBUGASSERT(entrypt);
-
-  /* Pass control to the thread entry point. */
-
-  exit_status = entrypt(arg);
-
-  /* The pthread has returned */
-
-  pthread_exit(exit_status);
+  return nx_pthread_create(pthread_startup, thread, attr, pthread_entry,
+                           arg);
 }
-
-#endif /* !CONFIG_BUILD_FLAT && !__KERNEL__ */
diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c
index 1c4af3b..22cd008 100644
--- a/sched/pthread/pthread_create.c
+++ b/sched/pthread/pthread_create.c
@@ -64,19 +64,20 @@ const pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER;
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pthread_argsetup
+ * Name: pthread_tcb_setup
  *
  * Description:
- *   This functions sets up parameters in the Task Control Block (TCB) in
+ *   This function sets up parameters in the Task Control Block (TCB) in
  *   preparation for starting a new thread.
  *
- *   pthread_argsetup() is called from nxtask_init() and nxtask_start() to
+ *   pthread_tcb_setup() is called from nxtask_init() and nxtask_start() to
  *   create a new task (with arguments cloned via strdup) or pthread_create()
  *   which has one argument passed by value (distinguished by the pthread
  *   boolean argument).
  *
  * Input Parameters:
  *   tcb        - Address of the new task's TCB
+ *   trampoline - User space pthread startup function
  *   arg        - The argument to provide to the pthread on startup.
  *
  * Returned Value:
@@ -84,21 +85,23 @@ const pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER;
  *
  ****************************************************************************/
 
-static inline void pthread_argsetup(FAR struct pthread_tcb_s *tcb,
-                                    pthread_addr_t arg)
+static inline void pthread_tcb_setup(FAR struct pthread_tcb_s *ptcb,
+                                     pthread_trampoline_t trampoline,
+                                     pthread_addr_t arg)
 {
 #if CONFIG_TASK_NAME_SIZE > 0
   /* Copy the pthread name into the TCB */
 
-  snprintf(tcb->cmn.name, CONFIG_TASK_NAME_SIZE,
-           "pt-%p", tcb->cmn.entry.pthread);
+  snprintf(ptcb->cmn.name, CONFIG_TASK_NAME_SIZE,
+           "pt-%p", ptcb->cmn.entry.pthread);
 #endif /* CONFIG_TASK_NAME_SIZE */
 
   /* For pthreads, args are strictly pass-by-value; that actual
    * type wrapped by pthread_addr_t is unknown.
    */
 
-  tcb->arg = arg;
+  ptcb->trampoline = trampoline;
+  ptcb->arg        = arg;
 }
 
 /****************************************************************************
@@ -150,9 +153,8 @@ static void pthread_start(void)
   FAR struct pthread_tcb_s *ptcb = (FAR struct pthread_tcb_s *)this_task();
   FAR struct task_group_s *group = ptcb->cmn.group;
   FAR struct join_s *pjoin = (FAR struct join_s *)ptcb->joininfo;
-  pthread_addr_t exit_status;
 
-  DEBUGASSERT(group && pjoin);
+  DEBUGASSERT(group != NULL && pjoin != NULL);
 
   /* Successfully spawned, add the pjoin to our data set. */
 
@@ -180,16 +182,18 @@ static void pthread_start(void)
    * to switch to user-mode before calling into the pthread.
    */
 
+  DEBUGASSERT(ptcb->trampoline != NULL && ptcb->cmn.entry.pthread != NULL);
+
 #ifdef CONFIG_BUILD_FLAT
-  exit_status = (*ptcb->cmn.entry.pthread)(ptcb->arg);
+  ptcb->trampoline(ptcb->cmn.entry.pthread, ptcb->arg);
 #else
-  up_pthread_start(ptcb->cmn.entry.pthread, ptcb->arg);
-  exit_status = NULL;
+  up_pthread_start(ptcb->trampoline, ptcb->cmn.entry.pthread, ptcb->arg);
 #endif
 
-  /* The thread has returned (should never happen in the kernel mode case) */
+  /* The thread has returned (should never happen) */
 
-  pthread_exit(exit_status);
+  DEBUGPANIC();
+  pthread_exit(NULL);
 }
 
 /****************************************************************************
@@ -197,13 +201,14 @@ static void pthread_start(void)
  ****************************************************************************/
 
 /****************************************************************************
- * Name:  pthread_create
+ * Name:  nx_pthread_create
  *
  * Description:
- *   This function creates and activates a new thread with a specified
+ *   This function creates and activates a new thread with specified
  *   attributes.
  *
  * Input Parameters:
+ *    trampoline
  *    thread
  *    attr
  *    start_routine
@@ -215,8 +220,9 @@ static void pthread_start(void)
  *
  ****************************************************************************/
 
-int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
-                   pthread_startroutine_t start_routine, pthread_addr_t arg)
+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)
 {
   FAR struct pthread_tcb_s *ptcb;
   FAR struct tls_info_s *info;
@@ -228,6 +234,8 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
   int ret;
   bool group_joined = false;
 
+  DEBUGASSERT(trampoline != NULL);
+
   /* If attributes were not supplied, use the default attributes */
 
   if (!attr)
@@ -415,7 +423,7 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
   /* Initialize the task control block */
 
   ret = pthread_setup_scheduler(ptcb, param.sched_priority, pthread_start,
-                                start_routine);
+                                entry);
   if (ret != OK)
     {
       errcode = EBUSY;
@@ -440,7 +448,7 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
    * passed by value
    */
 
-  pthread_argsetup(ptcb, arg);
+  pthread_tcb_setup(ptcb, trampoline, arg);
 
   /* Join the parent's task group */
 
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index c8b6807..a9c4658 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -66,6 +66,7 @@
 "munmap","sys/mman.h","defined(CONFIG_FS_RAMMAP)","int","FAR void *","size_t"
 "nx_mkfifo","nuttx/fs/fs.h","defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0","int","FAR const char *","mode_t","size_t"
 "nx_pipe","nuttx/fs/fs.h","defined(CONFIG_PIPES) && CONFIG_DEV_PIPE_SIZE > 0","int","int [2]|FAR int *","size_t","int"
+"nx_pthread_create","nuttx/pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_trampoline_t","FAR pthread_t *","FAR const pthread_attr_t *","pthread_startroutine_t","pthread_addr_t"
 "nx_task_spawn","nuttx/spawn.h","defined(CONFIG_LIB_SYSCALL) && !defined(CONFIG_BUILD_KERNEL)","int","FAR const struct spawn_syscall_parms_s *"
 "nx_vsyslog","nuttx/syslog/syslog.h","","int","int","FAR const IPTR char *","FAR va_list *"
 "nxsched_get_stackinfo","nuttx/sched.h","","int","pid_t","FAR struct stackinfo_s *"
@@ -88,7 +89,6 @@
 "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_create","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_t *","FAR const pthread_attr_t *","pthread_startroutine_t","pthread_addr_t"
 "pthread_detach","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
 "pthread_exit","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*"

[incubator-nuttx] 04/09: libc: Move pthread_cleanup to user space

Posted by gn...@apache.org.
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 f1a92e9cbb50813f7c92eb14a9007b664a737939
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Fri Apr 30 18:12:09 2021 +0800

    libc: Move pthread_cleanup to user space
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 include/nuttx/pthread.h                        |  15 +--
 include/nuttx/sched.h                          |  11 ---
 include/nuttx/tls.h                            |  11 +++
 include/sys/syscall_lookup.h                   |   5 -
 libs/libc/pthread/Make.defs                    |   4 +
 {sched => libs/libc}/pthread/pthread_cleanup.c | 127 ++++++-------------------
 libs/libc/pthread/pthread_exit.c               |  14 +--
 sched/pthread/Make.defs                        |   4 -
 sched/pthread/pthread.h                        |   4 -
 sched/pthread/pthread_cancel.c                 |  13 ---
 sched/task/exit.c                              |   6 --
 syscall/syscall.csv                            |   3 -
 12 files changed, 55 insertions(+), 162 deletions(-)

diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h
index 477cf2c..aa21cd6 100644
--- a/include/nuttx/pthread.h
+++ b/include/nuttx/pthread.h
@@ -168,21 +168,24 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
 void nx_pthread_exit(FAR void *exit_value) noreturn_function;
 
 /****************************************************************************
- * Name: pthread_cleanup_poplist
+ * Name: pthread_cleanup_popall
  *
  * Description:
- *   The pthread_cleanup_poplist() is function that will pop all clean-up
- *   functions.  This function is only called from within the pthread_exit()
+ *   The pthread_cleanup_popall() is an internal function that will pop and
+ *   execute all clean-up functions.  This function is only called from
+ *   within the pthread_exit() and pthread_cancellation() logic
  *
  * Input Parameters:
- *   cleanup - The array of struct pthread_cleanup_s to fetch callbacks
+ *   tcb - The TCB of the pthread that is exiting or being canceled.
  *
  * Returned Value:
- *   The index to the next available entry at the top of the stack
+ *   None
  *
  ****************************************************************************/
 
-int pthread_cleanup_poplist(FAR struct pthread_cleanup_s *cleanup);
+#ifdef CONFIG_PTHREAD_CLEANUP
+void pthread_cleanup_popall(void);
+#endif
 
 #undef EXTERN
 #ifdef __cplusplus
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index f40a2cd..95c7ad7 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -690,17 +690,6 @@ struct tcb_s
   FAR struct pthread_mutex_s *mhead;     /* List of mutexes held by thread      */
 #endif
 
-  /* Clean-up stack *************************************************************/
-
-#ifdef CONFIG_PTHREAD_CLEANUP
-  /* tos   - The index to the next available entry at the top of the stack.
-   * stack - The pre-allocated clean-up stack memory.
-   */
-
-  uint8_t tos;
-  struct pthread_cleanup_s stack[CONFIG_PTHREAD_CLEANUP_STACKSIZE];
-#endif
-
   /* Pre-emption monitor support ************************************************/
 
 #ifdef CONFIG_SCHED_CRITMONITOR
diff --git a/include/nuttx/tls.h b/include/nuttx/tls.h
index 79f0e78..c370abc 100644
--- a/include/nuttx/tls.h
+++ b/include/nuttx/tls.h
@@ -27,6 +27,7 @@
 
 #include <nuttx/config.h>
 
+#include <nuttx/sched.h>
 #include <nuttx/lib/getopt.h>
 
 /****************************************************************************
@@ -98,6 +99,16 @@ struct tls_info_s
 #if CONFIG_TLS_NELEM > 0
   uintptr_t tl_elem[CONFIG_TLS_NELEM]; /* TLS elements */
 #endif
+
+#ifdef CONFIG_PTHREAD_CLEANUP
+  /* tos   - The index to the next available entry at the top of the stack.
+   * stack - The pre-allocated clean-up stack memory.
+   */
+
+  uint8_t tos;
+  struct pthread_cleanup_s stack[CONFIG_PTHREAD_CLEANUP_STACKSIZE];
+#endif
+
   int tl_errno;                        /* Per-thread error number */
 };
 
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index d59467a..7781f09 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -327,11 +327,6 @@ SYSCALL_LOOKUP(telldir,                    1)
   SYSCALL_LOOKUP(pthread_cond_clockwait,   4)
   SYSCALL_LOOKUP(pthread_kill,             2)
   SYSCALL_LOOKUP(pthread_sigmask,          3)
-#ifdef CONFIG_PTHREAD_CLEANUP
-  SYSCALL_LOOKUP(pthread_cleanup_push,     2)
-  SYSCALL_LOOKUP(pthread_cleanup_pop,      1)
-  SYSCALL_LOOKUP(pthread_cleanup_poplist,  1)
-#endif
 #endif
 
 /* The following are defined only if message queues are enabled */
diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs
index bbdb75b..b4ba995 100644
--- a/libs/libc/pthread/Make.defs
+++ b/libs/libc/pthread/Make.defs
@@ -61,6 +61,10 @@ ifeq ($(CONFIG_PTHREAD_SPINLOCKS),y)
 CSRCS += pthread_spinlock.c
 endif
 
+ifeq ($(CONFIG_PTHREAD_CLEANUP),y)
+CSRCS += pthread_cleanup.c
+endif
+
 endif # CONFIG_DISABLE_PTHREAD
 
 # Add the pthread directory to the build
diff --git a/sched/pthread/pthread_cleanup.c b/libs/libc/pthread/pthread_cleanup.c
similarity index 62%
rename from sched/pthread/pthread_cleanup.c
rename to libs/libc/pthread/pthread_cleanup.c
index 8c5dbaf..0c2c848 100644
--- a/sched/pthread/pthread_cleanup.c
+++ b/libs/libc/pthread/pthread_cleanup.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * sched/pthread/pthread_cleanup.c
+ * libs/libc/pthread/pthread_cleanup.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -27,10 +27,11 @@
 #include <pthread.h>
 #include <sched.h>
 
+#include <nuttx/arch.h>
 #include <nuttx/sched.h>
-
-#include "sched/sched.h"
-#include "pthread/pthread.h"
+#include <nuttx/tls.h>
+#include <nuttx/pthread.h>
+#include <arch/tls.h>
 
 #ifdef CONFIG_PTHREAD_CLEANUP
 
@@ -39,7 +40,7 @@
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pthread_cleanup_pop_tcb
+ * Name: pthread_cleanup_pop_tls
  *
  * Description:
  *   The pthread_cleanup_pop_tcb() function will remove the routine at the
@@ -57,15 +58,15 @@
  *
  ****************************************************************************/
 
-static void pthread_cleanup_pop_tcb(FAR struct tcb_s *tcb, int execute)
+static void pthread_cleanup_pop_tls(FAR struct tls_info_s *tls, int execute)
 {
-  if (tcb->tos > 0)
+  if (tls->tos > 0)
     {
       unsigned int ndx;
 
       /* Get the index to the last cleaner function pushed onto the stack */
 
-      ndx = tcb->tos - 1;
+      ndx = tls->tos - 1;
       DEBUGASSERT(ndx >= 0 && ndx < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
 
       /* Should we execute the cleanup routine at the top of the stack? */
@@ -81,11 +82,11 @@ static void pthread_cleanup_pop_tcb(FAR struct tcb_s *tcb, int execute)
            * mode!  See also on_exit() and atexit() callbacks.
            */
 
-          cb  = &tcb->stack[ndx];
+          cb  = &tls->stack[ndx];
           cb->pc_cleaner(cb->pc_arg);
         }
 
-      tcb->tos = ndx;
+      tls->tos = ndx;
     }
 }
 
@@ -123,9 +124,9 @@ static void pthread_cleanup_pop_tcb(FAR struct tcb_s *tcb, int execute)
 
 void pthread_cleanup_pop(int execute)
 {
-  FAR struct tcb_s *tcb = this_task();
+  FAR struct tls_info_s *tls = up_tls_info();
 
-  DEBUGASSERT(tcb != NULL);
+  DEBUGASSERT(tls != NULL);
 
   /* sched_lock() should provide sufficient protection.  We only need to
    * have this TCB stationary; the pthread cleanup stack should never be
@@ -133,20 +134,16 @@ void pthread_cleanup_pop(int execute)
    */
 
   sched_lock();
-  if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
-    {
-      pthread_cleanup_pop_tcb(tcb, execute);
-    }
-
+  pthread_cleanup_pop_tls(tls, execute);
   sched_unlock();
 }
 
 void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg)
 {
-  FAR struct tcb_s *tcb = this_task();
+  FAR struct tls_info_s *tls = up_tls_info();
 
-  DEBUGASSERT(tcb != NULL);
-  DEBUGASSERT(tcb->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
+  DEBUGASSERT(tls != NULL);
+  DEBUGASSERT(tls->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
 
   /* sched_lock() should provide sufficient protection.  We only need to
    * have this TCB stationary; the pthread cleanup stack should never be
@@ -154,14 +151,13 @@ void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg)
    */
 
   sched_lock();
-  if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL &&
-      tcb->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE)
+  if (tls->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE)
     {
-      unsigned int ndx = tcb->tos;
+      unsigned int ndx = tls->tos;
 
-      tcb->tos++;
-      tcb->stack[ndx].pc_cleaner = routine;
-      tcb->stack[ndx].pc_arg = arg;
+      tls->tos++;
+      tls->stack[ndx].pc_cleaner = routine;
+      tls->stack[ndx].pc_arg = arg;
     }
 
   sched_unlock();
@@ -176,89 +172,26 @@ void pthread_cleanup_push(pthread_cleanup_t routine, FAR void *arg)
  *   within the pthread_exit() and pthread_cancellation() logic
  *
  * Input Parameters:
- *   tcb - The TCB of the pthread that is exiting or being canceled.
- *
- * Returned Value:
  *   None
  *
- ****************************************************************************/
-
-void pthread_cleanup_popall(FAR struct tcb_s *tcb)
-{
-  DEBUGASSERT(tcb != NULL);
-
-  /* Kernel threads do not support pthread APIs */
-
-  if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
-    {
-      /* Pop and execute each cleanup routine/
-       *
-       * 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)
-        {
-          pthread_cleanup_pop_tcb(tcb, 1);
-        }
-
-      sched_unlock();
-    }
-}
-
-/****************************************************************************
- * 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
+ *   None
  *
  ****************************************************************************/
 
-int pthread_cleanup_poplist(FAR struct pthread_cleanup_s *cleanup)
+void pthread_cleanup_popall(void)
 {
-  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);
+  FAR struct tls_info_s *tls = up_tls_info();
 
-  tos = tcb->tos;
+  DEBUGASSERT(tls != NULL);
 
-  /* Kernel threads do not support pthread APIs */
-
-  if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
+  sched_lock();
+  while (tls->tos > 0)
     {
-      /* 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();
+      pthread_cleanup_pop_tls(tls, 1);
     }
 
-  return tos;
+  sched_unlock();
 }
 
 #endif /* CONFIG_PTHREAD_CLEANUP */
diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c
index 71271d9..740a325 100644
--- a/libs/libc/pthread/pthread_exit.c
+++ b/libs/libc/pthread/pthread_exit.c
@@ -52,19 +52,7 @@
 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();
+  pthread_cleanup_popall();
 #endif
 
   nx_pthread_exit(exit_value);
diff --git a/sched/pthread/Make.defs b/sched/pthread/Make.defs
index 2a3b58d..681fe3e 100644
--- a/sched/pthread/Make.defs
+++ b/sched/pthread/Make.defs
@@ -38,10 +38,6 @@ ifeq ($(CONFIG_SMP),y)
 CSRCS += pthread_setaffinity.c pthread_getaffinity.c
 endif
 
-ifeq ($(CONFIG_PTHREAD_CLEANUP),y)
-CSRCS += pthread_cleanup.c
-endif
-
 # Include pthread build support
 
 DEPPATH += --dep-path pthread
diff --git a/sched/pthread/pthread.h b/sched/pthread/pthread.h
index a2ca182..db04ba2 100644
--- a/sched/pthread/pthread.h
+++ b/sched/pthread/pthread.h
@@ -81,10 +81,6 @@ struct task_group_s;  /* Forward reference */
 int pthread_setup_scheduler(FAR struct pthread_tcb_s *tcb, int priority,
                             start_t start, pthread_startroutine_t entry);
 
-#ifdef CONFIG_PTHREAD_CLEANUP
-void pthread_cleanup_popall(FAR struct tcb_s *tcb);
-#endif
-
 int pthread_completejoin(pid_t pid, FAR void *exit_value);
 void pthread_destroyjoin(FAR struct task_group_s *group,
                          FAR struct join_s *pjoin);
diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c
index dcc58f6..d2dc2f3 100644
--- a/sched/pthread/pthread_cancel.c
+++ b/sched/pthread/pthread_cancel.c
@@ -85,19 +85,6 @@ int pthread_cancel(pthread_t thread)
       pthread_exit(PTHREAD_CANCELED);
     }
 
-#ifdef CONFIG_PTHREAD_CLEANUP
-  /* Perform any stack pthread clean-up callbacks.
-   *
-   * REVISIT: In this case, the clean-up callback will execute on the
-   * thread of the caller of pthread cancel, not on the thread of
-   * the thread-to-be-canceled.  This is a problem when deferred
-   * cancellation is not supported because, for example, the clean-up
-   * function will be unable to unlock its own mutexes.
-   */
-
-  pthread_cleanup_popall(tcb);
-#endif
-
   /* Complete pending join operations */
 
   pthread_completejoin((pid_t)thread, PTHREAD_CANCELED);
diff --git a/sched/task/exit.c b/sched/task/exit.c
index 16fbcef..97d0b7a 100644
--- a/sched/task/exit.c
+++ b/sched/task/exit.c
@@ -87,12 +87,6 @@ void exit(int status)
   group_kill_children(tcb);
 #endif
 
-#ifdef CONFIG_PTHREAD_CLEANUP
-  /* Perform any stack pthread clean-up callbacks */
-
-  pthread_cleanup_popall(tcb);
-#endif
-
 #if !defined(CONFIG_DISABLE_PTHREAD) && !defined(CONFIG_PTHREAD_MUTEX_UNSAFE)
   /* Recover any mutexes still held by the canceled thread */
 
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index e88cf9e..8502cc0 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -83,9 +83,6 @@
 "pread","unistd.h","","ssize_t","int","FAR void *","size_t","off_t"
 "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 *"

[incubator-nuttx] 06/09: libc: Call pthread_exit in user-space by up_pthread_exit

Posted by gn...@apache.org.
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 f4a0b7aedd01ac3f39a88d62dbafaf367ae399f2
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Sat May 8 18:20:02 2021 +0800

    libc: Call pthread_exit in user-space by up_pthread_exit
    
    Drop to user-space in kernel/protected build with up_pthread_exit,
    now all pthread_cleanup functions executed in user mode.
    
    * A new syscall SYS_pthread_exit added
    * A new tcb flag TCB_FLAG_CANCEL_DOING added
    * up_pthread_exit implemented for riscv/arm arch
    
    Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
 arch/arm/src/a1x/Make.defs                         |  1 +
 arch/arm/src/am335x/Make.defs                      |  1 +
 arch/arm/src/armv6-m/arm_svcall.c                  | 43 +++++++++++++++++---
 arch/arm/src/armv6-m/svcall.h                      |  6 +--
 arch/arm/src/armv7-a/arm_syscall.c                 | 43 +++++++++++++-------
 arch/arm/src/armv7-a/svcall.h                      | 11 ++++-
 arch/arm/src/armv7-m/arm_svcall.c                  | 41 ++++++++++++++++---
 arch/arm/src/armv7-m/svcall.h                      | 13 ++++--
 arch/arm/src/armv7-r/arm_syscall.c                 | 47 ++++++++++++++--------
 arch/arm/src/armv8-m/arm_svcall.c                  | 43 +++++++++++++++++---
 .../arm/src/common/arm_pthread_exit.c              | 34 ++++++++--------
 arch/arm/src/cxd56xx/Make.defs                     |  1 +
 arch/arm/src/efm32/Make.defs                       |  1 +
 arch/arm/src/eoss3/Make.defs                       |  1 +
 arch/arm/src/imx6/Make.defs                        |  1 +
 arch/arm/src/imxrt/Make.defs                       |  1 +
 arch/arm/src/kinetis/Make.defs                     |  1 +
 arch/arm/src/kl/Make.defs                          |  1 +
 arch/arm/src/lc823450/Make.defs                    |  1 +
 arch/arm/src/lpc17xx_40xx/Make.defs                |  1 +
 arch/arm/src/lpc43xx/Make.defs                     |  1 +
 arch/arm/src/lpc54xx/Make.defs                     |  1 +
 arch/arm/src/max326xx/Make.defs                    |  1 +
 arch/arm/src/nrf52/Make.defs                       |  1 +
 arch/arm/src/nuc1xx/Make.defs                      |  1 +
 arch/arm/src/rp2040/Make.defs                      |  1 +
 arch/arm/src/s32k1xx/Make.defs                     |  1 +
 arch/arm/src/sam34/Make.defs                       |  1 +
 arch/arm/src/sama5/Make.defs                       |  1 +
 arch/arm/src/samd2l2/Make.defs                     |  1 +
 arch/arm/src/samd5e5/Make.defs                     |  1 +
 arch/arm/src/samv7/Make.defs                       |  1 +
 arch/arm/src/stm32/Make.defs                       |  2 +-
 arch/arm/src/stm32f0l0g0/Make.defs                 |  1 +
 arch/arm/src/stm32f7/Make.defs                     |  1 +
 arch/arm/src/stm32h7/Make.defs                     |  1 +
 arch/arm/src/stm32l4/Make.defs                     |  1 +
 arch/arm/src/stm32l5/Make.defs                     |  1 +
 arch/arm/src/tiva/Make.defs                        |  1 +
 arch/arm/src/tms570/Make.defs                      |  1 +
 arch/arm/src/xmc4/Make.defs                        |  1 +
 arch/or1k/src/common/up_pthread_start.c            |  2 +-
 arch/risc-v/src/c906/Make.defs                     |  1 +
 .../risc-v/src/common/riscv_pthread_exit.c         | 34 ++++++++--------
 arch/risc-v/src/k210/Make.defs                     |  3 +-
 arch/risc-v/src/rv64gc/riscv_swint.c               | 45 +++++++++++++++++----
 arch/risc-v/src/rv64gc/svcall.h                    | 15 +++++--
 .../arm/imxrt/imxrt1050-evk/configs/knsh/defconfig |  2 +-
 .../arm/imxrt/imxrt1060-evk/configs/knsh/defconfig |  2 +-
 .../arm/imxrt/imxrt1064-evk/configs/knsh/defconfig |  2 +-
 .../lc823450/lc823450-xgevk/configs/knsh/defconfig |  2 +-
 .../lc823450-xgevk/configs/kostest/defconfig       |  2 +-
 .../lc823450-xgevk/configs/krndis/defconfig        |  2 +-
 .../lpc4088-devkit/configs/knsh/defconfig          |  2 +-
 .../lpc4088-quickstart/configs/knsh/defconfig      |  2 +-
 .../lpc17xx_40xx/open1788/configs/knsh/defconfig   |  2 +-
 .../open1788/configs/knxterm/defconfig             |  2 +-
 .../lpc17xx_40xx/pnev5180b/configs/knsh/defconfig  |  2 +-
 .../lpc43xx/bambino-200e/configs/knsh/defconfig    |  2 +-
 boards/arm/sam34/sam3u-ek/configs/knsh/defconfig   |  2 +-
 boards/arm/sama5/sama5d4-ek/configs/knsh/defconfig |  2 +-
 .../arm/samv7/samv71-xult/configs/knsh/defconfig   |  2 +-
 .../stm32/clicker2-stm32/configs/knsh/defconfig    |  2 +-
 .../stm32/mikroe-stm32f4/configs/kostest/defconfig |  2 +-
 .../stm32/olimex-stm32-p407/configs/kelf/defconfig |  2 +-
 .../olimex-stm32-p407/configs/kmodule/defconfig    |  2 +-
 .../stm32/olimex-stm32-p407/configs/knsh/defconfig |  2 +-
 .../stm32/stm3240g-eval/configs/knxwm/defconfig    |  2 +-
 .../stm32f4discovery/configs/kostest/defconfig     |  2 +-
 .../stm32l476vg-disco/configs/knsh/defconfig       |  2 +-
 .../stm32l4r9ai-disco/configs/knsh/defconfig       |  2 +-
 .../lm3s6965-ek/configs/qemu-protected/defconfig   |  2 +-
 .../risc-v/c906/smartl-c906/configs/knsh/defconfig |  2 +-
 boards/risc-v/k210/maix-bit/configs/knsh/defconfig |  2 +-
 .../k210/maix-bit/configs/knsh_smp/defconfig       |  2 +-
 .../risc-v/k210/maix-bit/configs/kostest/defconfig |  2 +-
 include/nuttx/arch.h                               | 23 ++++++++++-
 include/nuttx/pthread.h                            |  6 +--
 include/nuttx/sched.h                              | 12 +++---
 include/pthread.h                                  |  2 +
 include/sys/syscall_lookup.h                       |  2 +-
 libs/libc/pthread/pthread_create.c                 |  2 +-
 libs/libc/pthread/pthread_exit.c                   |  2 +-
 sched/pthread/pthread_cancel.c                     | 10 +++++
 sched/pthread/pthread_create.c                     | 19 +++++++--
 sched/signal/sig_default.c                         | 10 ++++-
 sched/task/task_cancelpt.c                         | 17 ++++++++
 sched/task/task_setcancelstate.c                   |  8 ++++
 sched/task/task_setcanceltype.c                    | 10 ++++-
 syscall/syscall.csv                                |  2 +-
 90 files changed, 446 insertions(+), 151 deletions(-)

diff --git a/arch/arm/src/a1x/Make.defs b/arch/arm/src/a1x/Make.defs
index 8cb5a8f..a547ebe 100644
--- a/arch/arm/src/a1x/Make.defs
+++ b/arch/arm/src/a1x/Make.defs
@@ -74,6 +74,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_KERNEL),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c arm_signal_dispatch.c
+CMN_CSRCS += arm_pthread_exit.c
 endif
 
 ifeq ($(CONFIG_ARCH_ADDRENV),y)
diff --git a/arch/arm/src/am335x/Make.defs b/arch/arm/src/am335x/Make.defs
index b8a7ed5..df6f7fe 100644
--- a/arch/arm/src/am335x/Make.defs
+++ b/arch/arm/src/am335x/Make.defs
@@ -70,6 +70,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_KERNEL),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c arm_signal_dispatch.c
+CMN_CSRCS += arm_pthread_exit.c
 endif
 
 ifeq ($(CONFIG_ARCH_ADDRENV),y)
diff --git a/arch/arm/src/armv6-m/arm_svcall.c b/arch/arm/src/armv6-m/arm_svcall.c
index 0339ccc..6517b4c 100644
--- a/arch/arm/src/armv6-m/arm_svcall.c
+++ b/arch/arm/src/armv6-m/arm_svcall.c
@@ -298,26 +298,28 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
         break;
 #endif
 
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
+
       /* R0=SYS_pthread_start:  This a user pthread start
        *
-       *   void up_pthread_start(pthread_startroutine_t entrypt,
-       *                         pthread_addr_t arg) noreturn_function;
+       *   void up_pthread_start(pthread_trampoline_t startup,
+       *          pthread_startroutine_t entrypt, pthread_addr_t arg)
        *
        * At this point, the following values are saved in context:
        *
        *   R0 = SYS_pthread_start
-       *   R1 = entrypt
-       *   R2 = arg
+       *   R1 = startup
+       *   R2 = entrypt
+       *   R3 = arg
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
            * unprivileged mode.
            */
 
-          regs[REG_PC]         = (uint32_t)regs[REG_R1]; /* startup */
+          regs[REG_PC]         = (uint32_t)regs[REG_R1] & ~1;  /* startup */
           regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
 
           /* Change the parameter ordering to match the expectation of the
@@ -328,6 +330,35 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
           regs[REG_R1]         = regs[REG_R3]; /* arg */
         }
         break;
+
+      /* R0=SYS_pthread_exit:  This pthread_exit call in user-space
+       *
+       *   void up_pthread_exit(pthread_exitroutine_t exit,
+       *                        FAR void *exit_value)
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_pthread_exit
+       *   R1 = pthread_exit trampoline routine
+       *   R2 = exit_value
+       */
+
+      case SYS_pthread_exit:
+        {
+          /* Set up to return to the user-space pthread start-up function in
+           * unprivileged mode.
+           */
+
+          regs[REG_PC]         = (uint32_t)regs[REG_R1] & ~1;  /* startup */
+          regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
+
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
+           */
+
+          regs[REG_R0]         = regs[REG_R2]; /* exit_value */
+        }
+        break;
 #endif
 
       /* R0=SYS_signal_handler:  This a user signal handler callback
diff --git a/arch/arm/src/armv6-m/svcall.h b/arch/arm/src/armv6-m/svcall.h
index a790f58..0b0f8d7 100644
--- a/arch/arm/src/armv6-m/svcall.h
+++ b/arch/arm/src/armv6-m/svcall.h
@@ -45,9 +45,9 @@
 #ifdef CONFIG_LIB_SYSCALL
 #  ifdef CONFIG_BUILD_PROTECTED
 #    ifndef CONFIG_SYS_RESERVED
-#      error "CONFIG_SYS_RESERVED must be defined to have the value 8"
-#    elif CONFIG_SYS_RESERVED != 8
-#      error "CONFIG_SYS_RESERVED must have the value 8"
+#      error "CONFIG_SYS_RESERVED must be defined to have the value 9"
+#    elif CONFIG_SYS_RESERVED != 9
+#      error "CONFIG_SYS_RESERVED must have the value 9"
 #    endif
 #  else
 #    ifndef CONFIG_SYS_RESERVED
diff --git a/arch/arm/src/armv7-a/arm_syscall.c b/arch/arm/src/armv7-a/arm_syscall.c
index 985dc63..999d1b1 100644
--- a/arch/arm/src/armv7-a/arm_syscall.c
+++ b/arch/arm/src/armv7-a/arm_syscall.c
@@ -278,30 +278,23 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
 #endif
 
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
+
       /* R0=SYS_pthread_start:  This a user pthread start
        *
-       *   void up_pthread_start(pthread_startroutine_t entrypt,
-       *                         pthread_addr_t arg) noreturn_function;
+       *   void up_pthread_start(pthread_trampoline_t startup,
+       *          pthread_startroutine_t entrypt, pthread_addr_t arg)
        *
        * At this point, the following values are saved in context:
        *
        *   R0 = SYS_pthread_start
-       *   R1 = entrypt
-       *   R2 = arg
+       *   R1 = startup
+       *   R2 = entrypt
+       *   R3 = arg
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
-          /* Set up to enter the user-space pthread start-up function in
-           * unprivileged mode. We need:
-           *
-           *   R0   = entrypt
-           *   R1   = arg
-           *   PC   = startup
-           *   CSPR = user mode
-           */
-
           regs[REG_PC]   = regs[REG_R0];
           regs[REG_R0]   = regs[REG_R1];
           regs[REG_R1]   = regs[REG_R2];
@@ -310,6 +303,28 @@ uint32_t *arm_syscall(uint32_t *regs)
           regs[REG_CPSR] = cpsr | PSR_MODE_USR;
         }
         break;
+
+      /* R0=SYS_pthread_exit:  This pthread_exit call in user-space
+       *
+       *   void up_pthread_exit(pthread_exitroutine_t exit,
+       *                        FAR void *exit_value)
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_pthread_exit
+       *   R1 = pthread_exit trampoline routine
+       *   R2 = exit_value
+       */
+
+      case SYS_pthread_exit:
+        {
+          regs[REG_PC]   = regs[REG_R0];
+          regs[REG_R0]   = regs[REG_R1];
+
+          cpsr           = regs[REG_CPSR] & ~PSR_MODE_MASK;
+          regs[REG_CPSR] = cpsr | PSR_MODE_USR;
+        }
+        break;
 #endif
 
 #ifdef CONFIG_BUILD_KERNEL
diff --git a/arch/arm/src/armv7-a/svcall.h b/arch/arm/src/armv7-a/svcall.h
index 27dc875..d22fde1 100644
--- a/arch/arm/src/armv7-a/svcall.h
+++ b/arch/arm/src/armv7-a/svcall.h
@@ -44,8 +44,8 @@
 
 #ifdef CONFIG_BUILD_KERNEL
 #  ifndef CONFIG_SYS_RESERVED
-#    error "CONFIG_SYS_RESERVED must be defined to have the value 6"
-#  elif CONFIG_SYS_RESERVED != 6
+#    error "CONFIG_SYS_RESERVED must be defined to have the value 7"
+#  elif CONFIG_SYS_RESERVED != 7
 #    error "CONFIG_SYS_RESERVED must have the value 6"
 #  endif
 #else
@@ -109,6 +109,13 @@
 
 #define SYS_pthread_start         (3)
 
+/* SYS call 8:
+ *
+ * void up_pthread_exit(pthread_exitroutine_t exit, FAR void *exit_value)
+ */
+
+#define SYS_pthread_exit         (6)
+
 #endif /* CONFIG_BUILD_KERNEL */
 
 /****************************************************************************
diff --git a/arch/arm/src/armv7-m/arm_svcall.c b/arch/arm/src/armv7-m/arm_svcall.c
index 6119ee6..ca38d1b 100644
--- a/arch/arm/src/armv7-m/arm_svcall.c
+++ b/arch/arm/src/armv7-m/arm_svcall.c
@@ -312,19 +312,21 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
         break;
 #endif
 
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
+
       /* R0=SYS_pthread_start:  This a user pthread start
        *
-       *   void up_pthread_start(pthread_startroutine_t entrypt,
-       *                         pthread_addr_t arg) noreturn_function;
+       *   void up_pthread_start(pthread_trampoline_t startup,
+       *          pthread_startroutine_t entrypt, pthread_addr_t arg)
        *
        * At this point, the following values are saved in context:
        *
        *   R0 = SYS_pthread_start
-       *   R1 = entrypt
-       *   R2 = arg
+       *   R1 = startup
+       *   R2 = entrypt
+       *   R3 = arg
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
@@ -342,6 +344,35 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
           regs[REG_R1]         = regs[REG_R3]; /* arg */
         }
         break;
+
+      /* R0=SYS_pthread_exit:  This pthread_exit call in user-space
+       *
+       *   void up_pthread_exit(pthread_exitroutine_t exit,
+       *                        FAR void *exit_value)
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_pthread_exit
+       *   R1 = pthread_exit trampoline routine
+       *   R2 = exit_value
+       */
+
+      case SYS_pthread_exit:
+        {
+          /* Set up to return to the user-space pthread start-up function in
+           * unprivileged mode.
+           */
+
+          regs[REG_PC]         = (uint32_t)regs[REG_R1] & ~1;  /* startup */
+          regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
+
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
+           */
+
+          regs[REG_R0]         = regs[REG_R2]; /* exit_value */
+        }
+        break;
 #endif
 
       /* R0=SYS_signal_handler:  This a user signal handler callback
diff --git a/arch/arm/src/armv7-m/svcall.h b/arch/arm/src/armv7-m/svcall.h
index 98a574e..1fd56ea 100644
--- a/arch/arm/src/armv7-m/svcall.h
+++ b/arch/arm/src/armv7-m/svcall.h
@@ -45,9 +45,9 @@
 #ifdef CONFIG_LIB_SYSCALL
 #  ifdef CONFIG_BUILD_PROTECTED
 #    ifndef CONFIG_SYS_RESERVED
-#      error "CONFIG_SYS_RESERVED must be defined to have the value 8"
-#    elif CONFIG_SYS_RESERVED != 8
-#      error "CONFIG_SYS_RESERVED must have the value 8"
+#      error "CONFIG_SYS_RESERVED must be defined to have the value 9"
+#    elif CONFIG_SYS_RESERVED != 9
+#      error "CONFIG_SYS_RESERVED must have the value 9"
 #    endif
 #  else
 #    ifndef CONFIG_SYS_RESERVED
@@ -126,6 +126,13 @@
 
 #define SYS_pthread_start         (5)
 
+/* SYS call 8:
+ *
+ * void up_pthread_exit(pthread_exitroutine_t exit, FAR void *exit_value)
+ */
+
+#define SYS_pthread_exit         (8)
+
 #endif /* !CONFIG_BUILD_FLAT */
 #endif /* CONFIG_LIB_SYSCALL */
 
diff --git a/arch/arm/src/armv7-r/arm_syscall.c b/arch/arm/src/armv7-r/arm_syscall.c
index 29095d0..367c41c 100644
--- a/arch/arm/src/armv7-r/arm_syscall.c
+++ b/arch/arm/src/armv7-r/arm_syscall.c
@@ -273,33 +273,48 @@ uint32_t *arm_syscall(uint32_t *regs)
         break;
 #endif
 
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
+
       /* R0=SYS_pthread_start:  This a user pthread start
        *
-       *   void up_pthread_start(pthread_startroutine_t entrypt,
-       *                         pthread_addr_t arg) noreturn_function;
+       *   void up_pthread_start(pthread_trampoline_t startup,
+       *          pthread_startroutine_t entrypt, pthread_addr_t arg)
        *
        * At this point, the following values are saved in context:
        *
        *   R0 = SYS_pthread_start
-       *   R1 = entrypt
-       *   R2 = arg
+       *   R1 = startup
+       *   R2 = entrypt
+       *   R3 = arg
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
-          /* Set up to enter the user-space pthread start-up function in
-           * unprivileged mode. We need:
-           *
-           *   R0   = startup
-           *   R1   = arg
-           *   PC   = entrypt
-           *   CSPR = user mode
-           */
+          regs[REG_PC]   = regs[REG_R0];
+          regs[REG_R0]   = regs[REG_R1];
+          regs[REG_R1]   = regs[REG_R2];
 
-          regs[REG_PC]   = regs[REG_R1];
-          regs[REG_R0]   = regs[REG_R2];
-          regs[REG_R1]   = regs[REG_R3];
+          cpsr           = regs[REG_CPSR] & ~PSR_MODE_MASK;
+          regs[REG_CPSR] = cpsr | PSR_MODE_USR;
+        }
+        break;
+
+      /* R0=SYS_pthread_exit:  This pthread_exit call in user-space
+       *
+       *   void up_pthread_exit(pthread_exitroutine_t exit,
+       *                        FAR void *exit_value)
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_pthread_exit
+       *   R1 = pthread_exit trampoline routine
+       *   R2 = exit_value
+       */
+
+      case SYS_pthread_exit:
+        {
+          regs[REG_PC]   = regs[REG_R0];
+          regs[REG_R0]   = regs[REG_R1];
 
           cpsr           = regs[REG_CPSR] & ~PSR_MODE_MASK;
           regs[REG_CPSR] = cpsr | PSR_MODE_USR;
diff --git a/arch/arm/src/armv8-m/arm_svcall.c b/arch/arm/src/armv8-m/arm_svcall.c
index f0757c7..4f57fb3 100644
--- a/arch/arm/src/armv8-m/arm_svcall.c
+++ b/arch/arm/src/armv8-m/arm_svcall.c
@@ -311,19 +311,21 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
         break;
 #endif
 
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
+
       /* R0=SYS_pthread_start:  This a user pthread start
        *
-       *   void up_pthread_start(pthread_startroutine_t entrypt,
-       *                         pthread_addr_t arg) noreturn_function;
+       *   void up_pthread_start(pthread_trampoline_t startup,
+       *          pthread_startroutine_t entrypt, pthread_addr_t arg)
        *
        * At this point, the following values are saved in context:
        *
        *   R0 = SYS_pthread_start
-       *   R1 = entrypt
-       *   R2 = arg
+       *   R1 = startup
+       *   R2 = entrypt
+       *   R3 = arg
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
@@ -338,7 +340,36 @@ int arm_svcall(int irq, FAR void *context, FAR void *arg)
            */
 
           regs[REG_R0]         = regs[REG_R2]; /* pthread entry */
-          regs[REG_R1]         = regs[REG_R2]; /* arg */
+          regs[REG_R1]         = regs[REG_R3]; /* arg */
+        }
+        break;
+
+      /* R0=SYS_pthread_exit:  This pthread_exit call in user-space
+       *
+       *   void up_pthread_exit(pthread_exitroutine_t exit,
+       *                        FAR void *exit_value)
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_pthread_exit
+       *   R1 = pthread_exit trampoline routine
+       *   R2 = exit_value
+       */
+
+      case SYS_pthread_exit:
+        {
+          /* Set up to return to the user-space pthread start-up function in
+           * unprivileged mode.
+           */
+
+          regs[REG_PC]         = (uint32_t)regs[REG_R1] & ~1;  /* startup */
+          regs[REG_EXC_RETURN] = EXC_RETURN_UNPRIVTHR;
+
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_startup:
+           */
+
+          regs[REG_R0]         = regs[REG_R2]; /* exit_value */
         }
         break;
 #endif
diff --git a/libs/libc/pthread/pthread_exit.c b/arch/arm/src/common/arm_pthread_exit.c
similarity index 65%
copy from libs/libc/pthread/pthread_exit.c
copy to arch/arm/src/common/arm_pthread_exit.c
index 2e456b6..ba7eb82 100644
--- a/libs/libc/pthread/pthread_exit.c
+++ b/arch/arm/src/common/arm_pthread_exit.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * libs/libc/pthread/pthread_exit.c
+ * arch/arm/src/common/arm_pthread_exit.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -23,38 +23,40 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <pthread.h>
+#include <nuttx/arch.h>
 
-#include <debug.h>
-#include <sched.h>
+#include "svcall.h"
+#include "arm_internal.h"
 
-#include <nuttx/pthread.h>
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) && \
+    !defined(CONFIG_DISABLE_PTHREAD)
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pthread_exit
+ * Name: up_pthread_exit
  *
  * Description:
- *   Terminate execution of a thread started with pthread_create.
+ *   In this kernel mode build, this function will be called to execute a
+ *   pthread in user-space. This kernel-mode stub will then be called
+ *   transfer control to the user-mode pthread_exit.
  *
  * Input Parameters:
- *   exit_value
+ *   exit       - The user-space pthread_exit function
+ *   exit_value - The pointer of the pthread exit parameter
  *
  * Returned Value:
  *   None
- *
- * Assumptions:
- *
  ****************************************************************************/
 
-void pthread_exit(FAR void *exit_value)
+void up_pthread_exit(pthread_exitroutine_t exit, FAR void *exit_value)
 {
-#ifdef CONFIG_PTHREAD_CLEANUP
-  pthread_cleanup_popall();
-#endif
+  /* Let sys_call2() do all of the work */
 
-  nx_pthread_exit(exit_value);
-  PANIC();
+  sys_call2(SYS_pthread_exit, (uintptr_t)exit, (uintptr_t)exit_value);
 }
+
+#endif /* !CONFIG_BUILD_FLAT && __KERNEL__ && !CONFIG_DISABLE_PTHREAD */
diff --git a/arch/arm/src/cxd56xx/Make.defs b/arch/arm/src/cxd56xx/Make.defs
index c61a72f..9ffb394 100644
--- a/arch/arm/src/cxd56xx/Make.defs
+++ b/arch/arm/src/cxd56xx/Make.defs
@@ -51,6 +51,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/efm32/Make.defs b/arch/arm/src/efm32/Make.defs
index 2f76395..670d1a9 100644
--- a/arch/arm/src/efm32/Make.defs
+++ b/arch/arm/src/efm32/Make.defs
@@ -43,6 +43,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/eoss3/Make.defs b/arch/arm/src/eoss3/Make.defs
index 3e2bc2f..61492fe 100644
--- a/arch/arm/src/eoss3/Make.defs
+++ b/arch/arm/src/eoss3/Make.defs
@@ -43,6 +43,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/imx6/Make.defs b/arch/arm/src/imx6/Make.defs
index f04bd17..bc9884e 100644
--- a/arch/arm/src/imx6/Make.defs
+++ b/arch/arm/src/imx6/Make.defs
@@ -90,6 +90,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_KERNEL),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c arm_signal_dispatch.c
+CMN_CSRCS += arm_pthread_exit.c
 endif
 
 ifeq ($(CONFIG_ARCH_ADDRENV),y)
diff --git a/arch/arm/src/imxrt/Make.defs b/arch/arm/src/imxrt/Make.defs
index 5d5946b..ba9195a 100644
--- a/arch/arm/src/imxrt/Make.defs
+++ b/arch/arm/src/imxrt/Make.defs
@@ -55,6 +55,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/kinetis/Make.defs b/arch/arm/src/kinetis/Make.defs
index 0f2fd14..6b34266 100644
--- a/arch/arm/src/kinetis/Make.defs
+++ b/arch/arm/src/kinetis/Make.defs
@@ -51,6 +51,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/kl/Make.defs b/arch/arm/src/kl/Make.defs
index 912223b..2f76917 100644
--- a/arch/arm/src/kl/Make.defs
+++ b/arch/arm/src/kl/Make.defs
@@ -32,6 +32,7 @@ CMN_CSRCS += arm_hardfault.c arm_svcall.c arm_vectors.c arm_vfork.c
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/lc823450/Make.defs b/arch/arm/src/lc823450/Make.defs
index 74e92be..4f37e68 100644
--- a/arch/arm/src/lc823450/Make.defs
+++ b/arch/arm/src/lc823450/Make.defs
@@ -42,6 +42,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/lpc17xx_40xx/Make.defs b/arch/arm/src/lpc17xx_40xx/Make.defs
index 96b01fd..81a1515 100644
--- a/arch/arm/src/lpc17xx_40xx/Make.defs
+++ b/arch/arm/src/lpc17xx_40xx/Make.defs
@@ -54,6 +54,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/lpc43xx/Make.defs b/arch/arm/src/lpc43xx/Make.defs
index 05d8ba4..c42b777 100644
--- a/arch/arm/src/lpc43xx/Make.defs
+++ b/arch/arm/src/lpc43xx/Make.defs
@@ -47,6 +47,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/lpc54xx/Make.defs b/arch/arm/src/lpc54xx/Make.defs
index d40a65d..2f89791 100644
--- a/arch/arm/src/lpc54xx/Make.defs
+++ b/arch/arm/src/lpc54xx/Make.defs
@@ -47,6 +47,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/max326xx/Make.defs b/arch/arm/src/max326xx/Make.defs
index 628bcdd..b4f7e63 100644
--- a/arch/arm/src/max326xx/Make.defs
+++ b/arch/arm/src/max326xx/Make.defs
@@ -45,6 +45,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/nrf52/Make.defs b/arch/arm/src/nrf52/Make.defs
index b6b4970..b5091bc 100644
--- a/arch/arm/src/nrf52/Make.defs
+++ b/arch/arm/src/nrf52/Make.defs
@@ -51,6 +51,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/nuc1xx/Make.defs b/arch/arm/src/nuc1xx/Make.defs
index 85152e7..cd19f8e 100644
--- a/arch/arm/src/nuc1xx/Make.defs
+++ b/arch/arm/src/nuc1xx/Make.defs
@@ -32,6 +32,7 @@ CMN_CSRCS += arm_hardfault.c arm_svcall.c arm_vectors.c arm_vfork.c
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/rp2040/Make.defs b/arch/arm/src/rp2040/Make.defs
index a640d43..a918e10 100644
--- a/arch/arm/src/rp2040/Make.defs
+++ b/arch/arm/src/rp2040/Make.defs
@@ -36,6 +36,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/s32k1xx/Make.defs b/arch/arm/src/s32k1xx/Make.defs
index b9efbae..f2cf130 100644
--- a/arch/arm/src/s32k1xx/Make.defs
+++ b/arch/arm/src/s32k1xx/Make.defs
@@ -31,6 +31,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 endif
 
 # Source files common to all S32K1xx chip families.
diff --git a/arch/arm/src/sam34/Make.defs b/arch/arm/src/sam34/Make.defs
index 2aa370e..8f321ee 100644
--- a/arch/arm/src/sam34/Make.defs
+++ b/arch/arm/src/sam34/Make.defs
@@ -59,6 +59,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/sama5/Make.defs b/arch/arm/src/sama5/Make.defs
index 9d9f9d2..99c58d3 100644
--- a/arch/arm/src/sama5/Make.defs
+++ b/arch/arm/src/sama5/Make.defs
@@ -76,6 +76,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_KERNEL),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c arm_signal_dispatch.c
+CMN_CSRCS += arm_pthread_exit.c
 endif
 
 ifeq ($(CONFIG_ARCH_ADDRENV),y)
diff --git a/arch/arm/src/samd2l2/Make.defs b/arch/arm/src/samd2l2/Make.defs
index 7fcf0f3..9e30a0e 100644
--- a/arch/arm/src/samd2l2/Make.defs
+++ b/arch/arm/src/samd2l2/Make.defs
@@ -32,6 +32,7 @@ CMN_CSRCS += arm_hardfault.c arm_svcall.c arm_vectors.c arm_vfork.c
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/samd5e5/Make.defs b/arch/arm/src/samd5e5/Make.defs
index 1750513..7037181 100644
--- a/arch/arm/src/samd5e5/Make.defs
+++ b/arch/arm/src/samd5e5/Make.defs
@@ -49,6 +49,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/samv7/Make.defs b/arch/arm/src/samv7/Make.defs
index a49c369..7be0938 100644
--- a/arch/arm/src/samv7/Make.defs
+++ b/arch/arm/src/samv7/Make.defs
@@ -67,6 +67,7 @@ ifeq ($(CONFIG_ARM_MPU),y)
 CMN_CSRCS += arm_mpu.c
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/stm32/Make.defs b/arch/arm/src/stm32/Make.defs
index c5f5a7f..7285224 100644
--- a/arch/arm/src/stm32/Make.defs
+++ b/arch/arm/src/stm32/Make.defs
@@ -58,7 +58,7 @@ CMN_CSRCS += arm_mpu.c
 endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
-CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_task_start.c arm_pthread_start.c arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/stm32f0l0g0/Make.defs b/arch/arm/src/stm32f0l0g0/Make.defs
index 7ad308c..a108459 100644
--- a/arch/arm/src/stm32f0l0g0/Make.defs
+++ b/arch/arm/src/stm32f0l0g0/Make.defs
@@ -32,6 +32,7 @@ CMN_CSRCS += arm_hardfault.c arm_svcall.c arm_vectors.c arm_vfork.c
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/stm32f7/Make.defs b/arch/arm/src/stm32f7/Make.defs
index 94bb463..71c5981 100644
--- a/arch/arm/src/stm32f7/Make.defs
+++ b/arch/arm/src/stm32f7/Make.defs
@@ -73,6 +73,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/stm32h7/Make.defs b/arch/arm/src/stm32h7/Make.defs
index d401d06..2a24c0d 100644
--- a/arch/arm/src/stm32h7/Make.defs
+++ b/arch/arm/src/stm32h7/Make.defs
@@ -72,6 +72,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/stm32l4/Make.defs b/arch/arm/src/stm32l4/Make.defs
index 59051e6..ca695c8 100644
--- a/arch/arm/src/stm32l4/Make.defs
+++ b/arch/arm/src/stm32l4/Make.defs
@@ -63,6 +63,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/stm32l5/Make.defs b/arch/arm/src/stm32l5/Make.defs
index ec53d49..0ce8155 100644
--- a/arch/arm/src/stm32l5/Make.defs
+++ b/arch/arm/src/stm32l5/Make.defs
@@ -64,6 +64,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/tiva/Make.defs b/arch/arm/src/tiva/Make.defs
index 272de11..2483799 100644
--- a/arch/arm/src/tiva/Make.defs
+++ b/arch/arm/src/tiva/Make.defs
@@ -65,6 +65,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
   CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+  CMN_CSRCS += arm_pthread_exit.c
   CMN_CSRCS += arm_signal_dispatch.c
   CMN_UASRCS += arm_signal_handler.S
 else
diff --git a/arch/arm/src/tms570/Make.defs b/arch/arm/src/tms570/Make.defs
index 98d5ce5..6899d55 100644
--- a/arch/arm/src/tms570/Make.defs
+++ b/arch/arm/src/tms570/Make.defs
@@ -59,6 +59,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_mpu.c arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/arm/src/xmc4/Make.defs b/arch/arm/src/xmc4/Make.defs
index f9ea045..66d7669 100644
--- a/arch/arm/src/xmc4/Make.defs
+++ b/arch/arm/src/xmc4/Make.defs
@@ -51,6 +51,7 @@ endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS += arm_task_start.c arm_pthread_start.c
+CMN_CSRCS += arm_pthread_exit.c
 CMN_CSRCS += arm_signal_dispatch.c
 CMN_UASRCS += arm_signal_handler.S
 endif
diff --git a/arch/or1k/src/common/up_pthread_start.c b/arch/or1k/src/common/up_pthread_start.c
index 8edbd06..29640b6 100644
--- a/arch/or1k/src/common/up_pthread_start.c
+++ b/arch/or1k/src/common/up_pthread_start.c
@@ -63,7 +63,7 @@
 
 void up_pthread_start(pthread_startroutine_t entrypt, pthread_addr_t arg)
 {
-  /* Let sys_call2() do all of the work */
+  /* Let sys_call3() do all of the work */
 
   sinfo("entry %p arg %p\n", entrypt, arg);
 
diff --git a/arch/risc-v/src/c906/Make.defs b/arch/risc-v/src/c906/Make.defs
index a367c4d..8088b46 100644
--- a/arch/risc-v/src/c906/Make.defs
+++ b/arch/risc-v/src/c906/Make.defs
@@ -55,6 +55,7 @@ CHIP_CSRCS += c906_start.c c906_timerisr.c
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
 CMN_CSRCS  += riscv_task_start.c riscv_pthread_start.c
+CMN_CSRCS  += riscv_pthread_exit.c
 CMN_CSRCS  += riscv_signal_dispatch.c riscv_pmp.c
 CMN_UASRCS += riscv_signal_handler.S
 
diff --git a/libs/libc/pthread/pthread_exit.c b/arch/risc-v/src/common/riscv_pthread_exit.c
similarity index 66%
copy from libs/libc/pthread/pthread_exit.c
copy to arch/risc-v/src/common/riscv_pthread_exit.c
index 2e456b6..39964ea 100644
--- a/libs/libc/pthread/pthread_exit.c
+++ b/arch/risc-v/src/common/riscv_pthread_exit.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * libs/libc/pthread/pthread_exit.c
+ * arch/risc-v/src/common/riscv_pthread_exit.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -23,38 +23,38 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+#include <pthread.h>
+#include <nuttx/arch.h>
 
-#include <debug.h>
-#include <sched.h>
+#include "svcall.h"
+#include "riscv_internal.h"
 
-#include <nuttx/pthread.h>
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) && \
+    !defined(CONFIG_DISABLE_PTHREAD)
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: pthread_exit
+ * Name: up_pthread_exit
  *
  * Description:
- *   Terminate execution of a thread started with pthread_create.
+ *   In this kernel mode build, this function will be called to execute a
+ *   pthread in user-space. This kernel-mode stub will then be called
+ *   transfer control to the user-mode pthread_exit.
  *
  * Input Parameters:
- *   exit_value
+ *   exit       - The user-space pthread_exit function
+ *   exit_value - The pointer of the pthread exit parameter
  *
  * Returned Value:
  *   None
- *
- * Assumptions:
- *
  ****************************************************************************/
 
-void pthread_exit(FAR void *exit_value)
+void up_pthread_exit(pthread_exitroutine_t exit, FAR void *exit_value)
 {
-#ifdef CONFIG_PTHREAD_CLEANUP
-  pthread_cleanup_popall();
-#endif
-
-  nx_pthread_exit(exit_value);
-  PANIC();
+  sys_call2(SYS_pthread_exit, (uintptr_t)exit, (uintptr_t)exit_value);
 }
+
+#endif /* !CONFIG_BUILD_FLAT && __KERNEL__ && !CONFIG_DISABLE_PTHREAD */
diff --git a/arch/risc-v/src/k210/Make.defs b/arch/risc-v/src/k210/Make.defs
index 5c5cb22..a8bf25e 100644
--- a/arch/risc-v/src/k210/Make.defs
+++ b/arch/risc-v/src/k210/Make.defs
@@ -57,7 +57,8 @@ CHIP_CSRCS += k210_cpupause.c k210_cpustart.c
 endif
 
 ifeq ($(CONFIG_BUILD_PROTECTED),y)
-CMN_CSRCS  += riscv_task_start.c riscv_pthread_start.c
+CMN_CSRCS  += riscv_task_start.c
+CMN_CSRCS  += riscv_pthread_start.c riscv_pthread_exit.c
 CMN_CSRCS  += riscv_signal_dispatch.c
 CMN_UASRCS += riscv_signal_handler.S
 
diff --git a/arch/risc-v/src/rv64gc/riscv_swint.c b/arch/risc-v/src/rv64gc/riscv_swint.c
index 7e6d90b..8cd2528 100644
--- a/arch/risc-v/src/rv64gc/riscv_swint.c
+++ b/arch/risc-v/src/rv64gc/riscv_swint.c
@@ -282,19 +282,21 @@ int riscv_swint(int irq, FAR void *context, FAR void *arg)
         break;
 #endif
 
-      /* R0=SYS_pthread_start:  This a user pthread start
+#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
+
+      /* A0=SYS_pthread_start:  This a user pthread start
        *
-       *   void up_pthread_start(pthread_startroutine_t entrypt,
-       *                         pthread_addr_t arg) noreturn_function;
+       *   void up_pthread_start(pthread_trampoline_t startup,
+       *          pthread_startroutine_t entrypt, pthread_addr_t arg)
        *
        * At this point, the following values are saved in context:
        *
-       *   R0 = SYS_pthread_start
-       *   R1 = entrypt
-       *   R2 = arg
+       *   A0 = SYS_pthread_start
+       *   A1 = startup
+       *   A2 = entrypt
+       *   A3 = arg
        */
 
-#if !defined(CONFIG_BUILD_FLAT) && !defined(CONFIG_DISABLE_PTHREAD)
       case SYS_pthread_start:
         {
           /* Set up to return to the user-space pthread start-up function in
@@ -312,6 +314,35 @@ int riscv_swint(int irq, FAR void *context, FAR void *arg)
           regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
         }
         break;
+
+      /* R0=SYS_pthread_exit:  This pthread_exit call in user-space
+       *
+       *   void up_pthread_exit(pthread_exitroutine_t exit,
+       *                        FAR void *exit_value)
+       *
+       * At this point, the following values are saved in context:
+       *
+       *   R0 = SYS_pthread_exit
+       *   R1 = pthread_exit trampoline routine
+       *   R2 = exit_value
+       */
+
+      case SYS_pthread_exit:
+        {
+          /* Set up to enter the user-space pthread exit function in
+           * unprivileged mode.
+           */
+
+          regs[REG_EPC]      = (uintptr_t)regs[REG_A1] & ~1;  /* exit */
+
+          /* Change the parameter ordering to match the expectation of the
+           * user space pthread_exit:
+           */
+
+          regs[REG_A0]       = regs[REG_A2];  /* exit_value */
+          regs[REG_INT_CTX] &= ~MSTATUS_MPPM; /* User mode */
+        }
+        break;
 #endif
 
       /* R0=SYS_signal_handler:  This a user signal handler callback
diff --git a/arch/risc-v/src/rv64gc/svcall.h b/arch/risc-v/src/rv64gc/svcall.h
index 80c8c15..6ecb889 100644
--- a/arch/risc-v/src/rv64gc/svcall.h
+++ b/arch/risc-v/src/rv64gc/svcall.h
@@ -46,9 +46,9 @@
 #ifdef CONFIG_LIB_SYSCALL
 #  ifdef CONFIG_BUILD_PROTECTED
 #    ifndef CONFIG_SYS_RESERVED
-#      error "CONFIG_SYS_RESERVED must be defined to have the value 8"
-#    elif CONFIG_SYS_RESERVED != 8
-#      error "CONFIG_SYS_RESERVED must have the value 8"
+#      error "CONFIG_SYS_RESERVED must be defined to have the value 9"
+#    elif CONFIG_SYS_RESERVED != 9
+#      error "CONFIG_SYS_RESERVED must have the value 9"
 #    endif
 #  else
 #    ifndef CONFIG_SYS_RESERVED
@@ -118,13 +118,20 @@
 
 /* SYS call 5:
  *
- * void up_pthread_start(pthread_startroutine_t startup,
+ * void up_pthread_start(pthread_trampoline_t startup,
  *                       pthread_startroutine_t entrypt, pthread_addr_t arg)
  *        noreturn_function
  */
 
 #define SYS_pthread_start         (5)
 
+/* SYS call 8:
+ *
+ * void up_pthread_exit(pthread_exitroutine_t exit, FAR void *exit_value)
+ */
+
+#define SYS_pthread_exit          (8)
+
 #endif /* !CONFIG_BUILD_FLAT */
 #endif /* CONFIG_LIB_SYSCALL */
 
diff --git a/boards/arm/imxrt/imxrt1050-evk/configs/knsh/defconfig b/boards/arm/imxrt/imxrt1050-evk/configs/knsh/defconfig
index b13be81..df3c611 100644
--- a/boards/arm/imxrt/imxrt1050-evk/configs/knsh/defconfig
+++ b/boards/arm/imxrt/imxrt1050-evk/configs/knsh/defconfig
@@ -40,5 +40,5 @@ CONFIG_SCHED_WAITPID=y
 CONFIG_START_DAY=8
 CONFIG_START_MONTH=6
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/imxrt/imxrt1060-evk/configs/knsh/defconfig b/boards/arm/imxrt/imxrt1060-evk/configs/knsh/defconfig
index 2fe1cda..9f9ba3f 100644
--- a/boards/arm/imxrt/imxrt1060-evk/configs/knsh/defconfig
+++ b/boards/arm/imxrt/imxrt1060-evk/configs/knsh/defconfig
@@ -40,5 +40,5 @@ CONFIG_SCHED_WAITPID=y
 CONFIG_START_DAY=8
 CONFIG_START_MONTH=6
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/imxrt/imxrt1064-evk/configs/knsh/defconfig b/boards/arm/imxrt/imxrt1064-evk/configs/knsh/defconfig
index 1c0ed8c..1b33c0d 100644
--- a/boards/arm/imxrt/imxrt1064-evk/configs/knsh/defconfig
+++ b/boards/arm/imxrt/imxrt1064-evk/configs/knsh/defconfig
@@ -40,5 +40,5 @@ CONFIG_SCHED_WAITPID=y
 CONFIG_START_DAY=8
 CONFIG_START_MONTH=6
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/lc823450/lc823450-xgevk/configs/knsh/defconfig b/boards/arm/lc823450/lc823450-xgevk/configs/knsh/defconfig
index 3eae417..05109c5 100644
--- a/boards/arm/lc823450/lc823450-xgevk/configs/knsh/defconfig
+++ b/boards/arm/lc823450/lc823450-xgevk/configs/knsh/defconfig
@@ -109,7 +109,7 @@ CONFIG_START_YEAR=2013
 CONFIG_SYSTEM_I2CTOOL=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_TIME64=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=24
 CONFIG_UART0_RXBUFSIZE=512
 CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/arm/lc823450/lc823450-xgevk/configs/kostest/defconfig b/boards/arm/lc823450/lc823450-xgevk/configs/kostest/defconfig
index a50cc7a..f97b0fa 100644
--- a/boards/arm/lc823450/lc823450-xgevk/configs/kostest/defconfig
+++ b/boards/arm/lc823450/lc823450-xgevk/configs/kostest/defconfig
@@ -40,7 +40,7 @@ CONFIG_START_MONTH=10
 CONFIG_START_YEAR=2013
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_TIME64=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TESTING_OSTEST=y
 CONFIG_TESTING_OSTEST_NBARRIER_THREADS=3
 CONFIG_TESTING_OSTEST_STACKSIZE=2048
diff --git a/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig b/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig
index 1816c5b..813094b 100644
--- a/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig
+++ b/boards/arm/lc823450/lc823450-xgevk/configs/krndis/defconfig
@@ -173,7 +173,7 @@ CONFIG_SYSTEM_NSH_SYMTAB_COUNTNAME="g_nsymbols"
 CONFIG_SYSTEM_NXPLAYER=y
 CONFIG_SYSTEM_PING=y
 CONFIG_SYSTEM_TIME64=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=24
 CONFIG_TELNET_CHARACTER_MODE=y
 CONFIG_TESTING_OSTEST=y
diff --git a/boards/arm/lpc17xx_40xx/lpc4088-devkit/configs/knsh/defconfig b/boards/arm/lpc17xx_40xx/lpc4088-devkit/configs/knsh/defconfig
index 967e9c9..0d08c2f 100644
--- a/boards/arm/lpc17xx_40xx/lpc4088-devkit/configs/knsh/defconfig
+++ b/boards/arm/lpc17xx_40xx/lpc4088-devkit/configs/knsh/defconfig
@@ -57,7 +57,7 @@ CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2013
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/lpc17xx_40xx/lpc4088-quickstart/configs/knsh/defconfig b/boards/arm/lpc17xx_40xx/lpc4088-quickstart/configs/knsh/defconfig
index 72cfa7c..56b1d69 100644
--- a/boards/arm/lpc17xx_40xx/lpc4088-quickstart/configs/knsh/defconfig
+++ b/boards/arm/lpc17xx_40xx/lpc4088-quickstart/configs/knsh/defconfig
@@ -53,7 +53,7 @@ CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2013
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/lpc17xx_40xx/open1788/configs/knsh/defconfig b/boards/arm/lpc17xx_40xx/open1788/configs/knsh/defconfig
index d32e086..f57066c 100644
--- a/boards/arm/lpc17xx_40xx/open1788/configs/knsh/defconfig
+++ b/boards/arm/lpc17xx_40xx/open1788/configs/knsh/defconfig
@@ -57,7 +57,7 @@ CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2013
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/lpc17xx_40xx/open1788/configs/knxterm/defconfig b/boards/arm/lpc17xx_40xx/open1788/configs/knxterm/defconfig
index adbc074..3af96a5 100644
--- a/boards/arm/lpc17xx_40xx/open1788/configs/knxterm/defconfig
+++ b/boards/arm/lpc17xx_40xx/open1788/configs/knxterm/defconfig
@@ -67,7 +67,7 @@ CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2019
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_CLE=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nxterm_main"
diff --git a/boards/arm/lpc17xx_40xx/pnev5180b/configs/knsh/defconfig b/boards/arm/lpc17xx_40xx/pnev5180b/configs/knsh/defconfig
index 2d1f6cb..542c60b 100644
--- a/boards/arm/lpc17xx_40xx/pnev5180b/configs/knsh/defconfig
+++ b/boards/arm/lpc17xx_40xx/pnev5180b/configs/knsh/defconfig
@@ -21,6 +21,6 @@ CONFIG_PASS1_BUILDIR="boards/arm/lpc17xx_40xx/pnev5180b/kernel"
 CONFIG_RAM_SIZE=32768
 CONFIG_RAM_START=0x10000000
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/lpc43xx/bambino-200e/configs/knsh/defconfig b/boards/arm/lpc43xx/bambino-200e/configs/knsh/defconfig
index 153c525..38a66bf 100644
--- a/boards/arm/lpc43xx/bambino-200e/configs/knsh/defconfig
+++ b/boards/arm/lpc43xx/bambino-200e/configs/knsh/defconfig
@@ -49,7 +49,7 @@ CONFIG_START_MONTH=7
 CONFIG_START_YEAR=2012
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_TIMER=y
 CONFIG_UART1_SERIAL_CONSOLE=y
diff --git a/boards/arm/sam34/sam3u-ek/configs/knsh/defconfig b/boards/arm/sam34/sam3u-ek/configs/knsh/defconfig
index 8f5fae0..d2582b8 100644
--- a/boards/arm/sam34/sam3u-ek/configs/knsh/defconfig
+++ b/boards/arm/sam34/sam3u-ek/configs/knsh/defconfig
@@ -48,7 +48,7 @@ CONFIG_START_DAY=10
 CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2013
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_UART0_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/sama5/sama5d4-ek/configs/knsh/defconfig b/boards/arm/sama5/sama5d4-ek/configs/knsh/defconfig
index c5f7f32..e550748 100644
--- a/boards/arm/sama5/sama5d4-ek/configs/knsh/defconfig
+++ b/boards/arm/sama5/sama5d4-ek/configs/knsh/defconfig
@@ -85,5 +85,5 @@ CONFIG_SCHED_WAITPID=y
 CONFIG_SDIO_BLOCKSETUP=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_NSH_PROGNAME="init"
-CONFIG_SYS_RESERVED=6
+CONFIG_SYS_RESERVED=7
 CONFIG_USART3_SERIAL_CONSOLE=y
diff --git a/boards/arm/samv7/samv71-xult/configs/knsh/defconfig b/boards/arm/samv7/samv71-xult/configs/knsh/defconfig
index a5d351f..442f9d2 100644
--- a/boards/arm/samv7/samv71-xult/configs/knsh/defconfig
+++ b/boards/arm/samv7/samv71-xult/configs/knsh/defconfig
@@ -80,6 +80,6 @@ CONFIG_START_YEAR=2015
 CONFIG_SYSTEM_I2CTOOL=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_RAMTEST=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_UART3_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/stm32/clicker2-stm32/configs/knsh/defconfig b/boards/arm/stm32/clicker2-stm32/configs/knsh/defconfig
index 4bf0db3..32c2eff 100644
--- a/boards/arm/stm32/clicker2-stm32/configs/knsh/defconfig
+++ b/boards/arm/stm32/clicker2-stm32/configs/knsh/defconfig
@@ -52,7 +52,7 @@ CONFIG_STM32_JTAG_SW_ENABLE=y
 CONFIG_STM32_PWR=y
 CONFIG_STM32_USART3=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=32
 CONFIG_USART3_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/stm32/mikroe-stm32f4/configs/kostest/defconfig b/boards/arm/stm32/mikroe-stm32f4/configs/kostest/defconfig
index c23192d..32ed5f0 100644
--- a/boards/arm/stm32/mikroe-stm32f4/configs/kostest/defconfig
+++ b/boards/arm/stm32/mikroe-stm32f4/configs/kostest/defconfig
@@ -82,7 +82,7 @@ CONFIG_STM32_USART2=y
 CONFIG_SYSLOG_CHAR=y
 CONFIG_SYSLOG_DEVPATH="/dev/ttyS0"
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=11
 CONFIG_TESTING_OSTEST=y
 CONFIG_USBDEV=y
diff --git a/boards/arm/stm32/olimex-stm32-p407/configs/kelf/defconfig b/boards/arm/stm32/olimex-stm32-p407/configs/kelf/defconfig
index e3fcc8e..e5a22d9 100644
--- a/boards/arm/stm32/olimex-stm32-p407/configs/kelf/defconfig
+++ b/boards/arm/stm32/olimex-stm32-p407/configs/kelf/defconfig
@@ -56,7 +56,7 @@ CONFIG_STM32_SDIO=y
 CONFIG_STM32_USART3=y
 CONFIG_STM32_USBHOST=y
 CONFIG_SYMTAB_ORDEREDBYNAME=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_USART3_SERIAL_CONSOLE=y
 CONFIG_USBHOST_ISOC_DISABLE=y
 CONFIG_USBHOST_MSC=y
diff --git a/boards/arm/stm32/olimex-stm32-p407/configs/kmodule/defconfig b/boards/arm/stm32/olimex-stm32-p407/configs/kmodule/defconfig
index 8398270..74bad80 100644
--- a/boards/arm/stm32/olimex-stm32-p407/configs/kmodule/defconfig
+++ b/boards/arm/stm32/olimex-stm32-p407/configs/kmodule/defconfig
@@ -52,7 +52,7 @@ CONFIG_STM32_PWR=y
 CONFIG_STM32_USART3=y
 CONFIG_STM32_USBHOST=y
 CONFIG_SYMTAB_ORDEREDBYNAME=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_USART3_SERIAL_CONSOLE=y
 CONFIG_USBHOST_ISOC_DISABLE=y
 CONFIG_USBHOST_MSC=y
diff --git a/boards/arm/stm32/olimex-stm32-p407/configs/knsh/defconfig b/boards/arm/stm32/olimex-stm32-p407/configs/knsh/defconfig
index 928051f..20eec21 100644
--- a/boards/arm/stm32/olimex-stm32-p407/configs/knsh/defconfig
+++ b/boards/arm/stm32/olimex-stm32-p407/configs/knsh/defconfig
@@ -52,7 +52,7 @@ CONFIG_STM32_JTAG_SW_ENABLE=y
 CONFIG_STM32_PWR=y
 CONFIG_STM32_USART3=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=32
 CONFIG_USART3_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/stm32/stm3240g-eval/configs/knxwm/defconfig b/boards/arm/stm32/stm3240g-eval/configs/knxwm/defconfig
index 8e33f7a..fbc23a6 100644
--- a/boards/arm/stm32/stm3240g-eval/configs/knxwm/defconfig
+++ b/boards/arm/stm32/stm3240g-eval/configs/knxwm/defconfig
@@ -93,7 +93,7 @@ CONFIG_STMPE811_THRESHX=39
 CONFIG_STMPE811_THRESHY=51
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_READLINE=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_USART3_RXBUFSIZE=128
 CONFIG_USART3_SERIAL_CONSOLE=y
diff --git a/boards/arm/stm32/stm32f4discovery/configs/kostest/defconfig b/boards/arm/stm32/stm32f4discovery/configs/kostest/defconfig
index 627462d..5edb933 100644
--- a/boards/arm/stm32/stm32f4discovery/configs/kostest/defconfig
+++ b/boards/arm/stm32/stm32f4discovery/configs/kostest/defconfig
@@ -39,7 +39,7 @@ CONFIG_START_YEAR=2013
 CONFIG_STM32_JTAG_SW_ENABLE=y
 CONFIG_STM32_USART2=y
 CONFIG_SYMTAB_ORDEREDBYNAME=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TESTING_OSTEST=y
 CONFIG_TESTING_OSTEST_NBARRIER_THREADS=3
 CONFIG_TESTING_OSTEST_STACKSIZE=2048
diff --git a/boards/arm/stm32l4/stm32l476vg-disco/configs/knsh/defconfig b/boards/arm/stm32l4/stm32l476vg-disco/configs/knsh/defconfig
index 37d88e2..0c94cf8 100644
--- a/boards/arm/stm32l4/stm32l476vg-disco/configs/knsh/defconfig
+++ b/boards/arm/stm32l4/stm32l476vg-disco/configs/knsh/defconfig
@@ -69,7 +69,7 @@ CONFIG_STM32L4_RTC=y
 CONFIG_STM32L4_SAI1PLL=y
 CONFIG_STM32L4_USART2=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_USART2_SERIAL_CONSOLE=y
 CONFIG_USER_ENTRYPOINT="nsh_main"
diff --git a/boards/arm/stm32l4/stm32l4r9ai-disco/configs/knsh/defconfig b/boards/arm/stm32l4/stm32l4r9ai-disco/configs/knsh/defconfig
index dfea95c..2590e16 100644
--- a/boards/arm/stm32l4/stm32l4r9ai-disco/configs/knsh/defconfig
+++ b/boards/arm/stm32l4/stm32l4r9ai-disco/configs/knsh/defconfig
@@ -73,7 +73,7 @@ CONFIG_STM32L4_SRAM2_HEAP=y
 CONFIG_STM32L4_UART4=y
 CONFIG_STM32L4_USART2=y
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_UART4_BAUD=2000000
 CONFIG_UART4_RXBUFSIZE=512
diff --git a/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig b/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig
index 99597dc..da63d4b 100644
--- a/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig
+++ b/boards/arm/tiva/lm3s6965-ek/configs/qemu-protected/defconfig
@@ -98,7 +98,7 @@ CONFIG_SYSTEM_NETDB=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_NTPC=y
 CONFIG_SYSTEM_PING=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=0
 CONFIG_TIVA_ETHERNET=y
 CONFIG_TIVA_GPIOA_IRQS=y
diff --git a/boards/risc-v/c906/smartl-c906/configs/knsh/defconfig b/boards/risc-v/c906/smartl-c906/configs/knsh/defconfig
index c22533f..5280531 100644
--- a/boards/risc-v/c906/smartl-c906/configs/knsh/defconfig
+++ b/boards/risc-v/c906/smartl-c906/configs/knsh/defconfig
@@ -57,7 +57,7 @@ CONFIG_START_DAY=7
 CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2021
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=20
 CONFIG_TESTING_GETPRIME=y
 CONFIG_TESTING_OSTEST=y
diff --git a/boards/risc-v/k210/maix-bit/configs/knsh/defconfig b/boards/risc-v/k210/maix-bit/configs/knsh/defconfig
index bf09a7d..6a24cf8 100644
--- a/boards/risc-v/k210/maix-bit/configs/knsh/defconfig
+++ b/boards/risc-v/k210/maix-bit/configs/knsh/defconfig
@@ -46,7 +46,7 @@ CONFIG_START_DAY=12
 CONFIG_START_MONTH=5
 CONFIG_START_YEAR=2020
 CONFIG_SYSTEM_NSH=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=20
 CONFIG_TESTING_GETPRIME=y
 CONFIG_TESTING_OSTEST=y
diff --git a/boards/risc-v/k210/maix-bit/configs/knsh_smp/defconfig b/boards/risc-v/k210/maix-bit/configs/knsh_smp/defconfig
index 67debe2..53e6dc9 100644
--- a/boards/risc-v/k210/maix-bit/configs/knsh_smp/defconfig
+++ b/boards/risc-v/k210/maix-bit/configs/knsh_smp/defconfig
@@ -51,7 +51,7 @@ CONFIG_START_YEAR=2021
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_SYSTEM=y
 CONFIG_SYSTEM_TASKSET=y
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=20
 CONFIG_TESTING_GETPRIME=y
 CONFIG_TESTING_OSTEST=y
diff --git a/boards/risc-v/k210/maix-bit/configs/kostest/defconfig b/boards/risc-v/k210/maix-bit/configs/kostest/defconfig
index f120882..db0b77e 100644
--- a/boards/risc-v/k210/maix-bit/configs/kostest/defconfig
+++ b/boards/risc-v/k210/maix-bit/configs/kostest/defconfig
@@ -42,7 +42,7 @@ CONFIG_STACK_COLORATION=y
 CONFIG_START_DAY=14
 CONFIG_START_MONTH=2
 CONFIG_START_YEAR=2020
-CONFIG_SYS_RESERVED=8
+CONFIG_SYS_RESERVED=9
 CONFIG_TASK_NAME_SIZE=20
 CONFIG_TESTING_OSTEST=y
 CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/include/nuttx/arch.h b/include/nuttx/arch.h
index d3ef3d6..37c5c7f 100644
--- a/include/nuttx/arch.h
+++ b/include/nuttx/arch.h
@@ -558,6 +558,8 @@ void up_task_start(main_t taskentry, int argc, FAR char *argv[])
        noreturn_function;
 #endif
 
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) && \
+    !defined(CONFIG_DISABLE_PTHREAD)
 /****************************************************************************
  * Name: up_pthread_start
  *
@@ -583,11 +585,28 @@ void up_task_start(main_t taskentry, int argc, FAR char *argv[])
  *
  ****************************************************************************/
 
-#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) && \
-    !defined(CONFIG_DISABLE_PTHREAD)
 void up_pthread_start(pthread_trampoline_t startup,
                       pthread_startroutine_t entrypt, pthread_addr_t arg);
        noreturn_function;
+
+/****************************************************************************
+ * Name: up_pthread_exit
+ *
+ * Description:
+ *   In this kernel mode build, this function will be called to execute a
+ *   pthread in user-space. This kernel-mode stub will then be called
+ *   transfer control to the user-mode pthread_exit.
+ *
+ * Input Parameters:
+ *   exit       - The user-space pthread_exit function
+ *   exit_value - The pointer of the pthread exit parameter
+ *
+ * Returned Value:
+ *   None
+ ****************************************************************************/
+
+void up_pthread_exit(pthread_exitroutine_t exit, FAR void *exit_value);
+        noreturn_function;
 #endif
 
 /****************************************************************************
diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h
index d8e30aa..7c4b8ce 100644
--- a/include/nuttx/pthread.h
+++ b/include/nuttx/pthread.h
@@ -140,6 +140,7 @@ EXTERN const pthread_attr_t g_default_pthread_attr;
  *                 for the new thread
  *    entry      - The new thread starts execution by invoking entry
  *    arg        - It is passed as the sole argument of entry
+ *    exit       - The user-space pthread exit function
  *
  * Returned Value:
  *   OK (0) on success; a (non-negated) errno value on failure. The errno
@@ -149,7 +150,8 @@ EXTERN const pthread_attr_t g_default_pthread_attr;
 
 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);
+                      pthread_startroutine_t entry, pthread_addr_t arg,
+                      pthread_exitroutine_t exit);
 
 /****************************************************************************
  * Name: nx_pthread_exit
@@ -163,8 +165,6 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
  * Returned Value:
  *   None
  *
- * Assumptions:
- *
  ****************************************************************************/
 
 void nx_pthread_exit(FAR void *exit_value) noreturn_function;
diff --git a/include/nuttx/sched.h b/include/nuttx/sched.h
index 95c7ad7..a7d0c4f 100644
--- a/include/nuttx/sched.h
+++ b/include/nuttx/sched.h
@@ -95,16 +95,17 @@
 #define TCB_FLAG_NONCANCELABLE     (1 << 2)                      /* Bit 2: Pthread is non-cancelable */
 #define TCB_FLAG_CANCEL_DEFERRED   (1 << 3)                      /* Bit 3: Deferred (vs asynch) cancellation type */
 #define TCB_FLAG_CANCEL_PENDING    (1 << 4)                      /* Bit 4: Pthread cancel is pending */
-#define TCB_FLAG_POLICY_SHIFT      (5)                           /* Bit 5-6: Scheduling policy */
+#define TCB_FLAG_CANCEL_DOING      (1 << 5)                      /* Bit 4: Pthread cancel/exit is doing */
+#define TCB_FLAG_POLICY_SHIFT      (6)                           /* Bit 5-6: Scheduling policy */
 #define TCB_FLAG_POLICY_MASK       (3 << TCB_FLAG_POLICY_SHIFT)
 #  define TCB_FLAG_SCHED_FIFO      (0 << TCB_FLAG_POLICY_SHIFT)  /* FIFO scheding policy */
 #  define TCB_FLAG_SCHED_RR        (1 << TCB_FLAG_POLICY_SHIFT)  /* Round robin scheding policy */
 #  define TCB_FLAG_SCHED_SPORADIC  (2 << TCB_FLAG_POLICY_SHIFT)  /* Sporadic scheding policy */
 #  define TCB_FLAG_SCHED_OTHER     (3 << TCB_FLAG_POLICY_SHIFT)  /* Other scheding policy */
-#define TCB_FLAG_CPU_LOCKED        (1 << 7)                      /* Bit 7: Locked to this CPU */
-#define TCB_FLAG_SIGNAL_ACTION     (1 << 8)                      /* Bit 8: In a signal handler */
-#define TCB_FLAG_SYSCALL           (1 << 9)                      /* Bit 9: In a system call */
-#define TCB_FLAG_EXIT_PROCESSING   (1 << 10)                     /* Bit 10: Exitting */
+#define TCB_FLAG_CPU_LOCKED        (1 << 8)                      /* Bit 7: Locked to this CPU */
+#define TCB_FLAG_SIGNAL_ACTION     (1 << 9)                      /* Bit 8: In a signal handler */
+#define TCB_FLAG_SYSCALL           (1 << 10)                     /* Bit 9: In a system call */
+#define TCB_FLAG_EXIT_PROCESSING   (1 << 11)                     /* Bit 10: Exitting */
                                                                  /* Bits 11-15: Available */
 
 /* Values for struct task_group tg_flags */
@@ -761,6 +762,7 @@ struct pthread_tcb_s
 
   pthread_trampoline_t trampoline;       /* User-space pthread startup function */
   pthread_addr_t arg;                    /* Startup argument                    */
+  pthread_exitroutine_t exit;            /* User-space pthread exit function    */
   FAR void *joininfo;                    /* Detach-able info to support join    */
 };
 #endif /* !CONFIG_DISABLE_PTHREAD */
diff --git a/include/pthread.h b/include/pthread.h
index fb8a458..e7618ba 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -225,6 +225,8 @@ typedef FAR void *pthread_addr_t;
 typedef CODE pthread_addr_t (*pthread_startroutine_t)(pthread_addr_t);
 typedef pthread_startroutine_t pthread_func_t;
 
+typedef void (*pthread_exitroutine_t)(pthread_addr_t);
+
 typedef void (*pthread_trampoline_t)(pthread_startroutine_t, pthread_addr_t);
 
 struct pthread_attr_s
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index 7781f09..5a66d8f 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -305,7 +305,7 @@ SYSCALL_LOOKUP(telldir,                    1)
   SYSCALL_LOOKUP(pthread_cond_broadcast,   1)
   SYSCALL_LOOKUP(pthread_cond_signal,      1)
   SYSCALL_LOOKUP(pthread_cond_wait,        2)
-  SYSCALL_LOOKUP(nx_pthread_create,        5)
+  SYSCALL_LOOKUP(nx_pthread_create,        6)
   SYSCALL_LOOKUP(pthread_detach,           1)
   SYSCALL_LOOKUP(nx_pthread_exit,          1)
   SYSCALL_LOOKUP(pthread_getschedparam,    3)
diff --git a/libs/libc/pthread/pthread_create.c b/libs/libc/pthread/pthread_create.c
index e81c63e..fe85127 100644
--- a/libs/libc/pthread/pthread_create.c
+++ b/libs/libc/pthread/pthread_create.c
@@ -87,5 +87,5 @@ int pthread_create(FAR pthread_t *thread, FAR const pthread_attr_t *attr,
                    pthread_startroutine_t pthread_entry, pthread_addr_t arg)
 {
   return nx_pthread_create(pthread_startup, thread, attr, pthread_entry,
-                           arg);
+                           arg, pthread_exit);
 }
diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c
index 2e456b6..ce1324c 100644
--- a/libs/libc/pthread/pthread_exit.c
+++ b/libs/libc/pthread/pthread_exit.c
@@ -40,7 +40,7 @@
  *   Terminate execution of a thread started with pthread_create.
  *
  * Input Parameters:
- *   exit_value
+ *   exit_value - The pointer of the pthread_exit parameter
  *
  * Returned Value:
  *   None
diff --git a/sched/pthread/pthread_cancel.c b/sched/pthread/pthread_cancel.c
index d2dc2f3..e4088ba 100644
--- a/sched/pthread/pthread_cancel.c
+++ b/sched/pthread/pthread_cancel.c
@@ -24,6 +24,8 @@
 
 #include <nuttx/config.h>
 
+#include <nuttx/arch.h>
+
 #include <sys/types.h>
 #include <unistd.h>
 #include <pthread.h>
@@ -82,7 +84,15 @@ int pthread_cancel(pthread_t thread)
 
   if (tcb == this_task())
     {
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
+      tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+      tcb->flags |= TCB_FLAG_CANCEL_DOING;
+
+      up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
+                      PTHREAD_CANCELED);
+#else
       pthread_exit(PTHREAD_CANCELED);
+#endif
     }
 
   /* Complete pending join operations */
diff --git a/sched/pthread/pthread_create.c b/sched/pthread/pthread_create.c
index ade4dc6..507cc6c 100644
--- a/sched/pthread/pthread_create.c
+++ b/sched/pthread/pthread_create.c
@@ -79,6 +79,7 @@ const pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER;
  *   tcb        - Address of the new task's TCB
  *   trampoline - User space pthread startup function
  *   arg        - The argument to provide to the pthread on startup.
+ *   exit       - The user-space pthread exit function
  *
  * Returned Value:
  *  None
@@ -87,7 +88,8 @@ const pthread_attr_t g_default_pthread_attr = PTHREAD_ATTR_INITIALIZER;
 
 static inline void pthread_tcb_setup(FAR struct pthread_tcb_s *ptcb,
                                      pthread_trampoline_t trampoline,
-                                     pthread_addr_t arg)
+                                     pthread_addr_t arg,
+                                     pthread_exitroutine_t exit)
 {
 #if CONFIG_TASK_NAME_SIZE > 0
   /* Copy the pthread name into the TCB */
@@ -102,6 +104,7 @@ static inline void pthread_tcb_setup(FAR struct pthread_tcb_s *ptcb,
 
   ptcb->trampoline = trampoline;
   ptcb->arg        = arg;
+  ptcb->exit       = exit;
 }
 
 /****************************************************************************
@@ -193,7 +196,12 @@ static void pthread_start(void)
   /* The thread has returned (should never happen) */
 
   DEBUGPANIC();
-  pthread_exit(NULL);
+#ifndef CONFIG_BUILD_FLAT
+  ptcb->cmn.flags &= ~TCB_FLAG_CANCEL_PENDING;
+  ptcb->cmn.flags |= TCB_FLAG_CANCEL_DOING;
+
+  up_pthread_exit(ptcb->exit, NULL);
+#endif
 }
 
 /****************************************************************************
@@ -215,6 +223,7 @@ static void pthread_start(void)
  *                 for the new thread
  *    entry      - The new thread starts execution by invoking entry
  *    arg        - It is passed as the sole argument of entry
+ *    exit       - The user-space pthread exit function
  *
  * Returned Value:
  *   OK (0) on success; a (non-negated) errno value on failure. The errno
@@ -224,7 +233,8 @@ static void pthread_start(void)
 
 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)
+                      pthread_startroutine_t entry, pthread_addr_t arg,
+                      pthread_exitroutine_t exit)
 {
   FAR struct pthread_tcb_s *ptcb;
   FAR struct tls_info_s *info;
@@ -237,6 +247,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
   bool group_joined = false;
 
   DEBUGASSERT(trampoline != NULL);
+  DEBUGASSERT(exit != NULL);
 
   /* If attributes were not supplied, use the default attributes */
 
@@ -450,7 +461,7 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
    * passed by value
    */
 
-  pthread_tcb_setup(ptcb, trampoline, arg);
+  pthread_tcb_setup(ptcb, trampoline, arg, exit);
 
   /* Join the parent's task group */
 
diff --git a/sched/signal/sig_default.c b/sched/signal/sig_default.c
index 08b8f2e..7e87089 100644
--- a/sched/signal/sig_default.c
+++ b/sched/signal/sig_default.c
@@ -224,7 +224,15 @@ static void nxsig_abnormal_termination(int signo)
        * REVISIT:  This will not work if HAVE_GROUP_MEMBERS is not set.
        */
 
-      pthread_exit(NULL);
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
+      rtcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+      rtcb->flags |= TCB_FLAG_CANCEL_DOING;
+
+      up_pthread_exit(((FAR struct pthread_tcb_s *)rtcb)->exit,
+                                  PTHREAD_CANCELED);
+#else
+      pthread_exit(PTHREAD_CANCELED);
+#endif
     }
   else
 #endif
diff --git a/sched/task/task_cancelpt.c b/sched/task/task_cancelpt.c
index 8fcada3..659e5db 100644
--- a/sched/task/task_cancelpt.c
+++ b/sched/task/task_cancelpt.c
@@ -57,6 +57,7 @@
 
 #include <nuttx/irq.h>
 #include <nuttx/cancelpt.h>
+#include <nuttx/pthread.h>
 
 #include "sched/sched.h"
 #include "semaphore/semaphore.h"
@@ -139,7 +140,15 @@ bool enter_cancellation_point(void)
               if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
                   TCB_FLAG_TTYPE_PTHREAD)
                 {
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
+                  tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+                  tcb->flags |= TCB_FLAG_CANCEL_DOING;
+
+                  up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
+                                  PTHREAD_CANCELED);
+#else
                   pthread_exit(PTHREAD_CANCELED);
+#endif
                 }
               else
 #endif
@@ -226,7 +235,15 @@ void leave_cancellation_point(void)
               if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
                   TCB_FLAG_TTYPE_PTHREAD)
                 {
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
+                  tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+                  tcb->flags |= TCB_FLAG_CANCEL_DOING;
+
+                  up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
+                                  PTHREAD_CANCELED);
+#else
                   pthread_exit(PTHREAD_CANCELED);
+#endif
                 }
               else
 #endif
diff --git a/sched/task/task_setcancelstate.c b/sched/task/task_setcancelstate.c
index bb08b54..6b61632 100644
--- a/sched/task/task_setcancelstate.c
+++ b/sched/task/task_setcancelstate.c
@@ -112,7 +112,15 @@ int task_setcancelstate(int state, FAR int *oldstate)
               if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
                   TCB_FLAG_TTYPE_PTHREAD)
                 {
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
+                  tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+                  tcb->flags |= TCB_FLAG_CANCEL_DOING;
+
+                  up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
+                                  PTHREAD_CANCELED);
+#else
                   pthread_exit(PTHREAD_CANCELED);
+#endif
                 }
               else
 #endif
diff --git a/sched/task/task_setcanceltype.c b/sched/task/task_setcanceltype.c
index b14fec5..d57cc64 100644
--- a/sched/task/task_setcanceltype.c
+++ b/sched/task/task_setcanceltype.c
@@ -100,7 +100,15 @@ int task_setcanceltype(int type, FAR int *oldtype)
 #ifndef CONFIG_DISABLE_PTHREAD
           if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
             {
-              pthread_exit(PTHREAD_CANCELED);
+#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
+                  tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
+                  tcb->flags |= TCB_FLAG_CANCEL_DOING;
+
+                  up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
+                                  PTHREAD_CANCELED);
+#else
+                  pthread_exit(PTHREAD_CANCELED);
+#endif
             }
           else
 #endif
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index 8502cc0..c39442f 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -66,7 +66,7 @@
 "munmap","sys/mman.h","defined(CONFIG_FS_RAMMAP)","int","FAR void *","size_t"
 "nx_mkfifo","nuttx/fs/fs.h","defined(CONFIG_PIPES) && CONFIG_DEV_FIFO_SIZE > 0","int","FAR const char *","mode_t","size_t"
 "nx_pipe","nuttx/fs/fs.h","defined(CONFIG_PIPES) && CONFIG_DEV_PIPE_SIZE > 0","int","int [2]|FAR int *","size_t","int"
-"nx_pthread_create","nuttx/pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_trampoline_t","FAR pthread_t *","FAR const pthread_attr_t *","pthread_startroutine_t","pthread_addr_t"
+"nx_pthread_create","nuttx/pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_trampoline_t","FAR pthread_t *","FAR const pthread_attr_t *","pthread_startroutine_t","pthread_addr_t","pthread_exitroutine_t"
 "nx_task_spawn","nuttx/spawn.h","defined(CONFIG_LIB_SYSCALL) && !defined(CONFIG_BUILD_KERNEL)","int","FAR const struct spawn_syscall_parms_s *"
 "nx_vsyslog","nuttx/syslog/syslog.h","","int","int","FAR const IPTR char *","FAR va_list *"
 "nxsched_get_stackinfo","nuttx/sched.h","","int","pid_t","FAR struct stackinfo_s *"