summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2005-10-04 06:15:25 +0000
committerdavidxu <davidxu@FreeBSD.org>2005-10-04 06:15:25 +0000
commit6459dc5d9d0ec1b437d561a2038a1e4f053df2af (patch)
tree467a22e42b028df8d861fa91c891834e7deb9e4c /lib
parente3843610ee40a003342b7024d661837ba52cc19d (diff)
downloadFreeBSD-src-6459dc5d9d0ec1b437d561a2038a1e4f053df2af.zip
FreeBSD-src-6459dc5d9d0ec1b437d561a2038a1e4f053df2af.tar.gz
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.
Diffstat (limited to 'lib')
-rw-r--r--lib/libthr/pthread.map2
-rw-r--r--lib/libthr/thread/thr_join.c58
2 files changed, 51 insertions, 9 deletions
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
index 3cb7a38..b76a88e 100644
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -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;
diff --git a/lib/libthr/thread/thr_join.c b/lib/libthr/thread/thr_join.c
index c44b261..81c210d 100644
--- a/lib/libthr/thread/thr_join.c
+++ b/lib/libthr/thread/thr_join.c
@@ -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)
{
@@ -52,7 +55,26 @@ 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);
}
OpenPOWER on IntegriCloud