]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/um/os-Linux/signal.c
uml: style fixes pass 3
[linux-2.6-omap-h63xx.git] / arch / um / os-Linux / signal.c
1 /*
2  * Copyright (C) 2004 PathScale, Inc
3  * Copyright (C) 2004 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
4  * Licensed under the GPL
5  */
6
7 #include <stdlib.h>
8 #include <stdarg.h>
9 #include <errno.h>
10 #include <signal.h>
11 #include <strings.h>
12 #include "os.h"
13 #include "sysdep/barrier.h"
14 #include "sysdep/sigcontext.h"
15 #include "user.h"
16
17 /*
18  * These are the asynchronous signals.  SIGVTALRM and SIGARLM are handled
19  * together under SIGVTALRM_BIT.  SIGPROF is excluded because we want to
20  * be able to profile all of UML, not just the non-critical sections.  If
21  * profiling is not thread-safe, then that is not my problem.  We can disable
22  * profiling when SMP is enabled in that case.
23  */
24 #define SIGIO_BIT 0
25 #define SIGIO_MASK (1 << SIGIO_BIT)
26
27 #define SIGVTALRM_BIT 1
28 #define SIGVTALRM_MASK (1 << SIGVTALRM_BIT)
29
30 #define SIGALRM_BIT 2
31 #define SIGALRM_MASK (1 << SIGALRM_BIT)
32
33 /*
34  * These are used by both the signal handlers and
35  * block/unblock_signals.  I don't want modifications cached in a
36  * register - they must go straight to memory.
37  */
38 static volatile int signals_enabled = 1;
39 static volatile int pending = 0;
40
41 void sig_handler(int sig, struct sigcontext *sc)
42 {
43         int enabled;
44
45         enabled = signals_enabled;
46         if (!enabled && (sig == SIGIO)) {
47                 pending |= SIGIO_MASK;
48                 return;
49         }
50
51         block_signals();
52
53         sig_handler_common_skas(sig, sc);
54
55         set_signals(enabled);
56 }
57
58 static void real_alarm_handler(int sig, struct sigcontext *sc)
59 {
60         struct uml_pt_regs regs;
61
62         if (sig == SIGALRM)
63                 switch_timers(0);
64
65         if (sc != NULL)
66                 copy_sc(&regs, sc);
67         regs.is_user = 0;
68         unblock_signals();
69         timer_handler(sig, &regs);
70
71         if (sig == SIGALRM)
72                 switch_timers(1);
73 }
74
75 void alarm_handler(int sig, struct sigcontext *sc)
76 {
77         int enabled;
78
79         enabled = signals_enabled;
80         if (!signals_enabled) {
81                 if (sig == SIGVTALRM)
82                         pending |= SIGVTALRM_MASK;
83                 else pending |= SIGALRM_MASK;
84
85                 return;
86         }
87
88         block_signals();
89
90         real_alarm_handler(sig, sc);
91         set_signals(enabled);
92 }
93
94 void set_sigstack(void *sig_stack, int size)
95 {
96         stack_t stack = ((stack_t) { .ss_flags  = 0,
97                                      .ss_sp     = (__ptr_t) sig_stack,
98                                      .ss_size   = size - sizeof(void *) });
99
100         if (sigaltstack(&stack, NULL) != 0)
101                 panic("enabling signal stack failed, errno = %d\n", errno);
102 }
103
104 void remove_sigstack(void)
105 {
106         stack_t stack = ((stack_t) { .ss_flags  = SS_DISABLE,
107                                      .ss_sp     = NULL,
108                                      .ss_size   = 0 });
109
110         if (sigaltstack(&stack, NULL) != 0)
111                 panic("disabling signal stack failed, errno = %d\n", errno);
112 }
113
114 void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
115
116 void handle_signal(int sig, struct sigcontext *sc)
117 {
118         unsigned long pending = 1UL << sig;
119
120         do {
121                 int nested, bail;
122
123                 /*
124                  * pending comes back with one bit set for each
125                  * interrupt that arrived while setting up the stack,
126                  * plus a bit for this interrupt, plus the zero bit is
127                  * set if this is a nested interrupt.
128                  * If bail is true, then we interrupted another
129                  * handler setting up the stack.  In this case, we
130                  * have to return, and the upper handler will deal
131                  * with this interrupt.
132                  */
133                 bail = to_irq_stack(&pending);
134                 if (bail)
135                         return;
136
137                 nested = pending & 1;
138                 pending &= ~1;
139
140                 while ((sig = ffs(pending)) != 0){
141                         sig--;
142                         pending &= ~(1 << sig);
143                         (*handlers[sig])(sig, sc);
144                 }
145
146                 /*
147                  * Again, pending comes back with a mask of signals
148                  * that arrived while tearing down the stack.  If this
149                  * is non-zero, we just go back, set up the stack
150                  * again, and handle the new interrupts.
151                  */
152                 if (!nested)
153                         pending = from_irq_stack(nested);
154         } while (pending);
155 }
156
157 extern void hard_handler(int sig);
158
159 void set_handler(int sig, void (*handler)(int), int flags, ...)
160 {
161         struct sigaction action;
162         va_list ap;
163         sigset_t sig_mask;
164         int mask;
165
166         handlers[sig] = (void (*)(int, struct sigcontext *)) handler;
167         action.sa_handler = hard_handler;
168
169         sigemptyset(&action.sa_mask);
170
171         va_start(ap, flags);
172         while ((mask = va_arg(ap, int)) != -1)
173                 sigaddset(&action.sa_mask, mask);
174         va_end(ap);
175
176         action.sa_flags = flags;
177         action.sa_restorer = NULL;
178         if (sigaction(sig, &action, NULL) < 0)
179                 panic("sigaction failed - errno = %d\n", errno);
180
181         sigemptyset(&sig_mask);
182         sigaddset(&sig_mask, sig);
183         if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL) < 0)
184                 panic("sigprocmask failed - errno = %d\n", errno);
185 }
186
187 int change_sig(int signal, int on)
188 {
189         sigset_t sigset, old;
190
191         sigemptyset(&sigset);
192         sigaddset(&sigset, signal);
193         sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old);
194         return !sigismember(&old, signal);
195 }
196
197 void block_signals(void)
198 {
199         signals_enabled = 0;
200         /*
201          * This must return with signals disabled, so this barrier
202          * ensures that writes are flushed out before the return.
203          * This might matter if gcc figures out how to inline this and
204          * decides to shuffle this code into the caller.
205          */
206         mb();
207 }
208
209 void unblock_signals(void)
210 {
211         int save_pending;
212
213         if (signals_enabled == 1)
214                 return;
215
216         /*
217          * We loop because the IRQ handler returns with interrupts off.  So,
218          * interrupts may have arrived and we need to re-enable them and
219          * recheck pending.
220          */
221         while(1) {
222                 /*
223                  * Save and reset save_pending after enabling signals.  This
224                  * way, pending won't be changed while we're reading it.
225                  */
226                 signals_enabled = 1;
227
228                 /*
229                  * Setting signals_enabled and reading pending must
230                  * happen in this order.
231                  */
232                 mb();
233
234                 save_pending = pending;
235                 if (save_pending == 0) {
236                         /*
237                          * This must return with signals enabled, so
238                          * this barrier ensures that writes are
239                          * flushed out before the return.  This might
240                          * matter if gcc figures out how to inline
241                          * this (unlikely, given its size) and decides
242                          * to shuffle this code into the caller.
243                          */
244                         mb();
245                         return;
246                 }
247
248                 pending = 0;
249
250                 /*
251                  * We have pending interrupts, so disable signals, as the
252                  * handlers expect them off when they are called.  They will
253                  * be enabled again above.
254                  */
255
256                 signals_enabled = 0;
257
258                 /*
259                  * Deal with SIGIO first because the alarm handler might
260                  * schedule, leaving the pending SIGIO stranded until we come
261                  * back here.
262                  */
263                 if (save_pending & SIGIO_MASK)
264                         sig_handler_common_skas(SIGIO, NULL);
265
266                 if (save_pending & SIGALRM_MASK)
267                         real_alarm_handler(SIGALRM, NULL);
268
269                 if (save_pending & SIGVTALRM_MASK)
270                         real_alarm_handler(SIGVTALRM, NULL);
271         }
272 }
273
274 int get_signals(void)
275 {
276         return signals_enabled;
277 }
278
279 int set_signals(int enable)
280 {
281         int ret;
282         if (signals_enabled == enable)
283                 return enable;
284
285         ret = signals_enabled;
286         if (enable)
287                 unblock_signals();
288         else block_signals();
289
290         return ret;
291 }