|
@@ -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);
|
|
|
}
|