Add function pthread_timedjoin_np, the function is similar with pthread_join
except the function will return ETIMEDOUT if target thread does not exit before specified absolute time passes.
This commit is contained in:
parent
e3843610ee
commit
6459dc5d9d
@ -91,6 +91,7 @@ global:
|
||||
_pthread_getschedparam;
|
||||
_pthread_getspecific;
|
||||
_pthread_join;
|
||||
_pthread_timedjoin_np;
|
||||
_pthread_key_create;
|
||||
_pthread_key_delete;
|
||||
_pthread_kill;
|
||||
@ -246,6 +247,7 @@ global:
|
||||
pthread_getschedparam;
|
||||
pthread_getspecific;
|
||||
pthread_join;
|
||||
pthread_timedjoin_np;
|
||||
pthread_key_create;
|
||||
pthread_key_delete;
|
||||
pthread_kill;
|
||||
|
@ -37,7 +37,10 @@
|
||||
|
||||
#include "thr_private.h"
|
||||
|
||||
static int join_common(pthread_t, void **, const struct timespec *);
|
||||
|
||||
__weak_reference(_pthread_join, pthread_join);
|
||||
__weak_reference(_pthread_timedjoin_np, pthread_timedjoin_np);
|
||||
|
||||
static void backout_join(void *arg)
|
||||
{
|
||||
@ -51,8 +54,27 @@ static void backout_join(void *arg)
|
||||
|
||||
int
|
||||
_pthread_join(pthread_t pthread, void **thread_return)
|
||||
{
|
||||
return (join_common(pthread, thread_return, NULL));
|
||||
}
|
||||
|
||||
int
|
||||
_pthread_timedjoin_np(pthread_t pthread, void **thread_return,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
if (abstime == NULL || abstime->tv_sec < 0 || abstime->tv_nsec < 0 ||
|
||||
abstime->tv_nsec >= 1000000000)
|
||||
return (EINVAL);
|
||||
|
||||
return (join_common(pthread, thread_return, abstime));
|
||||
}
|
||||
|
||||
static int
|
||||
join_common(pthread_t pthread, void **thread_return,
|
||||
const struct timespec *abstime)
|
||||
{
|
||||
struct pthread *curthread = _get_curthread();
|
||||
struct timespec ts, ts2, *tsp;
|
||||
void *tmp;
|
||||
long state;
|
||||
int oldcancel;
|
||||
@ -86,20 +108,38 @@ _pthread_join(pthread_t pthread, void **thread_return)
|
||||
oldcancel = _thr_cancel_enter(curthread);
|
||||
|
||||
while ((state = pthread->state) != PS_DEAD) {
|
||||
_thr_umtx_wait(&pthread->state, state, NULL);
|
||||
if (abstime != NULL) {
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
TIMESPEC_SUB(&ts2, abstime, &ts);
|
||||
if (ts2.tv_sec < 0) {
|
||||
ret = ETIMEDOUT;
|
||||
break;
|
||||
}
|
||||
tsp = &ts2;
|
||||
} else
|
||||
tsp = NULL;
|
||||
ret = _thr_umtx_wait(&pthread->state, state, tsp);
|
||||
if (ret == ETIMEDOUT)
|
||||
break;
|
||||
}
|
||||
|
||||
_thr_cancel_leave(curthread, oldcancel);
|
||||
THR_CLEANUP_POP(curthread, 0);
|
||||
|
||||
tmp = pthread->ret;
|
||||
THREAD_LIST_LOCK(curthread);
|
||||
pthread->tlflags |= TLFLAGS_DETACHED;
|
||||
THR_GCLIST_ADD(pthread);
|
||||
THREAD_LIST_UNLOCK(curthread);
|
||||
|
||||
if (thread_return != NULL)
|
||||
*thread_return = tmp;
|
||||
if (ret == ETIMEDOUT) {
|
||||
THREAD_LIST_LOCK(curthread);
|
||||
pthread->joiner = NULL;
|
||||
THREAD_LIST_UNLOCK(curthread);
|
||||
} else {
|
||||
tmp = pthread->ret;
|
||||
THREAD_LIST_LOCK(curthread);
|
||||
pthread->tlflags |= TLFLAGS_DETACHED;
|
||||
pthread->joiner = NULL;
|
||||
THR_GCLIST_ADD(pthread);
|
||||
THREAD_LIST_UNLOCK(curthread);
|
||||
|
||||
if (thread_return != NULL)
|
||||
*thread_return = tmp;
|
||||
}
|
||||
return (ret);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user