aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r--arch/um/os-Linux/signal.c40
-rw-r--r--arch/um/os-Linux/sys-i386/signal.c8
-rw-r--r--arch/um/os-Linux/sys-x86_64/signal.c6
3 files changed, 46 insertions, 8 deletions
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index 420ee86d0d1a..18e5c8b67eb8 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -117,6 +117,46 @@ void remove_sigstack(void)
117 117
118void (*handlers[_NSIG])(int sig, struct sigcontext *sc); 118void (*handlers[_NSIG])(int sig, struct sigcontext *sc);
119 119
120void handle_signal(int sig, struct sigcontext *sc)
121{
122 unsigned long pending = 0;
123
124 do {
125 int nested, bail;
126
127 /*
128 * pending comes back with one bit set for each
129 * interrupt that arrived while setting up the stack,
130 * plus a bit for this interrupt, plus the zero bit is
131 * set if this is a nested interrupt.
132 * If bail is true, then we interrupted another
133 * handler setting up the stack. In this case, we
134 * have to return, and the upper handler will deal
135 * with this interrupt.
136 */
137 bail = to_irq_stack(sig, &pending);
138 if(bail)
139 return;
140
141 nested = pending & 1;
142 pending &= ~1;
143
144 while((sig = ffs(pending)) != 0){
145 sig--;
146 pending &= ~(1 << sig);
147 (*handlers[sig])(sig, sc);
148 }
149
150 /* Again, pending comes back with a mask of signals
151 * that arrived while tearing down the stack. If this
152 * is non-zero, we just go back, set up the stack
153 * again, and handle the new interrupts.
154 */
155 if(!nested)
156 pending = from_irq_stack(nested);
157 } while(pending);
158}
159
120extern void hard_handler(int sig); 160extern void hard_handler(int sig);
121 161
122void set_handler(int sig, void (*handler)(int), int flags, ...) 162void set_handler(int sig, void (*handler)(int), int flags, ...)
diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c
index 0d3eae518352..f311609f93da 100644
--- a/arch/um/os-Linux/sys-i386/signal.c
+++ b/arch/um/os-Linux/sys-i386/signal.c
@@ -1,15 +1,13 @@
1/* 1/*
2 * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7 7
8extern void (*handlers[])(int sig, struct sigcontext *sc); 8extern void handle_signal(int sig, struct sigcontext *sc);
9 9
10void hard_handler(int sig) 10void hard_handler(int sig)
11{ 11{
12 struct sigcontext *sc = (struct sigcontext *) (&sig + 1); 12 handle_signal(sig, (struct sigcontext *) (&sig + 1));
13
14 (*handlers[sig])(sig, sc);
15} 13}
diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c
index 3f369e5f976b..82a388822cd3 100644
--- a/arch/um/os-Linux/sys-x86_64/signal.c
+++ b/arch/um/os-Linux/sys-x86_64/signal.c
@@ -1,16 +1,16 @@
1/* 1/*
2 * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) 2 * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL 3 * Licensed under the GPL
4 */ 4 */
5 5
6#include <signal.h> 6#include <signal.h>
7 7
8extern void (*handlers[])(int sig, struct sigcontext *sc); 8extern void handle_signal(int sig, struct sigcontext *sc);
9 9
10void hard_handler(int sig) 10void hard_handler(int sig)
11{ 11{
12 struct ucontext *uc; 12 struct ucontext *uc;
13 asm("movq %%rdx, %0" : "=r" (uc)); 13 asm("movq %%rdx, %0" : "=r" (uc));
14 14
15 (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext); 15 handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext);
16} 16}