summaryrefslogtreecommitdiff
path: root/components/libc
diff options
context:
space:
mode:
authorBernard Xiong <[email protected]>2019-02-20 04:54:10 +0800
committerGitHub <[email protected]>2019-02-20 04:54:10 +0800
commit745659c42b714c7b4c7b6de7acdbbcf26ba4fc5e (patch)
treeaf662f13d4064fe9df4da8ab3202a453cd47dfe3 /components/libc
parent8ace8be30e014ed67887fcba893624400c8a1154 (diff)
parentc231565610fed352558c913ea0afd6faeca08824 (diff)
Merge pull request #2351 from armink/lts-v3.1.x
Sync from master (6a150c0963d4db931f71c5716c1811b672a19af3)
Diffstat (limited to 'components/libc')
-rw-r--r--components/libc/pthreads/pthread.c99
1 files changed, 60 insertions, 39 deletions
diff --git a/components/libc/pthreads/pthread.c b/components/libc/pthreads/pthread.c
index 62c110499d..55f46c0caa 100644
--- a/components/libc/pthreads/pthread.c
+++ b/components/libc/pthreads/pthread.c
@@ -7,6 +7,7 @@
* Date Author Notes
* 2018-01-26 Bernard Fix pthread_detach issue for a none-joinable
* thread.
+ * 2019-02-07 Bernard Add _pthread_destroy to release pthread resource.
*/
#include <pthread.h>
@@ -26,6 +27,32 @@ int pthread_system_init(void)
}
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)
{
_pthread_data_t *ptd;
@@ -40,14 +67,14 @@ static void _pthread_cleanup(rt_thread_t tid)
else
{
/* release pthread resource */
- pthread_detach(tid);
+ _pthread_destroy(ptd);
}
}
static void pthread_entry_stub(void *parameter)
{
- _pthread_data_t *ptd;
void *value;
+ _pthread_data_t *ptd;
ptd = (_pthread_data_t *)parameter;
@@ -181,60 +208,60 @@ RTM_EXPORT(pthread_create);
int pthread_detach(pthread_t thread)
{
- _pthread_data_t *ptd;
-
- ptd = _pthread_get_data(thread);
+ int ret = 0;
+ _pthread_data_t *ptd = _pthread_get_data(thread);
+ rt_enter_critical();
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;
+ ret = EINVAL;
+ goto __exit;
}
if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
{
- /* delete joinable semaphore */
- if (ptd->joinable_sem != RT_NULL)
- rt_sem_delete(ptd->joinable_sem);
- /* detach thread object */
- rt_thread_detach(ptd->tid);
-
- /* release thread resource */
- if (ptd->attr.stack_base == RT_NULL)
+ /* this defunct pthread is not handled by idle */
+ if (rt_sem_trytake(ptd->joinable_sem) != RT_EOK)
{
- /* release thread allocated stack */
- rt_free(ptd->tid->stack_addr);
+ 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
{
- /* clean stack addr pointer */
- ptd->tid->stack_addr = RT_NULL;
+ /* destroy this pthread */
+ _pthread_destroy(ptd);
}
- /*
- * 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);
+ goto __exit;
}
else
{
- rt_enter_critical();
/* change to detach state */
ptd->attr.detachstate = PTHREAD_CREATE_DETACHED;
/* detach joinable semaphore */
- rt_sem_delete(ptd->joinable_sem);
- ptd->joinable_sem = RT_NULL;
- rt_exit_critical();
+ if (ptd->joinable_sem)
+ {
+ rt_sem_delete(ptd->joinable_sem);
+ ptd->joinable_sem = RT_NULL;
+ }
}
- return 0;
+__exit:
+ rt_exit_critical();
+ return ret;
}
RTM_EXPORT(pthread_detach);
@@ -260,8 +287,8 @@ int pthread_join(pthread_t thread, void **value_ptr)
if (value_ptr != RT_NULL)
*value_ptr = ptd->return_value;
- /* release resource */
- pthread_detach(thread);
+ /* destroy this pthread */
+ _pthread_destroy(ptd);
}
else
{
@@ -319,12 +346,6 @@ void pthread_exit(void *value)
ptd->tls = RT_NULL;
}
- if (ptd->attr.detachstate == PTHREAD_CREATE_JOINABLE)
- {
- /* release the joinable pthread */
- rt_sem_release(ptd->joinable_sem);
- }
-
/* detach thread */
rt_thread_detach(ptd->tid);
/* reschedule thread */