summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-02-15 15:23:11 -0500
committerRich Felker <dalias@aerifal.cx>2019-02-15 15:23:11 -0500
commit5b74eed3b301e2227385f3bf26d3bb7c2d822cf8 (patch)
tree9fc7cb150d450d2e5447d266513bfa61b6eebf83 /src
parentaa5a9d15e09851f7b4a1668e9dbde0f6234abada (diff)
downloadmusl-5b74eed3b301e2227385f3bf26d3bb7c2d822cf8.tar.gz
for SIGEV_THREAD timer threads, replace signal handler with sigwaitinfo
this eliminates some ugly hacks that were repurposing the start function and start argument fields in the pthread structure for timer use, and the need to longjmp out of a signal handler.
Diffstat (limited to 'src')
-rw-r--r--src/time/timer_create.c35
-rw-r--r--src/time/timer_delete.c2
2 files changed, 16 insertions, 21 deletions
diff --git a/src/time/timer_create.c b/src/time/timer_create.c
index d9fbaee5..94219574 100644
--- a/src/time/timer_create.c
+++ b/src/time/timer_create.c
@@ -34,16 +34,6 @@ static void cleanup_fromsig(void *p)
static void timer_handler(int sig, siginfo_t *si, void *ctx)
{
- pthread_t self = __pthread_self();
- jmp_buf jb;
- void (*notify)(union sigval) = (void (*)(union sigval))self->start;
- union sigval val = { .sival_ptr = self->start_arg };
-
- if (!setjmp(jb) && si->si_code == SI_TIMER) {
- pthread_cleanup_push(cleanup_fromsig, jb);
- notify(val);
- pthread_cleanup_pop(1);
- }
}
static void install_handler()
@@ -59,20 +49,24 @@ static void *start(void *arg)
{
pthread_t self = __pthread_self();
struct start_args *args = arg;
- int id;
+ int id = self->timer_id;
+ jmp_buf jb;
- /* Reuse no-longer-needed thread structure fields to avoid
- * needing the timer address in the signal handler. */
- self->start = (void *(*)(void *))args->sev->sigev_notify_function;
- self->start_arg = args->sev->sigev_value.sival_ptr;
+ void (*notify)(union sigval) = args->sev->sigev_notify_function;
+ union sigval val = args->sev->sigev_value;
pthread_barrier_wait(&args->b);
- if ((id = self->timer_id) >= 0) {
- __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,
- SIGTIMER_SET, 0, _NSIG/8);
- __wait(&self->timer_id, 0, id, 1);
- __syscall(SYS_timer_delete, id);
+ for (;;) {
+ siginfo_t si;
+ while (sigwaitinfo(SIGTIMER_SET, &si) < 0);
+ if (si.si_code == SI_TIMER && !setjmp(jb)) {
+ pthread_cleanup_push(cleanup_fromsig, jb);
+ notify(val);
+ pthread_cleanup_pop(1);
+ }
+ if (self->timer_id < 0) break;
}
+ __syscall(SYS_timer_delete, id);
return 0;
}
@@ -112,6 +106,7 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
args.sev = evp;
__block_app_sigs(&set);
+ __syscall(SYS_rt_sigprocmask, SIG_BLOCK, SIGTIMER_SET, 0, _NSIG/8);
r = pthread_create(&td, &attr, start, &args);
__restore_sigs(&set);
if (r) {
diff --git a/src/time/timer_delete.c b/src/time/timer_delete.c
index 7c97eeb1..b0bfac09 100644
--- a/src/time/timer_delete.c
+++ b/src/time/timer_delete.c
@@ -7,7 +7,7 @@ int timer_delete(timer_t t)
if ((intptr_t)t < 0) {
pthread_t td = (void *)((uintptr_t)t << 1);
a_store(&td->timer_id, td->timer_id | INT_MIN);
- __wake(&td->timer_id, 1, 1);
+ __syscall(SYS_tkill, td->tid, SIGTIMER);
return 0;
}
return __syscall(SYS_timer_delete, t);