pthread: Avoid recursive pthread_exit call

pthread_exit will be called recursive when pthread_cancel
or other cleanup operation with syscalls that support
cancellation, to avoid this by mark current tcb flag as
TCB_FLAG_CANCEL_DOING instead of TCB_FLAG_CANCEL_PENDING.

Signed-off-by: Huang Qi <huangqi3@xiaomi.com>
This commit is contained in:
Huang Qi 2021-05-17 17:31:13 +08:00 committed by patacongo
parent 9dbeaa3b1f
commit a2941532bd
5 changed files with 10 additions and 16 deletions

View File

@ -84,10 +84,9 @@ int pthread_cancel(pthread_t thread)
if (tcb == this_task()) if (tcb == this_task())
{ {
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
tcb->flags |= TCB_FLAG_CANCEL_DOING; tcb->flags |= TCB_FLAG_CANCEL_DOING;
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
PTHREAD_CANCELED); PTHREAD_CANCELED);
#else #else

View File

@ -224,10 +224,9 @@ static void nxsig_abnormal_termination(int signo)
* REVISIT: This will not work if HAVE_GROUP_MEMBERS is not set. * REVISIT: This will not work if HAVE_GROUP_MEMBERS is not set.
*/ */
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
rtcb->flags &= ~TCB_FLAG_CANCEL_PENDING; rtcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
rtcb->flags |= TCB_FLAG_CANCEL_DOING; rtcb->flags |= TCB_FLAG_CANCEL_DOING;
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
up_pthread_exit(((FAR struct pthread_tcb_s *)rtcb)->exit, up_pthread_exit(((FAR struct pthread_tcb_s *)rtcb)->exit,
PTHREAD_CANCELED); PTHREAD_CANCELED);
#else #else

View File

@ -140,10 +140,9 @@ bool enter_cancellation_point(void)
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
TCB_FLAG_TTYPE_PTHREAD) TCB_FLAG_TTYPE_PTHREAD)
{ {
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
tcb->flags |= TCB_FLAG_CANCEL_DOING; tcb->flags |= TCB_FLAG_CANCEL_DOING;
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
PTHREAD_CANCELED); PTHREAD_CANCELED);
#else #else
@ -235,10 +234,9 @@ void leave_cancellation_point(void)
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
TCB_FLAG_TTYPE_PTHREAD) TCB_FLAG_TTYPE_PTHREAD)
{ {
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
tcb->flags |= TCB_FLAG_CANCEL_DOING; tcb->flags |= TCB_FLAG_CANCEL_DOING;
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
PTHREAD_CANCELED); PTHREAD_CANCELED);
#else #else

View File

@ -112,10 +112,9 @@ int task_setcancelstate(int state, FAR int *oldstate)
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == if ((tcb->flags & TCB_FLAG_TTYPE_MASK) ==
TCB_FLAG_TTYPE_PTHREAD) TCB_FLAG_TTYPE_PTHREAD)
{ {
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
tcb->flags |= TCB_FLAG_CANCEL_DOING; tcb->flags |= TCB_FLAG_CANCEL_DOING;
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit, up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
PTHREAD_CANCELED); PTHREAD_CANCELED);
#else #else

View File

@ -100,14 +100,13 @@ int task_setcanceltype(int type, FAR int *oldtype)
#ifndef CONFIG_DISABLE_PTHREAD #ifndef CONFIG_DISABLE_PTHREAD
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD) if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
{ {
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING;
tcb->flags |= TCB_FLAG_CANCEL_DOING;
#if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__) #if !defined(CONFIG_BUILD_FLAT) && defined(__KERNEL__)
tcb->flags &= ~TCB_FLAG_CANCEL_PENDING; up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
tcb->flags |= TCB_FLAG_CANCEL_DOING; PTHREAD_CANCELED);
up_pthread_exit(((FAR struct pthread_tcb_s *)tcb)->exit,
PTHREAD_CANCELED);
#else #else
pthread_exit(PTHREAD_CANCELED); pthread_exit(PTHREAD_CANCELED);
#endif #endif
} }
else else