Migrate signal code from pthread.c to signal.c
[akaros.git] / user / parlib / signal.c
1 /* Copyright (c) 2013 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * Kevin Klues <klueska@cs.berkeley.edu>
4  * See LICENSE for details.
5  *
6  * POSIX signal handling glue.  All glibc programs link against parlib, so they
7  * will get this mixed in.  Mostly just registration of signal handlers.
8  *
9  * POSIX signal handling caveats:
10  *      - We don't copy signal handling tables or anything across forks or execs
11  *      - We don't send meaningful info in the siginfos, nor do we pass pid/uids on
12  *      signals coming from a kill.  This is especially pertinent for sigqueue,
13  *      which needs a payload (value) and sending PID
14  *      - We run handlers in vcore context, so any blocking syscall will spin.
15  *      Regular signals have restrictions on their syscalls too, though not this
16  *      great.  We could spawn off a uthread to run the handler, given that we have
17  *      a 2LS (which we don't for SCPs).
18  *      - We don't do anything with signal blocking/masking.  When in a signal
19  *      handler, you won't get interrupted with another signal handler (so long as
20  *      you run it in vcore context!).  With uthreads, you could get interrupted.
21  *      There is also no process wide signal blocking yet (sigprocmask()).  If this
22  *      is desired, we can abort certain signals when we h_p_signal(), 
23  *      - Likewise, we don't do waiting for particular signals yet.  Just about the
24  *      only thing we do is allow the registration of signal handlers. 
25  *      - Check each function for further notes.  */
26
27 // Needed for sigmask functions...
28 #define _GNU_SOURCE
29
30 #include <stdio.h>
31 #include <parlib/parlib.h>
32 #include <parlib/signal.h>
33 #include <parlib/uthread.h>
34 #include <parlib/event.h>
35 #include <errno.h>
36 #include <parlib/assert.h>
37 #include <ros/procinfo.h>
38 #include <ros/syscall.h>
39 #include <sys/mman.h>
40 #include <parlib/stdio.h>
41
42 /* Forward declare our signal_ops functions. */
43 static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
44                          struct sigaltstack *__restrict __oss);
45 static int __siginterrupt(int __sig, int __interrupt);
46 static int __sigpending(sigset_t *__set);
47 static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
48                          sigset_t *__restrict __oset);
49 static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val);
50 static int __sigreturn(struct sigcontext *__scp);
51 static int __sigstack(struct sigstack *__ss, struct sigstack *__oss);
52 static int __sigsuspend(__const sigset_t *__set);
53 static int __sigtimedwait(__const sigset_t *__restrict __set,
54                           siginfo_t *__restrict __info,
55                           __const struct timespec *__restrict __timeout);
56 static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig);
57 static int __sigwaitinfo(__const sigset_t *__restrict __set,
58                          siginfo_t *__restrict __info);
59
60 /* The default definition of signal_ops (similar to sched_ops in uthread.c) */
61 struct signal_ops default_signal_ops = {
62         .sigaltstack = __sigaltstack,
63         .siginterrupt = __siginterrupt,
64         .sigpending = __sigpending,
65         .sigprocmask = __sigprocmask,
66         .sigqueue = __sigqueue,
67         .sigreturn = __sigreturn,
68         .sigstack = __sigstack,
69         .sigsuspend = __sigsuspend,
70         .sigtimedwait = __sigtimedwait,
71         .sigwait = __sigwait,
72         .sigwaitinfo = __sigwaitinfo
73 };
74
75 /* This is the catch all akaros event->posix signal handler.  All posix signals
76  * are received in a single akaros event type.  They are then dispatched from
77  * this function to their proper posix signal handler */
78 static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
79                          void *data)
80 {
81         int sig_nr;
82         struct siginfo info = {0};
83         info.si_code = SI_USER;
84
85         assert(ev_msg);
86         sig_nr = ev_msg->ev_arg1;
87         trigger_posix_signal(sig_nr, &info, 0);
88 }
89
90 /* Called from uthread_slim_init() */
91 void init_posix_signals(void)
92 {
93         struct event_queue *posix_sig_ev_q;
94
95         signal_ops = &default_signal_ops;
96         register_ev_handler(EV_POSIX_SIGNAL, handle_event, 0);
97         posix_sig_ev_q = get_eventq(EV_MBOX_UCQ);
98         assert(posix_sig_ev_q);
99         posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
100                                    EVENT_WAKEUP;
101         register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
102 }
103
104 /* Swap the contents of two user contexts (not just their pointers). */
105 static void swap_user_contexts(struct user_context *c1, struct user_context *c2)
106 {
107         struct user_context temp_ctx;
108
109         temp_ctx = *c1;
110         *c1 = *c2;
111         *c2 = temp_ctx;
112 }
113
114 /* Prep a to run a signal handler.  The original context of the uthread
115  * is saved on its stack, and a new context is set up to run the signal
116  * handler the next time the uthread is run. */
117 static void __prep_sighandler(struct uthread *uthread,
118                               void (*entry)(void),
119                               struct siginfo *info)
120 {
121         uintptr_t stack;
122         struct user_context *ctx;
123
124         if (uthread->flags & UTHREAD_SAVED) {
125                 ctx = &uthread->u_ctx;
126                 stack = get_user_ctx_stack(ctx) - sizeof(struct sigdata);
127                 uthread->sigstate.data = (struct sigdata*)stack;
128                 if (uthread->flags & UTHREAD_FPSAVED) {
129                         uthread->sigstate.data->as = uthread->as;
130                         uthread->flags &= ~UTHREAD_FPSAVED;
131                 }
132         } else {
133                 assert(current_uthread == uthread);
134                 ctx = &vcpd_of(vcore_id())->uthread_ctx;
135                 stack = get_user_ctx_stack(ctx) - sizeof(struct sigdata);
136                 uthread->sigstate.data = (struct sigdata*)stack;
137                 save_fp_state(&uthread->sigstate.data->as);
138         }
139         if (info != NULL)
140                 uthread->sigstate.data->info = *info;
141
142         init_user_ctx(&uthread->sigstate.data->u_ctx, (uintptr_t)entry, stack);
143         swap_user_contexts(ctx, &uthread->sigstate.data->u_ctx);
144 }
145
146 /* Restore the context saved as the result of running a signal handler on a
147  * uthread. This context will execute the next time the uthread is run. */
148 static void __restore_after_sighandler(struct uthread *uthread)
149 {
150         uthread->u_ctx = uthread->sigstate.data->u_ctx;
151         uthread->flags |= UTHREAD_SAVED;
152         if (uthread->u_ctx.type == ROS_HW_CTX) {
153                 uthread->as = uthread->sigstate.data->as;
154                 uthread->flags |= UTHREAD_FPSAVED;
155         }
156         uthread->sigstate.data = NULL;
157 }
158
159 /* Callback when yielding a pthread after upon completion of a sighandler.  We
160  * didn't save the current context on yeild, but that's ok because here we
161  * restore the original saved context of the pthread and then treat this like a
162  * normal voluntary yield. */
163 static void __exit_sighandler_cb(struct uthread *uthread, void *junk)
164 {
165         __restore_after_sighandler(uthread);
166         uthread_paused(uthread);
167 }
168
169 /* Run a specific sighandler from the top of the sigstate stack. The 'info'
170  * struct is prepopulated before the call is triggered as the result of a
171  * reflected fault. */
172 static void __run_sighandler(void)
173 {
174         struct uthread *uthread = current_uthread;
175         int signo = uthread->sigstate.data->info.si_signo;
176
177         __sigdelset(&uthread->sigstate.pending, signo);
178         trigger_posix_signal(signo, &uthread->sigstate.data->info,
179                              &uthread->sigstate.data->u_ctx);
180         uthread_yield(FALSE, __exit_sighandler_cb, 0);
181 }
182
183 /* Run through all pending sighandlers and trigger them with a NULL info
184  * field. These handlers are triggered as the result of thread directed
185  * signals (i.e. not interprocess signals), and thus don't require individual
186  * 'info' structs. */
187 static void __run_all_sighandlers(void)
188 {
189         struct uthread *uthread = current_uthread;
190         sigset_t andset = uthread->sigstate.pending & (~uthread->sigstate.mask);
191
192         for (int i = 1; i < _NSIG; i++) {
193                 if (__sigismember(&andset, i)) {
194                         __sigdelset(&uthread->sigstate.pending, i);
195                         trigger_posix_signal(i, NULL, &uthread->sigstate.data->u_ctx);
196                 }
197         }
198         uthread_yield(FALSE, __exit_sighandler_cb, 0);
199 }
200
201 int uthread_signal(struct uthread *uthread, int signo)
202 {
203         // Slightly racy with clearing of mask when triggering the signal, but
204         // that's OK, as signals are inherently racy since they don't queue up.
205         return sigaddset(&uthread->sigstate.pending, signo);
206 }
207
208 /* If there are any pending signals, prep the uthread to run it's signal
209  * handler. The next time the uthread is run, it will pop into it's signal
210  * handler context instead of its original saved context. Once the signal
211  * handler is complete, the original context will be restored and restarted. */
212 void uthread_prep_pending_signals(struct uthread *uthread)
213 {
214         if (!uthread->sigstate.data && uthread->sigstate.pending) {
215                 sigset_t andset = uthread->sigstate.pending & (~uthread->sigstate.mask);
216
217                 if (!__sigisemptyset(&andset))
218                         __prep_sighandler(uthread, __run_all_sighandlers, NULL);
219         }
220 }
221
222 /* If the given signal is unmasked, prep the uthread to run it's signal
223  * handler, but don't run it yet. In either case, make the uthread runnable
224  * again. Once the signal handler is complete, the original context will be
225  * restored and restarted. */
226 void uthread_prep_signal_from_fault(struct uthread *uthread,
227                                     int signo, int code, void *addr)
228 {
229         if (!__sigismember(&uthread->sigstate.mask, signo)) {
230                 struct siginfo info = {0};
231
232                 if (uthread->sigstate.data) {
233                         printf("Uthread sighandler faulted, signal: %d\n", signo);
234                         /* uthread.c already copied out the faulting ctx into the uth */
235                         print_user_context(&uthread->u_ctx);
236                         exit(-1);
237                 }
238                 info.si_signo = signo;
239                 info.si_code = code;
240                 info.si_addr = addr;
241                 __prep_sighandler(uthread, __run_sighandler, &info);
242         }
243 }
244
245 /* This is managed by vcore / 2LS code */
246 static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
247                          struct sigaltstack *__restrict __oss)
248 {
249         return 0;
250 }
251
252 /* Akaros can't have signals interrupt syscalls to need a restart, though we can
253  * re-wake-up the process while it is waiting for its syscall. */
254 static int __siginterrupt(int __sig, int __interrupt)
255 {
256         return 0;
257 }
258
259 /* Not really possible or relevant - you'd need to walk/examine the event UCQ */
260 static int __sigpending(sigset_t *__set)
261 {
262         return 0;
263 }
264
265 static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
266                          sigset_t *__restrict __oset)
267 {
268         sigset_t *sigmask = &current_uthread->sigstate.mask;
269
270         if (__set && (__how != SIG_BLOCK) &&
271                      (__how != SIG_SETMASK) &&
272                      (__how != SIG_UNBLOCK)) {
273                 errno = EINVAL;
274                 return -1;
275         }
276
277         if (__oset)
278                 *__oset = *sigmask;
279         if (__set) {
280                 switch (__how) {
281                         case SIG_BLOCK:
282                                 *sigmask = *sigmask | *__set;
283                                 break;
284                         case SIG_SETMASK:
285                                 *sigmask = *__set;
286                                 break;
287                         case SIG_UNBLOCK:
288                                 *sigmask = *sigmask & ~(*__set);
289                                 break;
290                 }
291         }
292         return 0;
293 }
294
295 /* Needs support with trigger_posix_signal to deal with passing values with
296  * POSIX signals. */
297 static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
298 {
299         return 0;
300 }
301
302 /* Linux specific, and not really needed for us */
303 static int __sigreturn(struct sigcontext *__scp)
304 {
305         return 0;
306 }
307
308 /* This is managed by vcore / 2LS code */
309 static int __sigstack(struct sigstack *__ss, struct sigstack *__oss)
310 {
311         return 0;
312 }
313
314 /* Could do this with a loop on delivery of the signal, sleeping and getting
315  * woken up by the kernel on any event, like we do with async syscalls. */
316 static int __sigsuspend(__const sigset_t *__set)
317 {
318         return 0;
319 }
320
321 /* Can be done similar to sigsuspend, with an extra alarm syscall */
322 static int __sigtimedwait(__const sigset_t *__restrict __set,
323                           siginfo_t *__restrict __info,
324                           __const struct timespec *__restrict __timeout)
325 {
326         return 0;
327 }
328
329 /* Can be done similar to sigsuspend */
330 static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
331 {
332         return 0;
333 }
334
335 /* Can be done similar to sigsuspend */
336 static int __sigwaitinfo(__const sigset_t *__restrict __set,
337                          siginfo_t *__restrict __info)
338 {
339         return 0;
340 }
341