diff options
Diffstat (limited to 'libpthread/linuxthreads/join.c')
-rw-r--r-- | libpthread/linuxthreads/join.c | 57 |
1 files changed, 23 insertions, 34 deletions
diff --git a/libpthread/linuxthreads/join.c b/libpthread/linuxthreads/join.c index 4a7c0d8ac..57ea54e34 100644 --- a/libpthread/linuxthreads/join.c +++ b/libpthread/linuxthreads/join.c @@ -14,38 +14,31 @@ /* Thread termination and joining */ -#include <features.h> #include <errno.h> #include <sched.h> -#include <unistd.h> #include <stdlib.h> +#include <unistd.h> #include "pthread.h" #include "internals.h" #include "spinlock.h" #include "restart.h" -#include "debug.h" /* PDEBUG, added by StS */ +#include <not-cancel.h> -libpthread_hidden_proto(pthread_exit) -void pthread_exit(void * retval) +void __pthread_exit(void * retval) { __pthread_do_exit (retval, CURRENT_STACK_FRAME); } -libpthread_hidden_def (pthread_exit) +strong_alias (__pthread_exit, pthread_exit) void __pthread_do_exit(void *retval, char *currentframe) { pthread_descr self = thread_self(); pthread_descr joining; struct pthread_request request; - PDEBUG("self=%p, pid=%d\n", self, self->p_pid); - - /* obey POSIX behavior and prevent cancellation functions from - * being called more than once. - * http://sourceware.org/ml/libc-ports/2006-10/msg00043.html - */ - THREAD_SETMEM(self, p_cancelstate, PTHREAD_CANCEL_DISABLE); - THREAD_SETMEM(self, p_canceltype, PTHREAD_CANCEL_DEFERRED); + /* Reset the cancellation flag to avoid looping if the cleanup handlers + contain cancellation points */ + THREAD_SETMEM(self, p_canceled, 0); /* Call cleanup functions and destroy the thread-specific data */ __pthread_perform_cleanup(currentframe); __pthread_destroy_specifics(); @@ -61,7 +54,7 @@ void __pthread_do_exit(void *retval, char *currentframe) if ((mask & (__pthread_threads_events.event_bits[idx] | THREAD_GETMEM_NC(self, - p_eventbuf.eventmask).event_bits[idx])) + p_eventbuf.eventmask.event_bits[idx]))) != 0) { /* Yep, we have to signal the death. */ @@ -77,7 +70,6 @@ void __pthread_do_exit(void *retval, char *currentframe) THREAD_SETMEM(self, p_terminated, 1); /* See if someone is joining on us */ joining = THREAD_GETMEM(self, p_joining); - PDEBUG("joining = %p, pid=%d\n", joining, joining ? joining->p_pid : 0); __pthread_unlock(THREAD_GETMEM(self, p_lock)); /* Restart joining thread if any */ if (joining != NULL) restart(joining); @@ -87,25 +79,25 @@ void __pthread_do_exit(void *retval, char *currentframe) if (self == __pthread_main_thread && __pthread_manager_request >= 0) { request.req_thread = self; request.req_kind = REQ_MAIN_THREAD_EXIT; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *)&request, sizeof(request))); + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *)&request, sizeof(request))); suspend(self); /* Main thread flushes stdio streams and runs atexit functions. - * It also calls a handler within LinuxThreads which sends a process exit - * request to the thread manager. */ + It also calls a handler within LinuxThreads which sends a process exit + request to the thread manager. */ exit(0); } - /* Exit the process (but don't flush stdio streams, and don't run - atexit functions). */ + /* Threads other than the main one terminate without flushing stdio streams + or running atexit functions. */ _exit(0); } /* Function called by pthread_cancel to remove the thread from waiting on a condition variable queue. */ -static int join_extricate_func(void *obj, pthread_descr th attribute_unused) +static int join_extricate_func(void *obj, pthread_descr th) { - volatile pthread_descr self = thread_self(); + __volatile__ pthread_descr self = thread_self(); pthread_handle handle = obj; pthread_descr jo; int did_remove = 0; @@ -121,20 +113,19 @@ static int join_extricate_func(void *obj, pthread_descr th attribute_unused) int pthread_join(pthread_t thread_id, void ** thread_return) { - volatile pthread_descr self = thread_self(); + __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; - 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)) { + if (nonexisting_handle(handle, thread_id)) { __pthread_unlock(&handle->h_lock); return ESRCH; } @@ -164,9 +155,7 @@ int pthread_join(pthread_t thread_id, void ** thread_return) __pthread_do_exit(PTHREAD_CANCELED, CURRENT_STACK_FRAME); } - PDEBUG("before suspend\n"); suspend(self); - PDEBUG("after suspend\n"); /* Deregister extrication interface */ __pthread_set_own_extricate_if(self, 0); @@ -186,8 +175,8 @@ int pthread_join(pthread_t thread_id, void ** thread_return) request.req_thread = self; request.req_kind = REQ_FREE; request.req_args.free.thread_id = thread_id; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); } return 0; } @@ -200,7 +189,7 @@ int pthread_detach(pthread_t thread_id) pthread_descr th; __pthread_lock(&handle->h_lock, NULL); - if (invalid_handle(handle, thread_id)) { + if (nonexisting_handle(handle, thread_id)) { __pthread_unlock(&handle->h_lock); return ESRCH; } @@ -224,8 +213,8 @@ int pthread_detach(pthread_t thread_id) request.req_thread = thread_self(); request.req_kind = REQ_FREE; request.req_args.free.thread_id = thread_id; - TEMP_FAILURE_RETRY(write(__pthread_manager_request, - (char *) &request, sizeof(request))); + TEMP_FAILURE_RETRY(write_not_cancel(__pthread_manager_request, + (char *) &request, sizeof(request))); } return 0; } |