diff options
Diffstat (limited to 'kernel/signal.c')
| -rw-r--r-- | kernel/signal.c | 45 |
1 files changed, 31 insertions, 14 deletions
diff --git a/kernel/signal.c b/kernel/signal.c index 934ae5e687b9..dbd7fe073c55 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 | ||
| @@ -228,7 +245,7 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi | |||
| 228 | 245 | ||
| 229 | if (override_rlimit || | 246 | if (override_rlimit || |
| 230 | atomic_read(&user->sigpending) <= | 247 | atomic_read(&user->sigpending) <= |
| 231 | t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) { | 248 | task_rlimit(t, RLIMIT_SIGPENDING)) { |
| 232 | q = kmem_cache_alloc(sigqueue_cachep, flags); | 249 | q = kmem_cache_alloc(sigqueue_cachep, flags); |
| 233 | } else { | 250 | } else { |
| 234 | print_dropped_signal(sig); | 251 | print_dropped_signal(sig); |
