optimize pthread termination in the non-detached case

we can avoid blocking signals by simply using a flag to mark that the
thread has exited and prevent it from getting counted in the rsyscall
signal-pingpong. this restores the original pthread create/join
throughput from before the sigprocmask call was added.
This commit is contained in:
Rich Felker 2011-03-10 18:31:37 -05:00
parent dc54a7cbb9
commit 5fcebcde6a
2 changed files with 16 additions and 4 deletions

View File

@ -36,6 +36,7 @@ struct pthread {
struct __ptcb *cancelbuf; struct __ptcb *cancelbuf;
void **tsd; void **tsd;
pthread_attr_t attr; pthread_attr_t attr;
volatile int dead;
}; };
#define __SU (sizeof(size_t)/sizeof(int)) #define __SU (sizeof(size_t)/sizeof(int))

View File

@ -25,13 +25,16 @@ void __pthread_unwind_next(struct __ptcb *cb)
} }
} }
syscall4(__NR_rt_sigprocmask, SIG_BLOCK, (long)(uint64_t[1]){-1},0,8); /* Mark this thread dead before decrementing count */
self->dead = 1;
if (!a_fetch_add(&libc.threads_minus_1, -1)) if (!a_fetch_add(&libc.threads_minus_1, -1))
exit(0); exit(0);
if (self->detached && self->map_base) if (self->detached && self->map_base) {
syscall4(__NR_rt_sigprocmask, SIG_BLOCK, (long)(uint64_t[1]){-1},0,8);
__unmapself(self->map_base, self->map_size); __unmapself(self->map_base, self->map_size);
}
__syscall_exit(0); __syscall_exit(0);
} }
@ -76,9 +79,17 @@ static struct {
static void rsyscall_handler(int sig, siginfo_t *si, void *ctx) static void rsyscall_handler(int sig, siginfo_t *si, void *ctx)
{ {
if (si->si_code > 0 || si->si_pid != __pthread_self()->pid) return; struct pthread *self = __pthread_self();
if (rs.cnt == libc.threads_minus_1) return; if (si->si_code > 0 || si->si_pid != self->pid ||
rs.cnt == libc.threads_minus_1) return;
/* Threads which have already decremented themselves from the
* thread count must not increment rs.cnt or otherwise act. */
if (self->dead) {
__wait(&rs.hold, 0, 1, 1);
return;
}
if (syscall6(rs.nr, rs.arg[0], rs.arg[1], rs.arg[2], if (syscall6(rs.nr, rs.arg[0], rs.arg[1], rs.arg[2],
rs.arg[3], rs.arg[4], rs.arg[5]) < 0 && !rs.err) rs.err=errno; rs.arg[3], rs.arg[4], rs.arg[5]) < 0 && !rs.err) rs.err=errno;