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 <huang...@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 <huang...@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 *"

Reply via email to