File: | src/time/timer_create.c |
Location: | line 130, column 16 |
Description: | Assigned value is garbage or undefined |
1 | #include <time.h> | |||
2 | #include <setjmpsetjmp.h> | |||
3 | #include "pthread_impl.h" | |||
4 | ||||
5 | struct ksigevent { | |||
6 | union sigval sigev_value; | |||
7 | int sigev_signo; | |||
8 | int sigev_notify; | |||
9 | int sigev_tid; | |||
10 | }; | |||
11 | ||||
12 | struct start_args { | |||
13 | pthread_barrier_t b; | |||
14 | struct sigevent *sev; | |||
15 | }; | |||
16 | ||||
17 | static void dummy_1(pthread_t self) | |||
18 | { | |||
19 | } | |||
20 | weak_alias(dummy_1, __pthread_tsd_run_dtors)extern __typeof(dummy_1) __pthread_tsd_run_dtors __attribute__ ((weak, alias("dummy_1"))); | |||
21 | ||||
22 | void __reset_tls(); | |||
23 | ||||
24 | static void cleanup_fromsig(void *p) | |||
25 | { | |||
26 | pthread_t self = __pthread_self(); | |||
27 | __pthread_tsd_run_dtors(self); | |||
28 | self->cancel = 0; | |||
29 | self->cancelbuf = 0; | |||
30 | self->canceldisable = 0; | |||
31 | self->cancelasync = 0; | |||
32 | self->unblock_cancel = 0; | |||
33 | __reset_tls(); | |||
34 | longjmp(p, 1); | |||
35 | } | |||
36 | ||||
37 | static void timer_handler(int sig, siginfo_t *si, void *ctx) | |||
38 | { | |||
39 | pthread_t self = __pthread_self(); | |||
40 | jmp_buf jb; | |||
41 | void (*notify)(union sigval) = (void (*)(union sigval))self->start; | |||
42 | union sigval val = { .sival_ptr = self->start_arg }; | |||
43 | ||||
44 | if (!setjmpsetjmp(jb) && si->si_code == SI_TIMER(-2)) { | |||
45 | pthread_cleanup_push(cleanup_fromsig, jb)do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, cleanup_fromsig , jb);; | |||
46 | notify(val); | |||
47 | pthread_cleanup_pop(1)_pthread_cleanup_pop(&__cb, (1)); } while(0); | |||
48 | } | |||
49 | } | |||
50 | ||||
51 | static void install_handler() | |||
52 | { | |||
53 | struct sigaction sa = { | |||
54 | .sa_sigaction__sa_handler.sa_sigaction = timer_handler, | |||
55 | .sa_flags = SA_SIGINFO4 | SA_RESTART0x10000000 | |||
56 | }; | |||
57 | __libc_sigaction(SIGTIMER32, &sa, 0); | |||
58 | } | |||
59 | ||||
60 | static void *start(void *arg) | |||
61 | { | |||
62 | pthread_t self = __pthread_self(); | |||
63 | struct start_args *args = arg; | |||
64 | int id; | |||
65 | ||||
66 | /* Reuse no-longer-needed thread structure fields to avoid | |||
67 | * needing the timer address in the signal handler. */ | |||
68 | self->start = (void *(*)(void *))args->sev->sigev_notify_function; | |||
69 | self->start_arg = args->sev->sigev_value.sival_ptr; | |||
70 | ||||
71 | pthread_barrier_wait(&args->b); | |||
72 | if ((id = self->timer_id) >= 0) { | |||
73 | __syscall(SYS_rt_sigprocmask, SIG_UNBLOCK,__syscall4(175,((long) (1)),((long) (((sigset_t *)(const unsigned long [65/8/sizeof(long)]){ 0x80000000 }))),((long) (0)),((long ) (65/8))) | |||
74 | SIGTIMER_SET, 0, _NSIG/8)__syscall4(175,((long) (1)),((long) (((sigset_t *)(const unsigned long [65/8/sizeof(long)]){ 0x80000000 }))),((long) (0)),((long ) (65/8))); | |||
75 | __wait(&self->timer_id, 0, id, 1); | |||
76 | __syscall(SYS_timer_delete, id)__syscall1(261,((long) (id))); | |||
77 | } | |||
78 | return 0; | |||
79 | } | |||
80 | ||||
81 | int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict res) | |||
82 | { | |||
83 | static pthread_once_t once = PTHREAD_ONCE_INIT0; | |||
84 | pthread_t td; | |||
85 | pthread_attr_t attr; | |||
86 | int r; | |||
87 | struct start_args args; | |||
88 | struct ksigevent ksev, *ksevp=0; | |||
89 | int timerid; | |||
| ||||
90 | sigset_t set; | |||
91 | ||||
92 | switch (evp ? evp->sigev_notify : SIGEV_SIGNAL0) { | |||
93 | case SIGEV_NONE1: | |||
94 | case SIGEV_SIGNAL0: | |||
95 | if (evp) { | |||
96 | ksev.sigev_value = evp->sigev_value; | |||
97 | ksev.sigev_signo = evp->sigev_signo; | |||
98 | ksev.sigev_notify = evp->sigev_notify; | |||
99 | ksev.sigev_tid = 0; | |||
100 | ksevp = &ksev; | |||
101 | } | |||
102 | if (syscall(SYS_timer_create, clk, ksevp, &timerid)__syscall_ret(__syscall3(257,((long) (clk)),((long) (ksevp)), ((long) (&timerid)))) < 0) | |||
103 | return -1; | |||
104 | *res = (void *)(intptr_t)timerid; | |||
105 | break; | |||
106 | case SIGEV_THREAD2: | |||
107 | pthread_once(&once, install_handler); | |||
108 | if (evp->sigev_notify_attributes) | |||
109 | attr = *evp->sigev_notify_attributes; | |||
110 | else | |||
111 | pthread_attr_init(&attr); | |||
112 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED1); | |||
113 | pthread_barrier_init(&args.b, 0, 2); | |||
114 | args.sev = evp; | |||
115 | ||||
116 | __block_app_sigs(&set); | |||
117 | r = pthread_create(&td, &attr, start, &args); | |||
118 | __restore_sigs(&set); | |||
119 | if (r) { | |||
120 | errno(*__errno_location()) = r; | |||
121 | return -1; | |||
122 | } | |||
123 | ||||
124 | ksev.sigev_value.sival_ptr = 0; | |||
125 | ksev.sigev_signo = SIGTIMER32; | |||
126 | ksev.sigev_notify = 4; /* SIGEV_THREAD_ID */ | |||
127 | ksev.sigev_tid = td->tid; | |||
128 | if (syscall(SYS_timer_create, clk, &ksev, &timerid)__syscall_ret(__syscall3(257,((long) (clk)),((long) (&ksev )),((long) (&timerid)))) < 0) | |||
129 | timerid = -1; | |||
130 | td->timer_id = timerid; | |||
| ||||
131 | pthread_barrier_wait(&args.b); | |||
132 | if (timerid < 0) return -1; | |||
133 | *res = (void *)(INTPTR_MIN(-1-0x7fffffff) | (uintptr_t)td>>1); | |||
134 | break; | |||
135 | default: | |||
136 | errno(*__errno_location()) = EINVAL22; | |||
137 | return -1; | |||
138 | } | |||
139 | ||||
140 | return 0; | |||
141 | } |