Weasel apart parlib/libc symbols for signals (XCC)
[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 a wait-free-list used to hold the data necessary to execute signal
75  * handlers inside a 2LS. We are able to store them in a wfl because all
76  * sigdata structs are created equal, and reuse is encouraged as uthreads
77  * ask for them on demand. */
78 static struct wfl sigdata_list;
79 #define SIGNAL_STACK_SIZE (2*PGSIZE + sizeof(struct sigdata))
80
81 /* This function allocates a sigdata struct for use when running signal
82  * handlers inside a 2LS. The sigdata struct returned is pre-initialized with
83  * the 'stack' field pointing to a valid stack.  Space is allocated for both
84  * the sigdata struct and the stack in a single mmap call.  The sigdata struct
85  * just sits at the bottom of the stack, and its 'stack' field points just
86  * above it.  */
87 struct sigdata *alloc_sigdata()
88 {
89         struct sigdata *data = wfl_remove(&sigdata_list);
90         if (data == NULL) {
91                 void *stack = mmap(0, SIGNAL_STACK_SIZE,
92                                    PROT_READ|PROT_WRITE|PROT_EXEC,
93                                    MAP_POPULATE|MAP_ANONYMOUS, -1, 0);
94                 assert(stack != MAP_FAILED);
95                 data = stack + SIGNAL_STACK_SIZE - sizeof(struct sigdata);
96                 data->stack = data;
97         }
98         return data;
99 }
100
101 /* This function frees a previously allocated sigdata struct. */
102 void free_sigdata(struct sigdata *sigdata)
103 {
104         wfl_insert(&sigdata_list, sigdata);
105 }
106
107 /* This is the catch all akaros event->posix signal handler.  All posix signals
108  * are received in a single akaros event type.  They are then dispatched from
109  * this function to their proper posix signal handler */
110 static void handle_event(struct event_msg *ev_msg, unsigned int ev_type,
111                          void *data)
112 {
113         int sig_nr;
114         struct siginfo info = {0};
115         info.si_code = SI_USER;
116
117         assert(ev_msg);
118         sig_nr = ev_msg->ev_arg1;
119         trigger_posix_signal(sig_nr, &info, 0);
120 }
121
122 /* Called from uthread_slim_init() */
123 void init_posix_signals(void)
124 {
125         struct event_queue *posix_sig_ev_q;
126
127         signal_ops = &default_signal_ops;
128         register_ev_handler(EV_POSIX_SIGNAL, handle_event, 0);
129         posix_sig_ev_q = get_eventq(EV_MBOX_UCQ);
130         assert(posix_sig_ev_q);
131         posix_sig_ev_q->ev_flags = EVENT_IPI | EVENT_INDIR | EVENT_SPAM_INDIR |
132                                    EVENT_WAKEUP;
133         register_kevent_q(posix_sig_ev_q, EV_POSIX_SIGNAL);
134         wfl_init(&sigdata_list);
135 }
136
137 /* This is managed by vcore / 2LS code */
138 static int __sigaltstack(__const struct sigaltstack *__restrict __ss,
139                          struct sigaltstack *__restrict __oss)
140 {
141         return 0;
142 }
143
144 /* Akaros can't have signals interrupt syscalls to need a restart, though we can
145  * re-wake-up the process while it is waiting for its syscall. */
146 static int __siginterrupt(int __sig, int __interrupt)
147 {
148         return 0;
149 }
150
151 /* Not really possible or relevant - you'd need to walk/examine the event UCQ */
152 static int __sigpending(sigset_t *__set)
153 {
154         return 0;
155 }
156
157 static int __sigprocmask(int __how, __const sigset_t *__restrict __set,
158                          sigset_t *__restrict __oset)
159 {
160         printf("Function not supported generically! "
161            "Use 2LS specific function e.g. pthread_sigmask\n");
162         return 0;
163 }
164
165 /* Needs support with trigger_posix_signal to deal with passing values with
166  * POSIX signals. */
167 static int __sigqueue(__pid_t __pid, int __sig, __const union sigval __val)
168 {
169         return 0;
170 }
171
172 /* Linux specific, and not really needed for us */
173 static int __sigreturn(struct sigcontext *__scp)
174 {
175         return 0;
176 }
177
178 /* This is managed by vcore / 2LS code */
179 static int __sigstack(struct sigstack *__ss, struct sigstack *__oss)
180 {
181         return 0;
182 }
183
184 /* Could do this with a loop on delivery of the signal, sleeping and getting
185  * woken up by the kernel on any event, like we do with async syscalls. */
186 static int __sigsuspend(__const sigset_t *__set)
187 {
188         return 0;
189 }
190
191 /* Can be done similar to sigsuspend, with an extra alarm syscall */
192 static int __sigtimedwait(__const sigset_t *__restrict __set,
193                           siginfo_t *__restrict __info,
194                           __const struct timespec *__restrict __timeout)
195 {
196         return 0;
197 }
198
199 /* Can be done similar to sigsuspend */
200 static int __sigwait(__const sigset_t *__restrict __set, int *__restrict __sig)
201 {
202         return 0;
203 }
204
205 /* Can be done similar to sigsuspend */
206 static int __sigwaitinfo(__const sigset_t *__restrict __set,
207                          siginfo_t *__restrict __info)
208 {
209         return 0;
210 }
211