Merge pull request #2314 from RT-Thread/fix_pthread

Fix pthread
This commit is contained in:
Bernard Xiong 2019-02-09 10:58:16 +08:00 committed by GitHub
commit 821c81e21a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 62 additions and 33 deletions

View File

@ -7,6 +7,7 @@
* Date Author Notes * Date Author Notes
* 2018-01-26 Bernard Fix pthread_detach issue for a none-joinable * 2018-01-26 Bernard Fix pthread_detach issue for a none-joinable
* thread. * thread.
* 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
*/ */
#include <pthread.h> #include <pthread.h>
@ -26,6 +27,32 @@ int pthread_system_init(void)
} }
INIT_COMPONENT_EXPORT(pthread_system_init); INIT_COMPONENT_EXPORT(pthread_system_init);
static void _pthread_destroy(_pthread_data_t *ptd)
{
/* delete joinable semaphore */
if (ptd->joinable_sem != RT_NULL)
rt_sem_delete(ptd->joinable_sem);
/* release thread resource */
if (ptd->attr.stack_base == RT_NULL)
{
/* release thread allocated stack */
rt_free(ptd->tid->stack_addr);
}
/* clean stack addr pointer */
ptd->tid->stack_addr = RT_NULL;
/*
* if this thread create the local thread data,
* delete it
*/
if (ptd->tls != RT_NULL) rt_free(ptd->tls);
rt_free(ptd->tid);
rt_free(ptd);
return;
}
static void _pthread_cleanup(rt_thread_t tid) static void _pthread_cleanup(rt_thread_t tid)
{ {
_pthread_data_t *ptd; _pthread_data_t *ptd;
@ -40,14 +67,14 @@ static void _pthread_cleanup(rt_thread_t tid)
else else
{ {
/* release pthread resource */ /* release pthread resource */
pthread_detach(tid); _pthread_destroy(ptd);
} }
} }
static void pthread_entry_stub(void *parameter) static void pthread_entry_stub(void *parameter)
{ {
_pthread_data_t *ptd;
void *value; void *value;
_pthread_data_t *ptd;
ptd = (_pthread_data_t *)parameter; ptd = (_pthread_data_t *)parameter;
@ -181,60 +208,60 @@ RTM_EXPORT(pthread_create);
int pthread_detach(pthread_t thread) int pthread_detach(pthread_t thread)
{ {
_pthread_data_t *ptd; int ret = 0;
_pthread_data_t *ptd = _pthread_get_data(thread);
ptd = _pthread_get_data(thread);
rt_enter_critical();
if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED) if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED)
{ {
/* The implementation has detected that the value specified by thread does not refer /* The implementation has detected that the value specified by thread does not refer
* to a joinable thread. * to a joinable thread.
*/ */
return EINVAL; ret = EINVAL;
goto __exit;
} }
if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE) if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{ {
/* delete joinable semaphore */ /* this defunct pthread is not handled by idle */
if (ptd->joinable_sem != RT_NULL) if (rt_sem_trytake(ptd->joinable_sem) != RT_EOK)
rt_sem_delete(ptd->joinable_sem);
/* detach thread object */
rt_thread_detach(ptd->tid);
/* release thread resource */
if (ptd->attr.stack_base == RT_NULL)
{ {
/* release thread allocated stack */ rt_sem_release(ptd->joinable_sem);
rt_free(ptd->tid->stack_addr);
/* change to detach state */
ptd->attr.detachstate = PTHREAD_CREATE_DETACHED;
/* detach joinable semaphore */
if (ptd->joinable_sem)
{
rt_sem_delete(ptd->joinable_sem);
ptd->joinable_sem = RT_NULL;
}
} }
else else
{ {
/* clean stack addr pointer */ /* destroy this pthread */
ptd->tid->stack_addr = RT_NULL; _pthread_destroy(ptd);
} }
/* goto __exit;
* if this thread create the local thread data,
* delete it
*/
if (ptd->tls != RT_NULL)
rt_free(ptd->tls);
rt_free(ptd->tid);
rt_free(ptd);
} }
else else
{ {
rt_enter_critical();
/* change to detach state */ /* change to detach state */
ptd->attr.detachstate = PTHREAD_CREATE_DETACHED; ptd->attr.detachstate = PTHREAD_CREATE_DETACHED;
/* detach joinable semaphore */ /* detach joinable semaphore */
rt_sem_delete(ptd->joinable_sem); if (ptd->joinable_sem)
ptd->joinable_sem = RT_NULL; {
rt_exit_critical(); rt_sem_delete(ptd->joinable_sem);
ptd->joinable_sem = RT_NULL;
}
} }
return 0; __exit:
rt_exit_critical();
return ret;
} }
RTM_EXPORT(pthread_detach); RTM_EXPORT(pthread_detach);
@ -260,8 +287,8 @@ int pthread_join(pthread_t thread, void **value_ptr)
if (value_ptr != RT_NULL) if (value_ptr != RT_NULL)
*value_ptr = ptd->return_value; *value_ptr = ptd->return_value;
/* release resource */ /* destroy this pthread */
pthread_detach(thread); _pthread_destroy(ptd);
} }
else else
{ {

View File

@ -193,6 +193,8 @@ void rt_thread_idle_excute(void)
/* if it's a system object, not delete it */ /* if it's a system object, not delete it */
if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
{ {
/* detach this object */
rt_object_detach((rt_object_t)thread);
/* unlock scheduler */ /* unlock scheduler */
rt_exit_critical(); rt_exit_critical();