Merge commit 'v2.6.34-rc1' into for-2.6.35-incoming
[safe/jmp/linux-2.6] / kernel / signal.c
index 934ae5e..dbd7fe0 100644 (file)
@@ -159,6 +159,10 @@ void recalc_sigpending(void)
 
 /* Given the mask, find the first available signal that should be serviced. */
 
+#define SYNCHRONOUS_MASK \
+       (sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \
+        sigmask(SIGTRAP) | sigmask(SIGFPE))
+
 int next_signal(struct sigpending *pending, sigset_t *mask)
 {
        unsigned long i, *s, *m, x;
@@ -166,26 +170,39 @@ int next_signal(struct sigpending *pending, sigset_t *mask)
 
        s = pending->signal.sig;
        m = mask->sig;
+
+       /*
+        * Handle the first word specially: it contains the
+        * synchronous signals that need to be dequeued first.
+        */
+       x = *s &~ *m;
+       if (x) {
+               if (x & SYNCHRONOUS_MASK)
+                       x &= SYNCHRONOUS_MASK;
+               sig = ffz(~x) + 1;
+               return sig;
+       }
+
        switch (_NSIG_WORDS) {
        default:
-               for (i = 0; i < _NSIG_WORDS; ++i, ++s, ++m)
-                       if ((x = *s &~ *m) != 0) {
-                               sig = ffz(~x) + i*_NSIG_BPW + 1;
-                               break;
-                       }
+               for (i = 1; i < _NSIG_WORDS; ++i) {
+                       x = *++s &~ *++m;
+                       if (!x)
+                               continue;
+                       sig = ffz(~x) + i*_NSIG_BPW + 1;
+                       break;
+               }
                break;
 
-       case 2: if ((x = s[0] &~ m[0]) != 0)
-                       sig = 1;
-               else if ((x = s[1] &~ m[1]) != 0)
-                       sig = _NSIG_BPW + 1;
-               else
+       case 2:
+               x = s[1] &~ m[1];
+               if (!x)
                        break;
-               sig += ffz(~x);
+               sig = ffz(~x) + _NSIG_BPW + 1;
                break;
 
-       case 1: if ((x = *s &~ *m) != 0)
-                       sig = ffz(~x) + 1;
+       case 1:
+               /* Nothing to do */
                break;
        }
 
@@ -228,7 +245,7 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
 
        if (override_rlimit ||
            atomic_read(&user->sigpending) <=
-                       t->signal->rlim[RLIMIT_SIGPENDING].rlim_cur) {
+                       task_rlimit(t, RLIMIT_SIGPENDING)) {
                q = kmem_cache_alloc(sigqueue_cachep, flags);
        } else {
                print_dropped_signal(sig);