add pivot_root syscall wrapper
[oweals/musl.git] / src / time / timer_create.c
index 89099dd6b8961ed816d1fd0bc998006431374fb6..e35293cc4027c1cbd57aaa51a245ac59b9f520c9 100644 (file)
@@ -11,13 +11,11 @@ struct ksigevent {
 struct start_args {
        pthread_barrier_t b;
        struct sigevent *sev;
-       timer_t t;
 };
 
-static void sighandler(int sig, siginfo_t *si, void *ctx)
+void __sigtimer_handler(pthread_t self)
 {
        int st;
-       pthread_t self = __pthread_self();
        void (*notify)(union sigval) = (void (*)(union sigval))self->start;
        union sigval val = { .sival_ptr = self->start_arg };
 
@@ -26,30 +24,29 @@ static void sighandler(int sig, siginfo_t *si, void *ctx)
        pthread_setcancelstate(st, 0);
 }
 
-static void killtimer(void *arg)
+static void cleanup(void *p)
 {
-       timer_t t = arg;
-       if (t->timerid >= 0) __syscall(SYS_timer_delete, t->timerid);
+       pthread_t self = p;
+       __syscall(SYS_timer_delete, self->result);
 }
 
 static void *start(void *arg)
 {
        pthread_t self = __pthread_self();
        struct start_args *args = arg;
-       struct __timer t = { .timerid = -1 };
 
        /* 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;
-       args->t = &t;
+       self->result = (void *)-1;
 
-       pthread_cleanup_push(killtimer, &t);
+       pthread_cleanup_push(cleanup, self);
        pthread_barrier_wait(&args->b);
        pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0);
        /* Loop on async-signal-safe cancellation point */
-       for (;;) sleep(1);
-       pthread_cleanup_pop(1);
+       for (;;) sleep(1000000000);
+       pthread_cleanup_pop(0);
        return 0;
 }
 
@@ -79,14 +76,9 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
                ksev.sigev_tid = 0;
                if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
                        return -1;
-               if (!(t = calloc(1, sizeof *t))) {
-                       syscall(SYS_timer_delete, timerid);
-                       return -1;
-               }
-               t->timerid = timerid;
+               *res = (void *)(2*timerid+1);
                break;
        case SIGEV_THREAD:
-               if (!libc.sigtimer) libc.sigtimer = sighandler;
                if (sev.sigev_notify_attributes)
                        attr = *sev.sigev_notify_attributes;
                else
@@ -105,19 +97,17 @@ int timer_create(clockid_t clk, struct sigevent *evp, timer_t *res)
                ksev.sigev_tid = td->tid;
                r = syscall(SYS_timer_create, clk, &ksev, &timerid);
                pthread_barrier_wait(&args.b);
-               t = args.t;
                if (r < 0) {
                        pthread_cancel(td);
                        return -1;
                }
-               t->timerid = timerid;
-               t->thread = td;
+               td->result = (void *)timerid;
+               *res = td;
                break;
        default:
                errno = EINVAL;
                return -1;
        }
 
-       *res = t;
        return 0;
 }