libc: Move pthread_exit to userspace

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi 2021-04-29 17:56:28 +08:00 committed by patacongo
parent bb9b58bdde
commit 54eef9f639
7 changed files with 166 additions and 10 deletions

View File

@ -149,6 +149,41 @@ int nx_pthread_create(pthread_trampoline_t trampoline, FAR pthread_t *thread,
FAR const pthread_attr_t *attr, FAR const pthread_attr_t *attr,
pthread_startroutine_t entry, pthread_addr_t arg); 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 #undef EXTERN
#ifdef __cplusplus #ifdef __cplusplus
} }

View File

@ -307,7 +307,7 @@ SYSCALL_LOOKUP(telldir, 1)
SYSCALL_LOOKUP(pthread_cond_wait, 2) SYSCALL_LOOKUP(pthread_cond_wait, 2)
SYSCALL_LOOKUP(nx_pthread_create, 5) SYSCALL_LOOKUP(nx_pthread_create, 5)
SYSCALL_LOOKUP(pthread_detach, 1) SYSCALL_LOOKUP(pthread_detach, 1)
SYSCALL_LOOKUP(pthread_exit, 1) SYSCALL_LOOKUP(nx_pthread_exit, 1)
SYSCALL_LOOKUP(pthread_getschedparam, 3) SYSCALL_LOOKUP(pthread_getschedparam, 3)
SYSCALL_LOOKUP(pthread_join, 2) SYSCALL_LOOKUP(pthread_join, 2)
SYSCALL_LOOKUP(pthread_mutex_destroy, 1) SYSCALL_LOOKUP(pthread_mutex_destroy, 1)
@ -330,6 +330,7 @@ SYSCALL_LOOKUP(telldir, 1)
#ifdef CONFIG_PTHREAD_CLEANUP #ifdef CONFIG_PTHREAD_CLEANUP
SYSCALL_LOOKUP(pthread_cleanup_push, 2) SYSCALL_LOOKUP(pthread_cleanup_push, 2)
SYSCALL_LOOKUP(pthread_cleanup_pop, 1) SYSCALL_LOOKUP(pthread_cleanup_pop, 1)
SYSCALL_LOOKUP(pthread_cleanup_poplist, 1)
#endif #endif
#endif #endif

View File

@ -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_init.c pthread_condattr_destroy.c
CSRCS += pthread_condattr_setclock.c pthread_condattr_getclock.c CSRCS += pthread_condattr_setclock.c pthread_condattr_getclock.c
CSRCS += pthread_condinit.c pthread_conddestroy.c pthread_condtimedwait.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_get_stackaddr_np.c pthread_get_stacksize_np.c
CSRCS += pthread_mutexattr_init.c pthread_mutexattr_destroy.c CSRCS += pthread_mutexattr_init.c pthread_mutexattr_destroy.c
CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c CSRCS += pthread_mutexattr_getpshared.c pthread_mutexattr_setpshared.c

View File

@ -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();
}

View File

@ -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 */ #endif /* CONFIG_PTHREAD_CLEANUP */

View File

@ -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(); FAR struct tcb_s *tcb = this_task();
sigset_t set = ALL_SIGNAL_SET; sigset_t set = ALL_SIGNAL_SET;
@ -87,12 +87,6 @@ void pthread_exit(FAR void *exit_value)
tcb->cpcount = 0; tcb->cpcount = 0;
#endif #endif
#ifdef CONFIG_PTHREAD_CLEANUP
/* Perform any stack pthread clean-up callbacks */
pthread_cleanup_popall(tcb);
#endif
/* Complete pending join operations */ /* Complete pending join operations */
status = pthread_completejoin(getpid(), exit_value); status = pthread_completejoin(getpid(), exit_value);

View File

@ -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 *" "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_cancel","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t"
"pthread_cleanup_pop","pthread.h","defined(CONFIG_PTHREAD_CLEANUP)","void","int" "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_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_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_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_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_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_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_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_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 *" "pthread_join","pthread.h","!defined(CONFIG_DISABLE_PTHREAD)","int","pthread_t","FAR pthread_addr_t *"

Can't render this file because it has a wrong number of fields in line 2.