Remove need for externally alloced sigdata struct
[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 #include <signal.h>
28 #include <stdio.h>
29
30 #include <parlib/parlib.h>
31 #include <parlib/event.h>
32 #include <errno.h>
33 #include <parlib/assert.h>
34 #include <ros/procinfo.h>
35 #include <ros/syscall.h>
36 #include <sys/mman.h>
37 #include <parlib/vcore.h> /* for print_user_context() */
38 #include <parlib/waitfreelist.h>
39 #include <parlib/stdio.h>
40
41 /* Forward declare our signal_ops functions. */
42 static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
43                          struct sigaltstack *__restrict __oss);
44 static int __siginterrupt(int __sig, int __interrupt);
45 static int __sigpending(sigset_t *__set);
46 static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
47                          sigset_t *__restrict __oset);
48 static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val);
49 static int __sigreturn(struct sigcontext *__scp);
50 static int __sigstack(struct sigstack *__ss, struct sigstack *__oss);
51 static int __sigsuspend(__const sigset_t *__set);
52 static int __sigtimedwait(__const sigset_t *__restrict __set,
53                           siginfo_t *__restrict __info,
54                           __const struct timespec *__restrict __timeout);
55 static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig);
56 static int __sigwaitinfo(__const sigset_t *__restrict __set,
57                          siginfo_t *__restrict __info);
58
59 /* The default definition of signal_ops (similar to sched_ops in uthread.c) */
60 struct signal_ops default_signal_ops = {
61         .sigaltstack = __sigaltstack,
62         .siginterrupt = __siginterrupt,
63         .sigpending = __sigpending,
64         .sigprocmask = __sigprocmask,
65         .sigqueue = __sigqueue,
66         .sigreturn = __sigreturn,
67         .sigstack = __sigstack,
68         .sigsuspend = __sigsuspend,
69         .sigtimedwait = __sigtimedwait,
70         .sigwait = __sigwait,
71         .sigwaitinfo = __sigwaitinfo
72 };
73
74 /* This is the catch all akaros event->posix signal handler.  All posix signals
75  * are received in a single akaros event type.  They are then dispatched from
76  * this function to their proper posix signal handler */
77 static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
78                          void *data)
79 {
80         int sig_nr;
81         struct siginfo info = {0};
82         info.si_code = SI_USER;
83
84         assert(ev_msg);
85         sig_nr = ev_msg->ev_arg1;
86         trigger_posix_signal(sig_nr, &info, 0);
87 }
88
89 /* Called from uthread_slim_init() */
90 void init_posix_signals(void)
91 {
92         struct event_queue *posix_sig_ev_q;
93
94         signal_ops = &default_signal_ops;
95         register_ev_handler(EV_POSIX_SIGNAL, handle_event, 0);
96         posix_sig_ev_q = get_eventq(EV_MBOX_UCQ);
97         assert(posix_sig_ev_q);
98         posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
99                                    EVENT_WAKEUP;
100         register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
101 }
102
103 /* This is managed by vcore / 2LS code */
104 static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
105                          struct sigaltstack *__restrict __oss)
106 {
107         return 0;
108 }
109
110 /* Akaros can't have signals interrupt syscalls to need a restart, though we can
111  * re-wake-up the process while it is waiting for its syscall. */
112 static int __siginterrupt(int __sig, int __interrupt)
113 {
114         return 0;
115 }
116
117 /* Not really possible or relevant - you'd need to walk/examine the event UCQ */
118 static int __sigpending(sigset_t *__set)
119 {
120         return 0;
121 }
122
123 static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
124                          sigset_t *__restrict __oset)
125 {
126         printf("Function not supported generically! "
127            "Use 2LS specific function e.g. pthread_sigmask\n");
128         return 0;
129 }
130
131 /* Needs support with trigger_posix_signal to deal with passing values with
132  * POSIX signals. */
133 static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
134 {
135         return 0;
136 }
137
138 /* Linux specific, and not really needed for us */
139 static int __sigreturn(struct sigcontext *__scp)
140 {
141         return 0;
142 }
143
144 /* This is managed by vcore / 2LS code */
145 static int __sigstack(struct sigstack *__ss, struct sigstack *__oss)
146 {
147         return 0;
148 }
149
150 /* Could do this with a loop on delivery of the signal, sleeping and getting
151  * woken up by the kernel on any event, like we do with async syscalls. */
152 static int __sigsuspend(__const sigset_t *__set)
153 {
154         return 0;
155 }
156
157 /* Can be done similar to sigsuspend, with an extra alarm syscall */
158 static int __sigtimedwait(__const sigset_t *__restrict __set,
159                           siginfo_t *__restrict __info,
160                           __const struct timespec *__restrict __timeout)
161 {
162         return 0;
163 }
164
165 /* Can be done similar to sigsuspend */
166 static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
167 {
168         return 0;
169 }
170
171 /* Can be done similar to sigsuspend */
172 static int __sigwaitinfo(__const sigset_t *__restrict __set,
173                          siginfo_t *__restrict __info)
174 {
175         return 0;
176 }
177