[pthread] Fix pthread_detach issue for a none-joinable thread
This commit is contained in:
parent
55e2fabbc5
commit
84a44e58dd
|
@ -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);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue