posix: pthread: implement non-standard try-join and timed-join
These functions can be used to join pthreads in a non-standard way. The function pthread_tryjoin will not block and simply test whether the thread has exited already. The function pthread_timed_join will only block until the specified time. The functions are wrappers for calling the k_thread_join with timeout K_NO_WAIT and with a specific timeout as opposed to calling it with K_FOREVER. Signed-off-by: Cla Galliard <clamattia@gmail.com>
This commit is contained in:
parent
7bfd5c0a10
commit
a71e0f2a29
2 changed files with 55 additions and 8 deletions
|
@ -429,6 +429,8 @@ int pthread_attr_setinheritsched(pthread_attr_t *attr, int inheritsched);
|
||||||
int pthread_once(pthread_once_t *once, void (*initFunc)(void));
|
int pthread_once(pthread_once_t *once, void (*initFunc)(void));
|
||||||
#endif
|
#endif
|
||||||
FUNC_NORETURN void pthread_exit(void *retval);
|
FUNC_NORETURN void pthread_exit(void *retval);
|
||||||
|
int pthread_timedjoin_np(pthread_t thread, void **status, const struct timespec *abstime);
|
||||||
|
int pthread_tryjoin_np(pthread_t thread, void **status);
|
||||||
int pthread_join(pthread_t thread, void **status);
|
int pthread_join(pthread_t thread, void **status);
|
||||||
int pthread_cancel(pthread_t pthread);
|
int pthread_cancel(pthread_t pthread);
|
||||||
int pthread_detach(pthread_t thread);
|
int pthread_detach(pthread_t thread);
|
||||||
|
|
|
@ -81,6 +81,7 @@ BUILD_ASSERT((PTHREAD_CANCEL_ENABLE == 0 || PTHREAD_CANCEL_DISABLE == 0) &&
|
||||||
BUILD_ASSERT(CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS + CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS <=
|
BUILD_ASSERT(CONFIG_POSIX_PTHREAD_ATTR_STACKSIZE_BITS + CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_BITS <=
|
||||||
32);
|
32);
|
||||||
|
|
||||||
|
int64_t timespec_to_timeoutms(const struct timespec *abstime);
|
||||||
static void posix_thread_recycle(void);
|
static void posix_thread_recycle(void);
|
||||||
static sys_dlist_t posix_thread_q[] = {
|
static sys_dlist_t posix_thread_q[] = {
|
||||||
SYS_DLIST_STATIC_INIT(&posix_thread_q[POSIX_THREAD_READY_Q]),
|
SYS_DLIST_STATIC_INIT(&posix_thread_q[POSIX_THREAD_READY_Q]),
|
||||||
|
@ -1061,12 +1062,7 @@ void pthread_exit(void *retval)
|
||||||
CODE_UNREACHABLE;
|
CODE_UNREACHABLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static int pthread_timedjoin_internal(pthread_t pthread, void **status, k_timeout_t timeout)
|
||||||
* @brief Wait for a thread termination.
|
|
||||||
*
|
|
||||||
* See IEEE 1003.1
|
|
||||||
*/
|
|
||||||
int pthread_join(pthread_t pthread, void **status)
|
|
||||||
{
|
{
|
||||||
int ret = ESRCH;
|
int ret = ESRCH;
|
||||||
struct posix_thread *t = NULL;
|
struct posix_thread *t = NULL;
|
||||||
|
@ -1115,8 +1111,19 @@ int pthread_join(pthread_t pthread, void **status)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = k_thread_join(&t->thread, K_FOREVER);
|
ret = k_thread_join(&t->thread, timeout);
|
||||||
/* other possibilities? */
|
if (ret != 0) {
|
||||||
|
/* when joining failed, ensure that the thread can be joined later */
|
||||||
|
SYS_SEM_LOCK(&pthread_pool_lock) {
|
||||||
|
t->attr.detachstate = PTHREAD_CREATE_JOINABLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ret == -EBUSY) {
|
||||||
|
return EBUSY;
|
||||||
|
} else if (ret == -EAGAIN) {
|
||||||
|
return ETIMEDOUT;
|
||||||
|
}
|
||||||
|
/* Can only be ok or -EDEADLK, which should never occur for pthreads */
|
||||||
__ASSERT_NO_MSG(ret == 0);
|
__ASSERT_NO_MSG(ret == 0);
|
||||||
|
|
||||||
LOG_DBG("Joined pthread %p", &t->thread);
|
LOG_DBG("Joined pthread %p", &t->thread);
|
||||||
|
@ -1131,6 +1138,44 @@ int pthread_join(pthread_t pthread, void **status)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Await a thread termination with timeout.
|
||||||
|
*
|
||||||
|
* Non-portable GNU extension of IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_timedjoin_np(pthread_t pthread, void **status, const struct timespec *abstime)
|
||||||
|
{
|
||||||
|
if (abstime == NULL) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abstime->tv_sec < 0 || abstime->tv_nsec < 0 || abstime->tv_nsec >= NSEC_PER_SEC) {
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pthread_timedjoin_internal(pthread, status, K_MSEC(timespec_to_timeoutms(abstime)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check a thread for termination.
|
||||||
|
*
|
||||||
|
* Non-portable GNU extension of IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_tryjoin_np(pthread_t pthread, void **status)
|
||||||
|
{
|
||||||
|
return pthread_timedjoin_internal(pthread, status, K_NO_WAIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Await a thread termination.
|
||||||
|
*
|
||||||
|
* See IEEE 1003.1
|
||||||
|
*/
|
||||||
|
int pthread_join(pthread_t pthread, void **status)
|
||||||
|
{
|
||||||
|
return pthread_timedjoin_internal(pthread, status, K_FOREVER);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Detach a thread.
|
* @brief Detach a thread.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue