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;
68 switch (sev.sigev_notify) {
71 ksev.sigev_value = evp ? sev.sigev_value
72 : (union sigval){.sival_ptr=t};
73 ksev.sigev_signo = sev.sigev_signo;
74 ksev.sigev_notify = sev.sigev_notify;
76 if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
78 if (!(t = calloc(1, sizeof *t))) {
79 syscall(SYS_timer_delete, timerid);
85 if (!libc.sigtimer) libc.sigtimer = sighandler;
86 if (sev.sigev_notify_attributes)
87 attr = *sev.sigev_notify_attributes;
89 pthread_attr_init(&attr);
90 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
91 pthread_barrier_init(&args.b, 0, 2);
93 r = pthread_create(&td, &attr, start, &args);
98 pthread_barrier_wait(&args.b);
101 ksev.sigev_value.sival_ptr = t;
102 ksev.sigev_signo = SIGCANCEL;
103 ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
104 ksev.sigev_tid = td->tid;
105 if (syscall(SYS_timer_create, clk, &ksev, &t->timerid) < 0) {