about summary refs log tree commit diff
path: root/src/thread/pthread_create.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/thread/pthread_create.c')
-rw-r--r--src/thread/pthread_create.c48
1 files changed, 13 insertions, 35 deletions
diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c
index a722a2d6..844d7bf9 100644
--- a/src/thread/pthread_create.c
+++ b/src/thread/pthread_create.c
@@ -19,6 +19,7 @@ weak_alias(dummy_1, __pthread_tsd_run_dtors);
 void __pthread_unwind_next(struct __ptcb *cb)
 {
 	pthread_t self;
+	int n;
 
 	if (cb->__next) longjmp((void *)cb->__next->__jb, 1);
 
@@ -31,8 +32,9 @@ void __pthread_unwind_next(struct __ptcb *cb)
 	/* Mark this thread dead before decrementing count */
 	self->dead = 1;
 
-	if (!a_fetch_add(&libc.threads_minus_1, -1))
-		exit(0);
+	do n = libc.threads_minus_1;
+	while (n && a_cas(&libc.threads_minus_1, n, n-1)!=n);
+	if (!n) exit(0);
 
 	if (self->detached && self->map_base) {
 		__syscall(SYS_rt_sigprocmask, SIG_BLOCK, (long)(uint64_t[1]){-1},0,8);
@@ -42,43 +44,16 @@ void __pthread_unwind_next(struct __ptcb *cb)
 	__syscall(SYS_exit, 0);
 }
 
-static void docancel(struct pthread *self)
-{
-	struct __ptcb cb = { .__next = self->cancelbuf };
-	self->canceldisable = 1;
-	self->cancelasync = 0;
-	__pthread_unwind_next(&cb);
-}
-
-static void cancel_handler(int sig, siginfo_t *si, void *ctx)
-{
-	struct pthread *self = __pthread_self();
-	if (self->cancel && !self->canceldisable &&
-	    (self->cancelasync || (self->cancelpoint==1 && PC_AT_SYS(ctx))))
-		docancel(self);
-}
-
-static void cancelpt(int x)
-{
-	struct pthread *self = __pthread_self();
-	if ((self->cancelpoint+=x)==1 && self->cancel
-		&& x<2U && !self->canceldisable) docancel(self);
-}
-
 static void init_threads()
 {
-	struct sigaction sa = { .sa_flags = SA_SIGINFO | SA_RESTART };
+	sigset_t set;
 	libc.lock = __lock;
 	libc.lockfile = __lockfile;
-	libc.cancelpt = cancelpt;
-
-	sigemptyset(&sa.sa_mask);
-	sa.sa_sigaction = cancel_handler;
-	__libc_sigaction(SIGCANCEL, &sa, 0);
 
-	sigaddset(&sa.sa_mask, SIGSYSCALL);
-	sigaddset(&sa.sa_mask, SIGCANCEL);
-	__libc_sigprocmask(SIG_UNBLOCK, &sa.sa_mask, 0);
+	sigemptyset(&set);
+	sigaddset(&set, SIGSYSCALL);
+	sigaddset(&set, SIGCANCEL);
+	__libc_sigprocmask(SIG_UNBLOCK, &set, 0);
 }
 
 static int start(void *p)
@@ -159,6 +134,9 @@ int pthread_create(pthread_t *res, const pthread_attr_t *attr, void *(*entry)(vo
 void pthread_exit(void *result)
 {
 	struct pthread *self = pthread_self();
+	struct __ptcb cb = { .__next = self->cancelbuf };
 	self->result = result;
-	docancel(self);
+	self->canceldisable = 1;
+	self->cancelasync = 0;
+	__pthread_unwind_next(&cb);
 }