[modify] the recycle logic about resource of pthread.

This commit is contained in:
liuxianliang 2022-05-10 21:51:30 +08:00 committed by guo
parent 9ab2094ef6
commit 9f5a9b6bc8
3 changed files with 120 additions and 109 deletions

View File

@ -20,8 +20,13 @@ void __rt_libc_exit(int status)
if (self != RT_NULL) if (self != RT_NULL)
{ {
#ifdef RT_USING_PTHREADS
extern void pthread_exit(void *value);
pthread_exit((void *)status);
#else
LOG_E("thread:%s exit:%d!", self->name, status); LOG_E("thread:%s exit:%d!", self->name, status);
rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL); rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
#endif
} }
} }

View File

@ -8,6 +8,7 @@
* 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. * 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
* 2022-05-10 xiangxistu Modify the recycle logic about resource of pthread.
*/ */
#include <rthw.h> #include <rthw.h>
@ -87,15 +88,18 @@ pthread_t _pthread_data_create(void)
return index; return index;
} }
void _pthread_data_destroy(pthread_t pth) void _pthread_data_destroy(_pthread_data_t *ptd)
{ {
RT_DECLARE_SPINLOCK(pth_lock); RT_DECLARE_SPINLOCK(pth_lock);
extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];
_pthread_data_t *ptd = _pthread_get_data(pth); pthread_t pth;
if (ptd) if (ptd)
{ {
/* destruct thread local key */ /* if this thread create the local thread data,
* destruct thread local key
*/
if (ptd->tls != RT_NULL) if (ptd->tls != RT_NULL)
{ {
void *data; void *data;
@ -115,6 +119,7 @@ void _pthread_data_destroy(pthread_t pth)
ptd->tls = RT_NULL; ptd->tls = RT_NULL;
} }
pth = _pthread_data_get_pth(ptd);
/* remove from pthread table */ /* remove from pthread table */
rt_hw_spin_lock(&pth_lock); rt_hw_spin_lock(&pth_lock);
pth_table[pth] = NULL; pth_table[pth] = NULL;
@ -122,66 +127,32 @@ void _pthread_data_destroy(pthread_t pth)
/* delete joinable semaphore */ /* delete joinable semaphore */
if (ptd->joinable_sem != RT_NULL) if (ptd->joinable_sem != RT_NULL)
{
rt_sem_delete(ptd->joinable_sem); rt_sem_delete(ptd->joinable_sem);
ptd->joinable_sem = RT_NULL;
/* release thread resource */
if (ptd->attr.stackaddr == RT_NULL)
{
/* release thread allocated stack */
if (ptd->tid)
{
rt_free(ptd->tid->stack_addr);
} }
}
/* clean stack addr pointer */
if (ptd->tid)
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);
/* clean magic */ /* clean magic */
ptd->magic = 0x0; ptd->magic = 0x0;
/* clear the "ptd->tid->user_data" */
ptd->tid->user_data = RT_NULL;
/* free ptd */ /* free ptd */
rt_free(ptd); rt_free(ptd);
} }
} }
static void _pthread_destroy(_pthread_data_t *ptd)
{
pthread_t pth = _pthread_data_get_pth(ptd);
if (pth != PTHREAD_NUM_MAX)
{
_pthread_data_destroy(pth);
}
return;
}
static void _pthread_cleanup(rt_thread_t tid) static void _pthread_cleanup(rt_thread_t tid)
{ {
_pthread_data_t *ptd;
/* get pthread data from user data of thread */
ptd = (_pthread_data_t *)tid->user_data;
RT_ASSERT(ptd != RT_NULL);
/* clear cleanup function */ /* clear cleanup function */
tid->cleanup = RT_NULL; tid->cleanup = RT_NULL;
if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
{ /* restore tid stack */
rt_sem_release(ptd->joinable_sem); rt_free(tid->stack_addr);
}
else /* restore tid control block */
{ rt_free(tid);
/* release pthread resource */
_pthread_destroy(ptd);
}
} }
static void pthread_entry_stub(void *parameter) static void pthread_entry_stub(void *parameter)
@ -193,8 +164,19 @@ static void pthread_entry_stub(void *parameter)
/* execute pthread entry */ /* execute pthread entry */
value = ptd->thread_entry(ptd->thread_parameter); value = ptd->thread_entry(ptd->thread_parameter);
/* According to "detachstate" to whether or not to recycle resource immediately */
if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
{
/* set value */ /* set value */
ptd->return_value = value; ptd->return_value = value;
rt_sem_release(ptd->joinable_sem);
}
else
{
/* release pthread resource */
_pthread_data_destroy(ptd);
}
} }
int pthread_create(pthread_t *pid, int pthread_create(pthread_t *pid,
@ -311,7 +293,9 @@ int pthread_create(pthread_t *pid,
__exit: __exit:
if (pth_id != PTHREAD_NUM_MAX) if (pth_id != PTHREAD_NUM_MAX)
_pthread_data_destroy(pth_id); {
_pthread_data_destroy(ptd);
}
return ret; return ret;
} }
RTM_EXPORT(pthread_create); RTM_EXPORT(pthread_create);
@ -327,7 +311,6 @@ int pthread_detach(pthread_t thread)
goto __exit; goto __exit;
} }
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
@ -338,28 +321,9 @@ int pthread_detach(pthread_t thread)
} }
if ((ptd->tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE) if ((ptd->tid->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{
/* this defunct pthread is not handled by idle */
if (rt_sem_trytake(ptd->joinable_sem) != RT_EOK)
{
rt_sem_release(ptd->joinable_sem);
/* 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
{ {
/* destroy this pthread */ /* destroy this pthread */
_pthread_destroy(ptd); _pthread_data_destroy(ptd);
}
goto __exit; goto __exit;
} }
else else
@ -376,7 +340,6 @@ int pthread_detach(pthread_t thread)
} }
__exit: __exit:
rt_exit_critical();
return ret; return ret;
} }
RTM_EXPORT(pthread_detach); RTM_EXPORT(pthread_detach);
@ -412,7 +375,7 @@ int pthread_join(pthread_t thread, void **value_ptr)
*value_ptr = ptd->return_value; *value_ptr = ptd->return_value;
/* destroy this pthread */ /* destroy this pthread */
_pthread_destroy(ptd); _pthread_data_destroy(ptd);
} }
else else
{ {
@ -507,9 +470,12 @@ void pthread_exit(void *value)
{ {
_pthread_data_t *ptd; _pthread_data_t *ptd;
_pthread_cleanup_t *cleanup; _pthread_cleanup_t *cleanup;
extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX]; rt_thread_t tid;
if (rt_thread_self() == NULL) return; if (rt_thread_self() == RT_NULL)
{
return;
}
/* get pthread data from user data of thread */ /* get pthread data from user data of thread */
ptd = (_pthread_data_t *)rt_thread_self()->user_data; ptd = (_pthread_data_t *)rt_thread_self()->user_data;
@ -521,7 +487,10 @@ void pthread_exit(void *value)
ptd->return_value = value; ptd->return_value = value;
rt_exit_critical(); rt_exit_critical();
/* invoke pushed cleanup */ /*
* When use pthread_exit to exit.
* invoke pushed cleanup
*/
while (ptd->cleanup != RT_NULL) while (ptd->cleanup != RT_NULL)
{ {
cleanup = ptd->cleanup; cleanup = ptd->cleanup;
@ -532,29 +501,30 @@ void pthread_exit(void *value)
rt_free(cleanup); rt_free(cleanup);
} }
/* destruct thread local key */ /* get the info aboult "tid" early */
if (ptd->tls != RT_NULL) tid = ptd->tid;
{
void *data;
rt_uint32_t index;
for (index = 0; index < PTHREAD_KEY_MAX; index ++) /* According to "detachstate" to whether or not to recycle resource immediately */
if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
{ {
if (_thread_keys[index].is_used) /* set value */
{ rt_sem_release(ptd->joinable_sem);
data = ptd->tls[index];
if (data && _thread_keys[index].destructor)
_thread_keys[index].destructor(data);
} }
else
{
/* release pthread resource */
_pthread_data_destroy(ptd);
} }
/* release tls area */ /*
rt_free(ptd->tls); * second: detach thread.
ptd->tls = RT_NULL; * this thread will be removed from scheduler list
} * and because there is a cleanup function in the
* thread (pthread_cleanup), it will move to defunct
* thread list and wait for handling in idle thread.
*/
rt_thread_detach(tid);
/* detach thread */
rt_thread_detach(ptd->tid);
/* reschedule thread */ /* reschedule thread */
rt_schedule(); rt_schedule();
} }
@ -765,6 +735,8 @@ RTM_EXPORT(pthread_testcancel);
int pthread_cancel(pthread_t thread) int pthread_cancel(pthread_t thread)
{ {
_pthread_data_t *ptd; _pthread_data_t *ptd;
_pthread_cleanup_t *cleanup;
rt_thread_t tid;
/* get posix thread data */ /* get posix thread data */
ptd = _pthread_get_data(thread); ptd = _pthread_get_data(thread);
@ -772,6 +744,7 @@ int pthread_cancel(pthread_t thread)
{ {
return EINVAL; return EINVAL;
} }
tid = ptd->tid;
/* cancel self */ /* cancel self */
if (ptd->tid == rt_thread_self()) if (ptd->tid == rt_thread_self())
@ -784,13 +757,39 @@ int pthread_cancel(pthread_t thread)
if (ptd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) if (ptd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
{ {
/* /*
* to detach thread. * When use pthread_cancel to exit.
* invoke pushed cleanup
*/
while (ptd->cleanup != RT_NULL)
{
cleanup = ptd->cleanup;
ptd->cleanup = cleanup->next;
cleanup->cleanup_func(cleanup->parameter);
/* release this cleanup function */
rt_free(cleanup);
}
/* According to "detachstate" to whether or not to recycle resource immediately */
if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
{
/* set value */
rt_sem_release(ptd->joinable_sem);
}
else
{
/* release pthread resource */
_pthread_data_destroy(ptd);
}
/*
* second: detach thread.
* this thread will be removed from scheduler list * this thread will be removed from scheduler list
* and because there is a cleanup function in the * and because there is a cleanup function in the
* thread (pthread_cleanup), it will move to defunct * thread (pthread_cleanup), it will move to defunct
* thread list and wait for handling in idle thread. * thread list and wait for handling in idle thread.
*/ */
rt_thread_detach(ptd->tid); rt_thread_detach(tid);
} }
} }

View File

@ -194,6 +194,7 @@ static void rt_defunct_execute(void)
while (1) while (1)
{ {
rt_thread_t thread; rt_thread_t thread;
rt_bool_t object_is_systemobject;
void (*cleanup)(struct rt_thread *tid); void (*cleanup)(struct rt_thread *tid);
#ifdef RT_USING_MODULE #ifdef RT_USING_MODULE
@ -212,32 +213,38 @@ static void rt_defunct_execute(void)
dlmodule_destroy(module); dlmodule_destroy(module);
} }
#endif #endif
/* invoke thread cleanup */
cleanup = thread->cleanup;
if (cleanup != RT_NULL)
{
cleanup(thread);
}
#ifdef RT_USING_SIGNALS #ifdef RT_USING_SIGNALS
rt_thread_free_sig(thread); rt_thread_free_sig(thread);
#endif #endif
/* store the point of "thread->cleanup" avoid to lose */
cleanup = thread->cleanup;
/* 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) object_is_systemobject = rt_object_is_systemobject((rt_object_t)thread);
if (object_is_systemobject == RT_TRUE)
{ {
/* detach this object */ /* detach this object */
rt_object_detach((rt_object_t)thread); rt_object_detach((rt_object_t)thread);
} }
else
/* invoke thread cleanup */
if (cleanup != RT_NULL)
{ {
cleanup(thread);
}
#ifdef RT_USING_HEAP #ifdef RT_USING_HEAP
/* if need free, delete it */
if (object_is_systemobject == RT_FALSE)
{
/* release thread's stack */ /* release thread's stack */
RT_KERNEL_FREE(thread->stack_addr); RT_KERNEL_FREE(thread->stack_addr);
/* delete thread object */ /* delete thread object */
rt_object_delete((rt_object_t)thread); rt_object_delete((rt_object_t)thread);
#endif
} }
#endif
} }
} }