diff options
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/signal.c | 40 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/signal.c | 8 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/signal.c | 6 |
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 | ||
118 | void (*handlers[_NSIG])(int sig, struct sigcontext *sc); | 118 | void (*handlers[_NSIG])(int sig, struct sigcontext *sc); |
119 | 119 | ||
120 | void 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 | |||
120 | extern void hard_handler(int sig); | 160 | extern void hard_handler(int sig); |
121 | 161 | ||
122 | void set_handler(int sig, void (*handler)(int), int flags, ...) | 162 | void 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 | ||
8 | extern void (*handlers[])(int sig, struct sigcontext *sc); | 8 | extern void handle_signal(int sig, struct sigcontext *sc); |
9 | 9 | ||
10 | void hard_handler(int sig) | 10 | void 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 | ||
8 | extern void (*handlers[])(int sig, struct sigcontext *sc); | 8 | extern void handle_signal(int sig, struct sigcontext *sc); |
9 | 9 | ||
10 | void hard_handler(int sig) | 10 | void 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 | } |