aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/signal.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/signal.c')
-rw-r--r--arch/um/os-Linux/signal.c40
1 files changed, 40 insertions, 0 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, ...)