[pthread] Fix pthread_detach issue for a none-joinable thread

This commit is contained in:
Bernard Xiong 2018-02-07 19:55:26 +08:00
parent 55e2fabbc5
commit 84a44e58dd
1 changed files with 50 additions and 28 deletions

View File

@ -1,7 +1,7 @@
/* /*
* File : pthread.c * File : pthread.c
* This file is part of RT-Thread RTOS * This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2012, RT-Thread Development Team * COPYRIGHT (C) 2012 - 2017, RT-Thread Development Team
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,6 +19,8 @@
* *
* Change Logs: * Change Logs:
* Date Author Notes * Date Author Notes
* 2018-01-26 Bernard Fix pthread_detach issue for a none-joinable
* thread.
*/ */
#include <pthread.h> #include <pthread.h>
@ -61,7 +63,7 @@ static void pthread_entry_stub(void *parameter)
_pthread_data_t *ptd; _pthread_data_t *ptd;
void *value; void *value;
ptd = (_pthread_data_t*)parameter; ptd = (_pthread_data_t *)parameter;
/* execute pthread entry */ /* execute pthread entry */
value = ptd->thread_entry(ptd->thread_parameter); value = ptd->thread_entry(ptd->thread_parameter);
@ -70,8 +72,8 @@ static void pthread_entry_stub(void *parameter)
} }
int pthread_create(pthread_t *tid, int pthread_create(pthread_t *tid,
const pthread_attr_t *attr, const pthread_attr_t *attr,
void *(*start) (void *), void *parameter) void *(*start)(void *), void *parameter)
{ {
int result; int result;
void *stack; void *stack;
@ -83,7 +85,7 @@ int pthread_create(pthread_t *tid,
RT_ASSERT(tid != RT_NULL); RT_ASSERT(tid != RT_NULL);
/* allocate posix thread data */ /* allocate posix thread data */
ptd = (_pthread_data_t*)rt_malloc(sizeof(_pthread_data_t)); ptd = (_pthread_data_t *)rt_malloc(sizeof(_pthread_data_t));
if (ptd == RT_NULL) if (ptd == RT_NULL)
return ENOMEM; return ENOMEM;
/* clean posix thread data memory */ /* clean posix thread data memory */
@ -94,8 +96,10 @@ int pthread_create(pthread_t *tid,
ptd->magic = PTHREAD_MAGIC; ptd->magic = PTHREAD_MAGIC;
if (attr != RT_NULL) if (attr != RT_NULL)
{
ptd->attr = *attr; ptd->attr = *attr;
else }
else
{ {
/* use default attribute */ /* use default attribute */
pthread_attr_init(&ptd->attr); pthread_attr_init(&ptd->attr);
@ -104,12 +108,14 @@ int pthread_create(pthread_t *tid,
rt_snprintf(name, sizeof(name), "pth%02d", pthread_number ++); rt_snprintf(name, sizeof(name), "pth%02d", pthread_number ++);
if (ptd->attr.stack_base == 0) if (ptd->attr.stack_base == 0)
{ {
stack = (void*)rt_malloc(ptd->attr.stack_size); stack = (void *)rt_malloc(ptd->attr.stack_size);
} }
else else
stack = (void*)(ptd->attr.stack_base); {
stack = (void *)(ptd->attr.stack_base);
}
if (stack == RT_NULL) if (stack == RT_NULL)
{ {
rt_free(ptd); rt_free(ptd);
@ -140,16 +146,18 @@ int pthread_create(pthread_t *tid,
} }
} }
else else
{
ptd->joinable_sem = RT_NULL; ptd->joinable_sem = RT_NULL;
}
/* set parameter */ /* set parameter */
ptd->thread_entry = start; ptd->thread_entry = start;
ptd->thread_parameter = parameter; ptd->thread_parameter = parameter;
/* initial this pthread to system */ /* initial this pthread to system */
if (rt_thread_init(ptd->tid, name, pthread_entry_stub, ptd, if (rt_thread_init(ptd->tid, name, pthread_entry_stub, ptd,
stack, ptd->attr.stack_size, stack, ptd->attr.stack_size,
ptd->attr.priority, 5) != RT_EOK) ptd->attr.priority, 5) != RT_EOK)
{ {
if (ptd->attr.stack_base == 0) if (ptd->attr.stack_base == 0)
rt_free(stack); rt_free(stack);
@ -187,11 +195,19 @@ RTM_EXPORT(pthread_create);
int pthread_detach(pthread_t thread) int pthread_detach(pthread_t thread)
{ {
_pthread_data_t* ptd; _pthread_data_t *ptd;
ptd = _pthread_get_data(thread); ptd = _pthread_get_data(thread);
if ((thread->stat & RT_THREAD_STAT_MASK)== RT_THREAD_CLOSE) if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED)
{
/* The implementation has detected that the value specified by thread does not refer
* to a joinable thread.
*/
return EINVAL;
}
if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{ {
/* delete joinable semaphore */ /* delete joinable semaphore */
if (ptd->joinable_sem != RT_NULL) if (ptd->joinable_sem != RT_NULL)
@ -205,6 +221,11 @@ int pthread_detach(pthread_t thread)
/* release thread allocated stack */ /* release thread allocated stack */
rt_free(ptd->tid->stack_addr); rt_free(ptd->tid->stack_addr);
} }
else
{
/* clean stack addr pointer */
ptd->tid->stack_addr = RT_NULL;
}
/* /*
* if this thread create the local thread data, * if this thread create the local thread data,
@ -231,9 +252,9 @@ int pthread_detach(pthread_t thread)
} }
RTM_EXPORT(pthread_detach); RTM_EXPORT(pthread_detach);
int pthread_join (pthread_t thread, void **value_ptr) int pthread_join(pthread_t thread, void **value_ptr)
{ {
_pthread_data_t* ptd; _pthread_data_t *ptd;
rt_err_t result; rt_err_t result;
if (thread == rt_thread_self()) if (thread == rt_thread_self())
@ -257,13 +278,15 @@ int pthread_join (pthread_t thread, void **value_ptr)
pthread_detach(thread); pthread_detach(thread);
} }
else else
{
return ESRCH; return ESRCH;
}
return 0; return 0;
} }
RTM_EXPORT(pthread_join); RTM_EXPORT(pthread_join);
void pthread_exit (void *value) void pthread_exit(void *value)
{ {
_pthread_data_t *ptd; _pthread_data_t *ptd;
_pthread_cleanup_t *cleanup; _pthread_cleanup_t *cleanup;
@ -294,7 +317,7 @@ void pthread_exit (void *value)
{ {
void *data; void *data;
rt_uint32_t index; rt_uint32_t index;
for (index = 0; index < PTHREAD_KEY_MAX; index ++) for (index = 0; index < PTHREAD_KEY_MAX; index ++)
{ {
if (_thread_keys[index].is_used) if (_thread_keys[index].is_used)
@ -323,7 +346,7 @@ void pthread_exit (void *value)
} }
RTM_EXPORT(pthread_exit); RTM_EXPORT(pthread_exit);
int pthread_once(pthread_once_t *once_control, void (*init_routine) (void)) int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
{ {
RT_ASSERT(once_control != RT_NULL); RT_ASSERT(once_control != RT_NULL);
RT_ASSERT(init_routine != RT_NULL); RT_ASSERT(init_routine != RT_NULL);
@ -354,7 +377,7 @@ int pthread_kill(pthread_t thread, int sig)
#ifdef RT_USING_SIGNALS #ifdef RT_USING_SIGNALS
return rt_thread_kill(thread, sig); return rt_thread_kill(thread, sig);
#else #else
return ENOSYS; return ENOSYS;
#endif #endif
} }
RTM_EXPORT(pthread_kill); RTM_EXPORT(pthread_kill);
@ -362,7 +385,7 @@ RTM_EXPORT(pthread_kill);
#ifdef RT_USING_SIGNALS #ifdef RT_USING_SIGNALS
int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset) int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset)
{ {
return sigprocmask(how, set, oset); return sigprocmask(how, set, oset);
} }
#endif #endif
@ -393,7 +416,7 @@ void pthread_cleanup_pop(int execute)
} }
RTM_EXPORT(pthread_cleanup_pop); RTM_EXPORT(pthread_cleanup_pop);
void pthread_cleanup_push(void (*routine)(void*), void *arg) void pthread_cleanup_push(void (*routine)(void *), void *arg)
{ {
_pthread_data_t *ptd; _pthread_data_t *ptd;
_pthread_cleanup_t *cleanup; _pthread_cleanup_t *cleanup;
@ -473,7 +496,7 @@ int pthread_setcanceltype(int type, int *oldtype)
ptd = _pthread_get_data(rt_thread_self()); ptd = _pthread_get_data(rt_thread_self());
RT_ASSERT(ptd != RT_NULL); RT_ASSERT(ptd != RT_NULL);
if ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS)) if ((type != PTHREAD_CANCEL_DEFERRED) && (type != PTHREAD_CANCEL_ASYNCHRONOUS))
return EINVAL; return EINVAL;
if (oldtype) if (oldtype)
@ -486,8 +509,8 @@ RTM_EXPORT(pthread_setcanceltype);
void pthread_testcancel(void) void pthread_testcancel(void)
{ {
int cancel=0; int cancel = 0;
_pthread_data_t* ptd; _pthread_data_t *ptd;
/* get posix thread data */ /* get posix thread data */
ptd = _pthread_get_data(rt_thread_self()); ptd = _pthread_get_data(rt_thread_self());
@ -496,7 +519,7 @@ void pthread_testcancel(void)
if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE) if (ptd->cancelstate == PTHREAD_CANCEL_ENABLE)
cancel = ptd->canceled; cancel = ptd->canceled;
if (cancel) if (cancel)
pthread_exit((void*)PTHREAD_CANCELED); pthread_exit((void *)PTHREAD_CANCELED);
} }
RTM_EXPORT(pthread_testcancel); RTM_EXPORT(pthread_testcancel);
@ -532,4 +555,3 @@ int pthread_cancel(pthread_t thread)
return 0; return 0;
} }
RTM_EXPORT(pthread_cancel); RTM_EXPORT(pthread_cancel);