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:
David Xu 2005-10-04 06:15:25 +00:00
parent 67a7895ff4
commit 9e49a2370c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=150901
2 changed files with 51 additions and 9 deletions

View File

@ -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;

View File

@ -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);
}