summaryrefslogtreecommitdiff
path: root/libpthread/linuxthreads/join.c
diff options
context:
space:
mode:
Diffstat (limited to 'libpthread/linuxthreads/join.c')
-rw-r--r--libpthread/linuxthreads/join.c57
1 files changed, 34 insertions, 23 deletions
diff --git a/libpthread/linuxthreads/join.c b/libpthread/linuxthreads/join.c
index 57ea54e34..4a7c0d8ac 100644
--- a/libpthread/linuxthreads/join.c
+++ b/libpthread/linuxthreads/join.c
@@ -14,31 +14,38 @@
/* Thread termination and joining */
+#include <features.h>
#include <errno.h>
#include <sched.h>
-#include <stdlib.h>
#include <unistd.h>
+#include <stdlib.h>
#include "pthread.h"
#include "internals.h"
#include "spinlock.h"
#include "restart.h"
-#include <not-cancel.h>
+#include "debug.h" /* PDEBUG, added by StS */
-void __pthread_exit(void * retval)
+libpthread_hidden_proto(pthread_exit)
+void pthread_exit(void * retval)
{
__pthread_do_exit (retval, CURRENT_STACK_FRAME);
}
-strong_alias (__pthread_exit, pthread_exit)
+libpthread_hidden_def (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();
@@ -54,7 +61,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. */
@@ -70,6 +77,7 @@ 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);
@@ -79,25 +87,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_not_cancel(__pthread_manager_request,
- (char *)&request, sizeof(request)));
+ TEMP_FAILURE_RETRY(write(__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);
}
- /* Threads other than the main one terminate without flushing stdio streams
- or running atexit functions. */
+ /* Exit the process (but don't flush stdio streams, and don't run
+ 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)
+static int join_extricate_func(void *obj, pthread_descr th attribute_unused)
{
- __volatile__ pthread_descr self = thread_self();
+ volatile pthread_descr self = thread_self();
pthread_handle handle = obj;
pthread_descr jo;
int did_remove = 0;
@@ -113,19 +121,20 @@ static int join_extricate_func(void *obj, pthread_descr th)
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 (nonexisting_handle(handle, thread_id)) {
+ if (invalid_handle(handle, thread_id)) {
__pthread_unlock(&handle->h_lock);
return ESRCH;
}
@@ -155,7 +164,9 @@ 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);
@@ -175,8 +186,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_not_cancel(__pthread_manager_request,
- (char *) &request, sizeof(request)));
+ TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+ (char *) &request, sizeof(request)));
}
return 0;
}
@@ -189,7 +200,7 @@ int pthread_detach(pthread_t thread_id)
pthread_descr th;
__pthread_lock(&handle->h_lock, NULL);
- if (nonexisting_handle(handle, thread_id)) {
+ if (invalid_handle(handle, thread_id)) {
__pthread_unlock(&handle->h_lock);
return ESRCH;
}
@@ -213,8 +224,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_not_cancel(__pthread_manager_request,
- (char *) &request, sizeof(request)));
+ TEMP_FAILURE_RETRY(write(__pthread_manager_request,
+ (char *) &request, sizeof(request)));
}
return 0;
}