aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2008-02-05 01:31:13 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2008-02-05 12:44:30 -0500
commite6a2d1f7024f93e4622cd7ba633666a63ccce49e (patch)
treec51eb5112312cf70af9786a4fa5b650efa516de8 /arch/um
parent75ada8ffe08cef9b506a796ba6f9ce2071dcf0d7 (diff)
uml: clean up sig_handler_common_skas
sig_handler_common_skas needs significant modernization, starting with its name and storage class. There is no need to hide the true type of the sigcontext pointer, so the void * dummy parameter can be replaced with a sigcontext *sc. The array of uml_pt_regs structs used in the page fault case are gone, replaced by a local variable. This is also used in the non-segfault case instead of the copy in the task_struct. Since it's local, the special handling of the is_user flag can go away. There hasn't been any special treatment of SIGUSR1 in ages, so the line that enables it can be deleted. The special treatment of SIGSEGV similarly goes away, but to compensate, SA_NODEFER is added to sa_mask when registering a signal handler. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch/um')
-rw-r--r--arch/um/os-Linux/signal.c63
1 files changed, 18 insertions, 45 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index cde9e766b5b4..91a35da5fe90 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -10,14 +10,15 @@
10#include <signal.h> 10#include <signal.h>
11#include <strings.h> 11#include <strings.h>
12#include "as-layout.h" 12#include "as-layout.h"
13#include "kern_constants.h"
14#include "kern_util.h" 13#include "kern_util.h"
15#include "os.h" 14#include "os.h"
16#include "sysdep/barrier.h" 15#include "sysdep/barrier.h"
17#include "sysdep/sigcontext.h" 16#include "sysdep/sigcontext.h"
18#include "task.h"
19#include "user.h" 17#include "user.h"
20 18
19/* Copied from linux/compiler-gcc.h since we can't include it directly */
20#define barrier() __asm__ __volatile__("": : :"memory")
21
21void (*sig_info[NSIG])(int, struct uml_pt_regs *) = { 22void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
22 [SIGTRAP] = relay_signal, 23 [SIGTRAP] = relay_signal,
23 [SIGFPE] = relay_signal, 24 [SIGFPE] = relay_signal,
@@ -28,58 +29,27 @@ void (*sig_info[NSIG])(int, struct uml_pt_regs *) = {
28 [SIGIO] = sigio_handler, 29 [SIGIO] = sigio_handler,
29 [SIGVTALRM] = timer_handler }; 30 [SIGVTALRM] = timer_handler };
30 31
31static struct uml_pt_regs ksig_regs[UM_NR_CPUS]; 32static void sig_handler_common(int sig, struct sigcontext *sc)
32
33void sig_handler_common_skas(int sig, void *sc_ptr)
34{ 33{
35 struct sigcontext *sc = sc_ptr; 34 struct uml_pt_regs r;
36 struct uml_pt_regs *r; 35 int save_errno = errno;
37 void (*handler)(int, struct uml_pt_regs *);
38 int save_user, save_errno = errno;
39 36
40 /* 37 r.is_user = 0;
41 * This is done because to allow SIGSEGV to be delivered inside a SEGV
42 * handler. This can happen in copy_user, and if SEGV is disabled,
43 * the process will die.
44 * XXX Figure out why this is better than SA_NODEFER
45 */
46 if (sig == SIGSEGV) { 38 if (sig == SIGSEGV) {
47 change_sig(SIGSEGV, 1); 39 /* For segfaults, we want the data from the sigcontext. */
48 /* 40 copy_sc(&r, sc);
49 * For segfaults, we want the data from the 41 GET_FAULTINFO_FROM_SC(r.faultinfo, sc);
50 * sigcontext. In this case, we don't want to mangle 42 }
51 * the process registers, so use a static set of
52 * registers. For other signals, the process
53 * registers are OK.
54 */
55 r = &ksig_regs[cpu()];
56 copy_sc(r, sc_ptr);
57 } else
58 r = TASK_REGS(get_current());
59
60 save_user = r->is_user;
61 r->is_user = 0;
62 if ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) ||
63 (sig == SIGILL) || (sig == SIGTRAP))
64 GET_FAULTINFO_FROM_SC(r->faultinfo, sc);
65
66 change_sig(SIGUSR1, 1);
67
68 handler = sig_info[sig];
69 43
70 /* unblock SIGVTALRM, SIGIO if sig isn't IRQ signal */ 44 /* enable signals if sig isn't IRQ signal */
71 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM)) 45 if ((sig != SIGIO) && (sig != SIGWINCH) && (sig != SIGVTALRM))
72 unblock_signals(); 46 unblock_signals();
73 47
74 handler(sig, r); 48 (*sig_info[sig])(sig, &r);
75 49
76 errno = save_errno; 50 errno = save_errno;
77 r->is_user = save_user;
78} 51}
79 52
80/* Copied from linux/compiler-gcc.h since we can't include it directly */
81#define barrier() __asm__ __volatile__("": : :"memory")
82
83/* 53/*
84 * These are the asynchronous signals. SIGPROF is excluded because we want to 54 * These are the asynchronous signals. SIGPROF is excluded because we want to
85 * be able to profile all of UML, not just the non-critical sections. If 55 * be able to profile all of UML, not just the non-critical sections. If
@@ -107,7 +77,7 @@ void sig_handler(int sig, struct sigcontext *sc)
107 77
108 block_signals(); 78 block_signals();
109 79
110 sig_handler_common_skas(sig, sc); 80 sig_handler_common(sig, sc);
111 81
112 set_signals(enabled); 82 set_signals(enabled);
113} 83}
@@ -227,6 +197,9 @@ void set_handler(int sig, void (*handler)(int), int flags, ...)
227 sigaddset(&action.sa_mask, mask); 197 sigaddset(&action.sa_mask, mask);
228 va_end(ap); 198 va_end(ap);
229 199
200 if (sig == SIGSEGV)
201 flags |= SA_NODEFER;
202
230 action.sa_flags = flags; 203 action.sa_flags = flags;
231 action.sa_restorer = NULL; 204 action.sa_restorer = NULL;
232 if (sigaction(sig, &action, NULL) < 0) 205 if (sigaction(sig, &action, NULL) < 0)
@@ -306,7 +279,7 @@ void unblock_signals(void)
306 * back here. 279 * back here.
307 */ 280 */
308 if (save_pending & SIGIO_MASK) 281 if (save_pending & SIGIO_MASK)
309 sig_handler_common_skas(SIGIO, NULL); 282 sig_handler_common(SIGIO, NULL);
310 283
311 if (save_pending & SIGVTALRM_MASK) 284 if (save_pending & SIGVTALRM_MASK)
312 real_alarm_handler(NULL); 285 real_alarm_handler(NULL);