summaryrefslogtreecommitdiff
path: root/components
diff options
context:
space:
mode:
authorliuxianliang <[email protected]>2022-05-10 21:51:30 +0800
committerguo <[email protected]>2022-05-18 08:44:30 +0800
commit9f5a9b6bc884ff0640219677e2e18c84db2100c6 (patch)
tree25a4a7521a462c7bfee8e6ef5d1b265c7eb7de0e /components
parent9ab2094ef613873ed86fb5fe675691f7d47a856c (diff)
[modify] the recycle logic about resource of pthread.
Diffstat (limited to 'components')
-rw-r--r--components/libc/compilers/common/stdlib.c5
-rw-r--r--components/libc/posix/pthreads/pthread.c197
2 files changed, 103 insertions, 99 deletions
diff --git a/components/libc/compilers/common/stdlib.c b/components/libc/compilers/common/stdlib.c
index 10da81f30e..12e379acbf 100644
--- a/components/libc/compilers/common/stdlib.c
+++ b/components/libc/compilers/common/stdlib.c
@@ -20,8 +20,13 @@ void __rt_libc_exit(int status)
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);
rt_thread_control(self, RT_THREAD_CTRL_CLOSE, RT_NULL);
+#endif
}
}
diff --git a/components/libc/posix/pthreads/pthread.c b/components/libc/posix/pthreads/pthread.c
index 33f29b62ed..a7dcc9ee7c 100644
--- a/components/libc/posix/pthreads/pthread.c
+++ b/components/libc/posix/pthreads/pthread.c
@@ -8,6 +8,7 @@
* 2018-01-26 Bernard Fix pthread_detach issue for a none-joinable
* thread.
* 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>
@@ -87,15 +88,18 @@ pthread_t _pthread_data_create(void)
return index;
}
-void _pthread_data_destroy(pthread_t pth)
+void _pthread_data_destroy(_pthread_data_t *ptd)
{
RT_DECLARE_SPINLOCK(pth_lock);
extern _pthread_key_data_t _thread_keys[PTHREAD_KEY_MAX];
- _pthread_data_t *ptd = _pthread_get_data(pth);
+ pthread_t pth;
+
if (ptd)
{
- /* destruct thread local key */
+ /* if this thread create the local thread data,
+ * destruct thread local key
+ */
if (ptd->tls != RT_NULL)
{
void *data;
@@ -115,6 +119,7 @@ void _pthread_data_destroy(pthread_t pth)
ptd->tls = RT_NULL;
}
+ pth = _pthread_data_get_pth(ptd);
/* remove from pthread table */
rt_hw_spin_lock(&pth_lock);
pth_table[pth] = NULL;
@@ -122,81 +127,58 @@ void _pthread_data_destroy(pthread_t pth)
/* delete joinable semaphore */
if (ptd->joinable_sem != RT_NULL)
- rt_sem_delete(ptd->joinable_sem);
-
- /* release thread resource */
- if (ptd->attr.stackaddr == RT_NULL)
{
- /* release thread allocated stack */
- if (ptd->tid)
- {
- rt_free(ptd->tid->stack_addr);
- }
+ rt_sem_delete(ptd->joinable_sem);
+ ptd->joinable_sem = RT_NULL;
}
- /* 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 */
ptd->magic = 0x0;
+ /* clear the "ptd->tid->user_data" */
+ ptd->tid->user_data = RT_NULL;
+
/* free ptd */
rt_free(ptd);
}
}
-static void _pthread_destroy(_pthread_data_t *ptd)
+static void _pthread_cleanup(rt_thread_t tid)
{
- pthread_t pth = _pthread_data_get_pth(ptd);
- if (pth != PTHREAD_NUM_MAX)
- {
- _pthread_data_destroy(pth);
- }
+ /* clear cleanup function */
+ tid->cleanup = RT_NULL;
+
+ /* restore tid stack */
+ rt_free(tid->stack_addr);
- return;
+ /* restore tid control block */
+ rt_free(tid);
}
-static void _pthread_cleanup(rt_thread_t tid)
+static void pthread_entry_stub(void *parameter)
{
+ void *value;
_pthread_data_t *ptd;
- /* get pthread data from user data of thread */
- ptd = (_pthread_data_t *)tid->user_data;
- RT_ASSERT(ptd != RT_NULL);
+ ptd = (_pthread_data_t *)parameter;
- /* clear cleanup function */
- tid->cleanup = RT_NULL;
+ /* execute pthread entry */
+ 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 */
+ ptd->return_value = value;
rt_sem_release(ptd->joinable_sem);
}
else
{
/* release pthread resource */
- _pthread_destroy(ptd);
+ _pthread_data_destroy(ptd);
}
}
-static void pthread_entry_stub(void *parameter)
-{
- void *value;
- _pthread_data_t *ptd;
-
- ptd = (_pthread_data_t *)parameter;
-
- /* execute pthread entry */
- value = ptd->thread_entry(ptd->thread_parameter);
- /* set value */
- ptd->return_value = value;
-}
-
int pthread_create(pthread_t *pid,
const pthread_attr_t *attr,
void *(*start)(void *), void *parameter)
@@ -311,7 +293,9 @@ int pthread_create(pthread_t *pid,
__exit:
if (pth_id != PTHREAD_NUM_MAX)
- _pthread_data_destroy(pth_id);
+ {
+ _pthread_data_destroy(ptd);
+ }
return ret;
}
RTM_EXPORT(pthread_create);
@@ -327,7 +311,6 @@ int pthread_detach(pthread_t thread)
goto __exit;
}
- rt_enter_critical();
if (ptd->attr.detachstate == PTHREAD_CREATE_DETACHED)
{
/* The implementation has detected that the value specified by thread does not refer
@@ -339,27 +322,8 @@ int pthread_detach(pthread_t thread)
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 */
- _pthread_destroy(ptd);
- }
-
+ /* destroy this pthread */
+ _pthread_data_destroy(ptd);
goto __exit;
}
else
@@ -376,7 +340,6 @@ int pthread_detach(pthread_t thread)
}
__exit:
- rt_exit_critical();
return ret;
}
RTM_EXPORT(pthread_detach);
@@ -412,7 +375,7 @@ int pthread_join(pthread_t thread, void **value_ptr)
*value_ptr = ptd->return_value;
/* destroy this pthread */
- _pthread_destroy(ptd);
+ _pthread_data_destroy(ptd);
}
else
{
@@ -507,9 +470,12 @@ void pthread_exit(void *value)
{
_pthread_data_t *ptd;
_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 */
ptd = (_pthread_data_t *)rt_thread_self()->user_data;
@@ -521,7 +487,10 @@ void pthread_exit(void *value)
ptd->return_value = value;
rt_exit_critical();
- /* invoke pushed cleanup */
+ /*
+ * When use pthread_exit to exit.
+ * invoke pushed cleanup
+ */
while (ptd->cleanup != RT_NULL)
{
cleanup = ptd->cleanup;
@@ -532,29 +501,30 @@ void pthread_exit(void *value)
rt_free(cleanup);
}
- /* destruct thread local key */
- if (ptd->tls != RT_NULL)
- {
- void *data;
- rt_uint32_t index;
+ /* get the info aboult "tid" early */
+ tid = ptd->tid;
- for (index = 0; index < PTHREAD_KEY_MAX; index ++)
- {
- if (_thread_keys[index].is_used)
- {
- data = ptd->tls[index];
- if (data && _thread_keys[index].destructor)
- _thread_keys[index].destructor(data);
- }
- }
-
- /* release tls area */
- rt_free(ptd->tls);
- ptd->tls = RT_NULL;
+ /* 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);
}
- /* detach thread */
- rt_thread_detach(ptd->tid);
+ /*
+ * second: detach thread.
+ * 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);
+
/* reschedule thread */
rt_schedule();
}
@@ -765,6 +735,8 @@ RTM_EXPORT(pthread_testcancel);
int pthread_cancel(pthread_t thread)
{
_pthread_data_t *ptd;
+ _pthread_cleanup_t *cleanup;
+ rt_thread_t tid;
/* get posix thread data */
ptd = _pthread_get_data(thread);
@@ -772,6 +744,7 @@ int pthread_cancel(pthread_t thread)
{
return EINVAL;
}
+ tid = ptd->tid;
/* cancel self */
if (ptd->tid == rt_thread_self())
@@ -784,13 +757,39 @@ int pthread_cancel(pthread_t thread)
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
* 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(ptd->tid);
+ rt_thread_detach(tid);
}
}