diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/signal.c | 43 |
1 files changed, 30 insertions, 13 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 934ae5e687b9..5bb9baffa4f1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c | |||
@@ -159,6 +159,10 @@ void recalc_sigpending(void) | |||
159 | 159 | ||
160 | /* Given the mask, find the first available signal that should be serviced. */ | 160 | /* Given the mask, find the first available signal that should be serviced. */ |
161 | 161 | ||
162 | #define SYNCHRONOUS_MASK \ | ||
163 | (sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \ | ||
164 | sigmask(SIGTRAP) | sigmask(SIGFPE)) | ||
165 | |||
162 | int next_signal(struct sigpending *pending, sigset_t *mask) | 166 | int next_signal(struct sigpending *pending, sigset_t *mask) |
163 | { | 167 | { |
164 | unsigned long i, *s, *m, x; | 168 | unsigned long i, *s, *m, x; |
@@ -166,26 +170,39 @@ int next_signal(struct sigpending *pending, sigset_t *mask) | |||
166 | 170 | ||
167 | s = pending->signal.sig; | 171 | s = pending->signal.sig; |
168 | m = mask->sig; | 172 | m = mask->sig; |
173 | |||
174 | /* | ||
175 | * Handle the first word specially: it contains the | ||
176 | * synchronous signals that need to be dequeued first. | ||
177 | */ | ||
178 | x = *s &~ *m; | ||
179 | if (x) { | ||
180 | if (x & SYNCHRONOUS_MASK) | ||
181 | x &= SYNCHRONOUS_MASK; | ||
182 | sig = ffz(~x) + 1; | ||
183 | return sig; | ||
184 | } | ||
185 | |||
169 | switch (_NSIG_WORDS) { | 186 | switch (_NSIG_WORDS) { |
170 | default: | 187 | default: |
171 | for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m) | 188 | for (i = 1; i < _NSIG_WORDS; ++i) { |
172 | if ((x = *s &~ *m) != 0) { | 189 | x = *++s &~ *++m; |
173 | sig = ffz(~x) + i*_NSIG_BPW + 1; | 190 | if (!x) |
174 | break; | 191 | continue; |
175 | } | 192 | sig = ffz(~x) + i*_NSIG_BPW + 1; |
193 | break; | ||
194 | } | ||
176 | break; | 195 | break; |
177 | 196 | ||
178 | case 2: if ((x = s[0] &~ m[0]) != 0) | 197 | case 2: |
179 | sig = 1; | 198 | x = s[1] &~ m[1]; |
180 | else if ((x = s[1] &~ m[1]) != 0) | 199 | if (!x) |
181 | sig = _NSIG_BPW + 1; | ||
182 | else | ||
183 | break; | 200 | break; |
184 | sig += ffz(~x); | 201 | sig = ffz(~x) + _NSIG_BPW + 1; |
185 | break; | 202 | break; |
186 | 203 | ||
187 | case 1: if ((x = *s &~ *m) != 0) | 204 | case 1: |
188 | sig = ffz(~x) + 1; | 205 | /* Nothing to do */ |
189 | break; | 206 | break; |
190 | } | 207 | } |
191 | 208 | ||