Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-Id: <1462646901-16748-1-git-send-email-koorogi@koorogi.info>
Date: Sat,  7 May 2016 13:48:21 -0500
From: Bobby Bingham <koorogi@...rogi.info>
To: musl@...ts.openwall.com
Subject: [PATCH v3] pthread: implement try/timed join variants

---

In the interest of unstalling this, here's a new, less invasive version.

In the previous patch, timejoin waited for the thread to exit, and tail
called to tryjoin which cleaned up after the thread and retrieved the
thread result.  The regular join was just a timedjoin with an infinite
timeout.

Now, timedjoin has all the logic for waiting, cleaning up after the
thread, and retrieving the result.  Regular join is still just a
timedjoin with an infinite timeout.  However, tryjoin now just checks if
the thread has exited and either returns EBUSY or calls join, depending.

 include/pthread.h         |  2 ++
 src/thread/pthread_join.c | 20 +++++++++++++++++---
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/include/pthread.h b/include/pthread.h
index af70b73..3d2e0c4 100644
--- a/include/pthread.h
+++ b/include/pthread.h
@@ -214,6 +214,8 @@ struct cpu_set_t;
 int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *);
 int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *);
 int pthread_getattr_np(pthread_t, pthread_attr_t *);
+int pthread_tryjoin_np(pthread_t, void **);
+int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
 #endif
 
 #ifdef __cplusplus
diff --git a/src/thread/pthread_join.c b/src/thread/pthread_join.c
index 694d377..5211148 100644
--- a/src/thread/pthread_join.c
+++ b/src/thread/pthread_join.c
@@ -5,18 +5,32 @@ int __munmap(void *, size_t);
 void __pthread_testcancel(void);
 int __pthread_setcancelstate(int, int *);
 
-int __pthread_join(pthread_t t, void **res)
+int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at)
 {
-	int tmp, cs;
+	int tmp, cs, r = 0;
 	__pthread_testcancel();
 	__pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
 	if (cs == PTHREAD_CANCEL_ENABLE) __pthread_setcancelstate(cs, 0);
-	while ((tmp = t->tid)) __timedwait_cp(&t->tid, tmp, 0, 0, 0);
+	while ((tmp = t->tid) && r != ETIMEDOUT && r != EINVAL)
+		r = __timedwait_cp(&t->tid, tmp, CLOCK_REALTIME, at, 0);
 	__pthread_setcancelstate(cs, 0);
+	if (r == ETIMEDOUT || r == EINVAL) return r;
 	a_barrier();
 	if (res) *res = t->result;
 	if (t->map_base) __munmap(t->map_base, t->map_size);
 	return 0;
 }
 
+int __pthread_join(pthread_t t, void **res)
+{
+	return __pthread_timedjoin_np(t, res, 0);
+}
+
+int __pthread_tryjoin_np(pthread_t t, void **res)
+{
+	return t->tid ? EBUSY : __pthread_join(t, res);
+}
+
+weak_alias(__pthread_tryjoin_np, pthread_tryjoin_np);
+weak_alias(__pthread_timedjoin_np, pthread_timedjoin_np);
 weak_alias(__pthread_join, pthread_join);
-- 
2.8.1

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.