You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by gn...@apache.org on 2021/05/22 04:47:05 UTC
[incubator-nuttx] 02/09: libc: Move pthread_exit to userspace
This is an automated email from the ASF dual-hosted git repository.
gnutt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git
commit 54eef9f639476ced38a46559fad218811bd9e3c9
Author: Huang Qi <hu...@xiaomi.com>
AuthorDate: Thu Apr 29 17:56:28 2021 +0800
libc: Move pthread_exit to userspace
Signed-off-by: Huang Qi <hu...@xiaomi.com>
---
include/nuttx/pthread.h | 35 +++++++++++++++++++
include/sys/syscall_lookup.h | 3 +-
libs/libc/pthread/Make.defs | 2 +-
libs/libc/pthread/pthread_exit.c | 72 ++++++++++++++++++++++++++++++++++++++++
sched/pthread/pthread_cleanup.c | 53 +++++++++++++++++++++++++++++
sched/pthread/pthread_exit.c | 8 +----
syscall/syscall.csv | 3 +-
7 files changed, 166 insertions(+), 10 deletions(-)
diff --git a/include/nuttx/pthread.h b/include/nuttx/pthread.h
index 8dc21d9..477cf2c 100644
--- a/include/nuttx/pthread.h
+++ b/include/nuttx/pthread.h
@@ -149,6 +149,41 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
FAR const pthread_attr_t *attr,
pthread_startroutine_t entry, pthread_addr_t arg);
+/****************************************************************************
+ * Name: nx_pthread_exit
+ *
+ * Description:
+ * Terminate execution of a thread started with pthread_create.
+ *
+ * Input Parameters:
+ * exit_valie
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+void nx_pthread_exit(FAR void *exit_value) noreturn_function;
+
+/****************************************************************************
+ * Name: pthread_cleanup_poplist
+ *
+ * Description:
+ * The pthread_cleanup_poplist() is function that will pop all clean-up
+ * functions. This function is only called from within the pthread_exit()
+ *
+ * Input Parameters:
+ * cleanup - The array of struct pthread_cleanup_s to fetch callbacks
+ *
+ * Returned Value:
+ * The index to the next available entry at the top of the stack
+ *
+ ****************************************************************************/
+
+int pthread_cleanup_poplist(FAR struct pthread_cleanup_s *cleanup);
+
#undef EXTERN
#ifdef __cplusplus
}
diff --git a/include/sys/syscall_lookup.h b/include/sys/syscall_lookup.h
index c3f3dea..d59467a 100644
--- a/include/sys/syscall_lookup.h
+++ b/include/sys/syscall_lookup.h
@@ -307,7 +307,7 @@ SYSCALL_LOOKUP(telldir, 1)
SYSCALL_LOOKUP(pthread_cond_wait, 2)
SYSCALL_LOOKUP(nx_pthread_create, 5)
SYSCALL_LOOKUP(pthread_detach, 1)
- SYSCALL_LOOKUP(pthread_exit, 1)
+ SYSCALL_LOOKUP(nx_pthread_exit, 1)
SYSCALL_LOOKUP(pthread_getschedparam, 3)
SYSCALL_LOOKUP(pthread_join, 2)
SYSCALL_LOOKUP(pthread_mutex_destroy, 1)
@@ -330,6 +330,7 @@ SYSCALL_LOOKUP(telldir, 1)
#ifdef CONFIG_PTHREAD_CLEANUP
SYSCALL_LOOKUP(pthread_cleanup_push, 2)
SYSCALL_LOOKUP(pthread_cleanup_pop, 1)
+ SYSCALL_LOOKUP(pthread_cleanup_poplist, 1)
#endif
#endif
diff --git a/libs/libc/pthread/Make.defs b/libs/libc/pthread/Make.defs
index 21497bf..bbdb75b 100644
--- a/libs/libc/pthread/Make.defs
+++ b/libs/libc/pthread/Make.defs
@@ -40,7 +40,7 @@ CSRCS += pthread_barrierinit.c pthread_barrierdestroy.c pthread_barrierwait.c
CSRCS += pthread_condattr_init.c pthread_condattr_destroy.c
CSRCS += pthread_condattr_setclock.c pthread_condattr_getclock.c
CSRCS += pthread_condinit.c pthread_conddestroy.c pthread_condtimedwait.c
-CSRCS += pthread_create.c
+CSRCS += pthread_create.c pthread_exit.c
CSRCS += pthread_get_stackaddr_np.c pthread_get_stacksize_np.c
CSRCS += pthread_mutexattr_init.c pthread_mutexattr_destroy.c
CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c
diff --git a/libs/libc/pthread/pthread_exit.c b/libs/libc/pthread/pthread_exit.c
new file mode 100644
index 0000000..71271d9
--- /dev/null
+++ b/libs/libc/pthread/pthread_exit.c
@@ -0,0 +1,72 @@
+/****************************************************************************
+ * libs/libc/pthread/pthread_exit.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership. The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <debug.h>
+#include <sched.h>
+
+#include <nuttx/pthread.h>
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_exit
+ *
+ * Description:
+ * Terminate execution of a thread started with pthread_create.
+ *
+ * Input Parameters:
+ * exit_valie
+ *
+ * Returned Value:
+ * None
+ *
+ * Assumptions:
+ *
+ ****************************************************************************/
+
+void pthread_exit(FAR void *exit_value)
+{
+#ifdef CONFIG_PTHREAD_CLEANUP
+ int cnt;
+ struct pthread_cleanup_s cleanup[CONFIG_PTHREAD_CLEANUP_STACKSIZE];
+ cnt = pthread_cleanup_poplist(cleanup);
+
+ sched_lock();
+ while (cnt-- > 0)
+ {
+ struct pthread_cleanup_s cp = cleanup[cnt];
+ if (cp.pc_cleaner)
+ cp.pc_cleaner(cp.pc_arg);
+ }
+
+ sched_unlock();
+#endif
+
+ nx_pthread_exit(exit_value);
+ PANIC();
+}
diff --git a/sched/pthread/pthread_cleanup.c b/sched/pthread/pthread_cleanup.c
index e735b15..8c5dbaf 100644
--- a/sched/pthread/pthread_cleanup.c
+++ b/sched/pthread/pthread_cleanup.c
@@ -208,4 +208,57 @@ void pthread_cleanup_popall(FAR struct tcb_s *tcb)
}
}
+/****************************************************************************
+ * Name: pthread_cleanup_poplist
+ *
+ * Description:
+ * The pthread_cleanup_poplist() is function that will pop all clean-up
+ * functions. This function is only called from within the pthread_exit()
+ *
+ * Input Parameters:
+ * cleanup - The array of struct pthread_cleanup_s to fetch callbacks
+ *
+ * Returned Value:
+ * The index to the next available entry at the top of the stack
+ *
+ ****************************************************************************/
+
+int pthread_cleanup_poplist(FAR struct pthread_cleanup_s *cleanup)
+{
+ uint8_t tos = 0;
+ uint8_t ndx = 0;
+ FAR struct tcb_s *tcb = this_task();
+
+ DEBUGASSERT(cleanup != NULL);
+ DEBUGASSERT(tcb != NULL);
+ DEBUGASSERT(tcb->tos < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
+
+ tos = tcb->tos;
+
+ /* Kernel threads do not support pthread APIs */
+
+ if ((tcb->flags & TCB_FLAG_TTYPE_MASK) != TCB_FLAG_TTYPE_KERNEL)
+ {
+ /* Pop cleanup routine list
+ *
+ * sched_lock() should provide sufficient protection. We only need to
+ * have this TCB stationary; the pthread cleanup stack should never be
+ * modified by interrupt level logic.
+ */
+
+ sched_lock();
+ while (tcb->tos > 0)
+ {
+ ndx = tcb->tos - 1;
+ DEBUGASSERT(ndx >= 0 && ndx < CONFIG_PTHREAD_CLEANUP_STACKSIZE);
+ cleanup[ndx] = tcb->stack[ndx];
+ tcb->tos = ndx;
+ }
+
+ sched_unlock();
+ }
+
+ return tos;
+}
+
#endif /* CONFIG_PTHREAD_CLEANUP */
diff --git a/sched/pthread/pthread_exit.c b/sched/pthread/pthread_exit.c
index bc6086f..a7704ab 100644
--- a/sched/pthread/pthread_exit.c
+++ b/sched/pthread/pthread_exit.c
@@ -59,7 +59,7 @@
*
****************************************************************************/
-void pthread_exit(FAR void *exit_value)
+void nx_pthread_exit(FAR void *exit_value)
{
FAR struct tcb_s *tcb = this_task();
sigset_t set = ALL_SIGNAL_SET;
@@ -87,12 +87,6 @@ void pthread_exit(FAR void *exit_value)
tcb->cpcount = 0;
#endif
-#ifdef CONFIG_PTHREAD_CLEANUP
- /* Perform any stack pthread clean-up callbacks */
-
- pthread_cleanup_popall(tcb);
-#endif
-
/* Complete pending join operations */
status = pthread_completejoin(getpid(), exit_value);
diff --git a/syscall/syscall.csv b/syscall/syscall.csv
index a9c4658..e88cf9e 100644
--- a/syscall/syscall.csv
+++ b/syscall/syscall.csv
@@ -84,13 +84,14 @@
"pselect","sys/select.h","","int","int","FAR fd_set *","FAR fd_set *","FAR fd_set *","FAR const struct timespec *","FAR const sigset_t *"
"pthread_cancel","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
"pthread_cleanup_pop","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","int"
+"pthread_cleanup_poplist","nuttx/pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","int","struct pthread_cleanup_s *"
"pthread_cleanup_push","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","pthread_cleanup_t","FAR void *"
"pthread_cond_broadcast","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *"
"pthread_cond_clockwait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *","clockid_t","FAR const struct timespec *"
"pthread_cond_signal","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *"
"pthread_cond_wait","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","FAR pthread_cond_t *","FAR pthread_mutex_t *"
"pthread_detach","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
-"pthread_exit","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","noreturn","pthread_addr_t"
+"nx_pthread_exit","nuttx/pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","noreturn","pthread_addr_t"
"pthread_getaffinity_np","pthread.h","!defined(CONFIG_DISABLE_PTHREAD) && defined(CONFIG_SMP)","int","pthread_t","size_t","FAR cpu_set_t*"
"pthread_getschedparam","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR int *","FAR struct sched_param *"
"pthread_join","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR pthread_addr_t *"