2 #include "pthread_impl.h"
5 union sigval sigev_value;
17 static void sighandler(int sig, siginfo_t *si, void *ctx)
20 timer_t t = si->si_value.sival_ptr;
21 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &st);
23 pthread_setcancelstate(st, 0);
26 static void killtimer(void *arg)
29 if (t->timerid >= 0) __syscall(SYS_timer_delete, t->timerid);
32 static void *start(void *arg)
34 struct start_args *args = arg;
36 .notify = args->sev->sigev_notify_function,
37 .val = args->sev->sigev_value,
42 pthread_barrier_wait(&args->b);
44 pthread_cleanup_push(killtimer, &t);
45 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
46 /* Loop on async-signal-safe cancellation point */
48 pthread_cleanup_pop(1);
52 int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
54 struct sigevent sev = {
55 .sigev_notify = SIGEV_SIGNAL,
56 .sigev_signo = SIGALRM
61 struct start_args args;
63 struct ksigevent ksev;
67 switch (sev.sigev_notify) {
70 if (!(t = calloc(1, sizeof *t)))
72 ksev.sigev_value = evp ? sev.sigev_value
73 : (union sigval){.sival_ptr=t};
74 ksev.sigev_signo = sev.sigev_signo;
75 ksev.sigev_notify = sev.sigev_notify;
79 if (sev.sigev_notify_attributes)
80 attr = *sev.sigev_notify_attributes;
82 pthread_attr_init(&attr);
83 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
84 pthread_barrier_init(&args.b, 0, 2);
86 r = pthread_create(&td, &attr, start, &args);
91 pthread_barrier_wait(&args.b);
94 ksev.sigev_value.sival_ptr = t;
95 ksev.sigev_signo = SIGCANCEL;
96 ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
97 ksev.sigev_tid = td->tid;
98 if (!libc.sigtimer) libc.sigtimer = sighandler;
103 if (syscall(SYS_timer_create, clk, &ksev, &t->timerid) < 0) {