2 #include "pthread_impl.h"
5 union sigval sigev_value;
16 static void cleanup_fromsig(void *p)
18 pthread_t self = __pthread_self();
24 void __sigtimer_handler(pthread_t self)
27 void (*notify)(union sigval) = (void (*)(union sigval))self->start;
28 union sigval val = { .sival_ptr = self->start_arg };
30 if (setjmp(jb)) return;
31 pthread_cleanup_push(cleanup_fromsig, jb);
33 pthread_cleanup_pop(0);
36 static void *start(void *arg)
38 pthread_t self = __pthread_self();
39 struct start_args *args = arg;
41 /* Reuse no-longer-needed thread structure fields to avoid
42 * needing the timer address in the signal handler. */
43 self->start = (void *(*)(void *))args->sev->sigev_notify_function;
44 self->start_arg = args->sev->sigev_value.sival_ptr;
45 self->result = (void *)-1;
47 pthread_barrier_wait(&args->b);
48 __wait(&self->delete_timer, 0, 0, 1);
49 __syscall(SYS_timer_delete, self->result);
53 int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
58 struct start_args args;
59 struct ksigevent ksev, *ksevp=0;
62 switch (evp ? evp->sigev_notify : SIGEV_SIGNAL) {
66 ksev.sigev_value = evp->sigev_value;
67 ksev.sigev_signo = evp->sigev_signo;
68 ksev.sigev_notify = evp->sigev_notify;
72 if (syscall(SYS_timer_create, clk, ksevp, &timerid) < 0)
74 *res = (void *)timerid;
77 if (evp->sigev_notify_attributes)
78 attr = *evp->sigev_notify_attributes;
80 pthread_attr_init(&attr);
81 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
82 pthread_barrier_init(&args.b, 0, 2);
84 r = pthread_create(&td, &attr, start, &args);
89 ksev.sigev_value.sival_ptr = 0;
90 ksev.sigev_signo = SIGCANCEL;
91 ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */
92 ksev.sigev_tid = td->tid;
93 r = syscall(SYS_timer_create, clk, &ksev, &timerid);
94 pthread_barrier_wait(&args.b);
99 td->result = (void *)timerid;