diff --git a/src/time/timer_create.c b/src/time/timer_create.c index 4bef2390..117e5ec6 100644 --- a/src/time/timer_create.c +++ b/src/time/timer_create.c @@ -11,9 +11,15 @@ struct ksigevent { int sigev_tid; }; +struct worker { + pid_t tid; + volatile int deleted; +}; + struct start_args { pthread_barrier_t b; struct sigevent *sev; + struct worker *w; }; static void dummy_0() @@ -38,11 +44,15 @@ static void *start(void *arg) pthread_t self = __pthread_self(); struct start_args *args = arg; jmp_buf jb; + struct worker w = { self->tid }; void (*notify)(union sigval) = args->sev->sigev_notify_function; union sigval val = args->sev->sigev_value; + args->w = &w; pthread_barrier_wait(&args->b); + if (self->timer_id < 0) + return 0; for (;;) { siginfo_t si; while (sigwaitinfo(SIGTIMER_SET, &si) < 0); @@ -51,9 +61,9 @@ static void *start(void *arg) notify(val); pthread_cleanup_pop(1); } - if (self->timer_id < 0) break; + if (w.deleted) break; } - __syscall(SYS_timer_delete, self->timer_id & INT_MAX); + __syscall(SYS_timer_delete, self->timer_id); return 0; } @@ -118,7 +128,7 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict td->timer_id = timerid; pthread_barrier_wait(&args.b); if (timerid < 0) return -1; - *res = (void *)(INTPTR_MIN | (uintptr_t)td>>1); + *res = (void *)(INTPTR_MIN | (uintptr_t)args.w>>1); break; default: errno = EINVAL; diff --git a/src/time/timer_delete.c b/src/time/timer_delete.c index b0bfac09..80baa920 100644 --- a/src/time/timer_delete.c +++ b/src/time/timer_delete.c @@ -5,9 +5,12 @@ 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); - __syscall(SYS_tkill, td->tid, SIGTIMER); + struct worker { + pid_t tid; + volatile int deleted; + } *w = (void *)((uintptr_t)t << 1); + a_store(&w->deleted, 1); + __syscall(SYS_tkill, w->tid, SIGTIMER); return 0; } return __syscall(SYS_timer_delete, t);