This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "uClibc-ng - small C library for embedded systems".
The branch, master has been updated
via 4aed5269c44032e8ddbeb176d661350542fc05ab (commit)
from c8b14823b5325da8b51b49a121fadb7a54dbb5c9 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
commit 4aed5269c44032e8ddbeb176d661350542fc05ab
Author: Waldemar Brodkorb <wbx(a)uclibc-ng.org>
Date: Thu Jan 7 23:03:52 2016 +0100
linuxthreads: Implement pthread_tryjoin_np(), pthread_timedjoin_np()
Some applications needs it.
Adapted to master.
Signed-off-by: Leonid Lisovskiy <lly.dev(a)gmail.com>
Signed-off-by: Waldemar Brodkorb <wbx(a)uclibc-ng.org>
-----------------------------------------------------------------------
Summary of changes:
libpthread/linuxthreads/join.c | 138 +++++++++++++++++++++
libpthread/linuxthreads/sysdeps/pthread/pthread.h | 15 +++
test/{nptl => pthread}/tst-join2.c | 5 +-
test/{nptl => pthread}/tst-join3.c | 5 +-
4 files changed, 159 insertions(+), 4 deletions(-)
copy test/{nptl => pthread}/tst-join2.c (93%)
copy test/{nptl => pthread}/tst-join3.c (94%)
diff --git a/libpthread/linuxthreads/join.c b/libpthread/linuxthreads/join.c
index 4a7c0d8..c7e5479 100644
--- a/libpthread/linuxthreads/join.c
+++ b/libpthread/linuxthreads/join.c
@@ -192,6 +192,144 @@ int pthread_join(pthread_t thread_id, void ** thread_return)
return 0;
}
+int pthread_tryjoin_np(pthread_t thread_id, void ** thread_return)
+{
+ volatile pthread_descr self = thread_self();
+ struct pthread_request request;
+ pthread_handle handle = thread_handle(thread_id);
+ pthread_descr th;
+ int result = 0;
+
+ /* Make sure the descriptor is valid. */
+ __pthread_lock(&handle->h_lock, self);
+ if (invalid_handle(handle, thread_id)) {
+ result = ESRCH;
+ goto err;
+ }
+ th = handle->h_descr;
+ /* Is the thread joinable?. */
+ if (th->p_detached || th->p_joining != NULL) {
+ result = EINVAL;
+ goto err;
+ }
+ if (th == self) {
+ result = EDEADLK;
+ goto err;
+ }
+ /* Return right away if the thread hasn't terminated yet. */
+ if (! th->p_terminated) {
+ result = EBUSY;
+ goto err;
+ }
+
+ /* Get return value */
+ if (thread_return != NULL) *thread_return = th->p_retval;
+ __pthread_unlock(&handle->h_lock);
+ /* Send notification to thread manager */
+ if (__pthread_manager_request >= 0) {
+ request.req_thread = self;
+ request.req_kind = REQ_FREE;
+ request.req_args.free.thread_id = thread_id;
+ TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
+ (char *) &request, sizeof(request)));
+ }
+ return 0;
+
+err:
+ __pthread_unlock(&handle->h_lock);
+ return result;
+}
+
+int pthread_timedjoin_np(pthread_t thread_id, void ** thread_return,
+ const struct timespec *abstime)
+{
+ volatile pthread_descr self = thread_self();
+ struct pthread_request request;
+ pthread_handle handle = thread_handle(thread_id);
+ pthread_descr th;
+ pthread_extricate_if extr;
+ int already_canceled = 0;
+ int result = 0;
+ PDEBUG("\n");
+
+ /* Set up extrication interface */
+ extr.pu_object = handle;
+ extr.pu_extricate_func = join_extricate_func;
+
+ __pthread_lock(&handle->h_lock, self);
+ if (invalid_handle(handle, thread_id)) {
+ result = ESRCH;
+ goto err;
+ }
+ th = handle->h_descr;
+ if (th == self) {
+ result = EDEADLK;
+ goto err;
+ }
+ /* If detached or already joined, error */
+ if (th->p_detached || th->p_joining != NULL) {
+ result = EINVAL;
+ goto err;
+ }
+ /* If not terminated yet, suspend ourselves. */
+ if (! th->p_terminated) {
+ /* Register extrication interface */
+ __pthread_set_own_extricate_if(self, &extr);
+ if (!(THREAD_GETMEM(self, p_canceled)
+ && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE))
+ th->p_joining = self;
+ else
+ already_canceled = 1;
+ __pthread_unlock(&handle->h_lock);
+
+ if (already_canceled) {
+ __pthread_set_own_extricate_if(self, 0);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+ }
+
+ PDEBUG("before suspend\n");
+ result = (timedsuspend(self, abstime) == 0) ? ETIMEDOUT : 0;
+ PDEBUG("after suspend\n");
+ /* Deregister extrication interface */
+ __pthread_set_own_extricate_if(self, 0);
+
+ /* This is a cancellation point */
+ if (result == 0
+ && THREAD_GETMEM(self, p_woken_by_cancel)
+ && THREAD_GETMEM(self, p_cancelstate) == PTHREAD_CANCEL_ENABLE) {
+ THREAD_SETMEM(self, p_woken_by_cancel, 0);
+ __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME);
+ }
+ __pthread_lock(&handle->h_lock, self);
+ }
+
+ /* We might have timed out. */
+ if (result == 0) {
+ /* Get return value */
+ if (thread_return != NULL) *thread_return = th->p_retval;
+ }
+ else
+ th->p_joining = NULL;
+
+ __pthread_unlock(&handle->h_lock);
+
+ if (result == 0) {
+ /* Send notification to thread manager */
+ if (__pthread_manager_request >= 0) {
+ request.req_thread = self;
+ request.req_kind = REQ_FREE;
+ request.req_args.free.thread_id = thread_id;
+ TEMP_FAILURE_RETRY(__libc_write(__pthread_manager_request,
+ (char *) &request, sizeof(request)));
+ }
+ }
+ return result;
+
+err:
+ __pthread_unlock(&handle->h_lock);
+ return result;
+}
+
int pthread_detach(pthread_t thread_id)
{
int terminated;
diff --git a/libpthread/linuxthreads/sysdeps/pthread/pthread.h
b/libpthread/linuxthreads/sysdeps/pthread/pthread.h
index 879bcea..3c7044d 100644
--- a/libpthread/linuxthreads/sysdeps/pthread/pthread.h
+++ b/libpthread/linuxthreads/sysdeps/pthread/pthread.h
@@ -179,6 +179,21 @@ extern void pthread_exit (void *__retval) __attribute__
((__noreturn__));
is not NULL. */
extern int pthread_join (pthread_t __th, void **__thread_return);
+#ifdef __USE_GNU
+/* Check whether thread TH has terminated. If yes return the status of
+ the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */
+extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
+
+/* Make calling thread wait for termination of the thread TH, but only
+ until TIMEOUT. The exit status of the thread is stored in
+ *THREAD_RETURN, if THREAD_RETURN is not NULL.
+
+ This function is a cancellation point and therefore not marked with
+ __THROW. */
+extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
+ __const struct timespec *__abstime);
+#endif
+
/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
The resources of TH will therefore be freed immediately when it
terminates, instead of waiting for another thread to perform PTHREAD_JOIN
diff --git a/test/nptl/tst-join2.c b/test/pthread/tst-join2.c
similarity index 93%
copy from test/nptl/tst-join2.c
copy to test/pthread/tst-join2.c
index 0320398..2cfab8b 100644
--- a/test/nptl/tst-join2.c
+++ b/test/pthread/tst-join2.c
@@ -13,8 +13,9 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
diff --git a/test/nptl/tst-join3.c b/test/pthread/tst-join3.c
similarity index 94%
copy from test/nptl/tst-join3.c
copy to test/pthread/tst-join3.c
index b25ffd8..df1135f 100644
--- a/test/nptl/tst-join3.c
+++ b/test/pthread/tst-join3.c
@@ -13,8 +13,9 @@
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
- License along with the GNU C Library; if not, see
- <http://www.gnu.org/licenses/>. */
+ License along with the GNU C Library; if not, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
#include <errno.h>
#include <pthread.h>
hooks/post-receive
--
uClibc-ng - small C library for embedded systems