]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
sparc: Use set_current_blocked() and block_sigmask()
authorMatt Fleming <matt.fleming@intel.com>
Fri, 19 Aug 2011 16:46:47 +0000 (17:46 +0100)
committerOleg Nesterov <oleg@redhat.com>
Wed, 24 Aug 2011 18:13:14 +0000 (20:13 +0200)
As described in e6fa16ab ("signal: sigprocmask() should do
retarget_shared_pending()") the modification of current->blocked is
incorrect as we need to check whether the signal we're about to block
is pending in the shared queue.

Also, use the new helper function block_sigmask() which centralises
the code for updating current->blocked after successfully delivering a
signal and reduces the amount of duplicate code across
architectures. In the past some architectures got this code wrong, so
using this helper function should stop that from happening again.

Cc: Oleg Nesterov <oleg@redhat.com>
Cc: "David S. Miller" <davem@davemloft.net>
Signed-off-by: Matt Fleming <matt.fleming@intel.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c

index 75fad425e249bc40559f98d14ead5699839bbbb8..88a384154e0e6c339175ebd58fc832dba1a424c8 100644 (file)
@@ -287,10 +287,7 @@ void do_sigreturn32(struct pt_regs *regs)
                case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
        }
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        return;
 
 segv:
@@ -383,10 +380,7 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
                case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
        }
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        return;
 segv:
        force_sig(SIGSEGV, current);
@@ -766,12 +760,7 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
        if (err)
                return err;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NOMASK))
-               sigaddset(&current->blocked,signr);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       block_sigmask(ka, signr);
 
        tracehook_signal_handler(signr, info, ka, regs, 0);
 
index 5e5c5fd03783c997f5c344025e8f4784182a0ddc..f6b0faba399bdc52991d4c883937475d6b735e32 100644 (file)
@@ -60,12 +60,13 @@ struct rt_signal_frame {
 
 static int _sigpause_common(old_sigset_t set)
 {
-       set &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
+       sigset_t blocked;
+
        current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, set);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+
+       set &= _BLOCKABLE;
+       siginitset(&blocked, set);
+       set_current_blocked(&blocked);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -165,10 +166,7 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
                goto segv_and_exit;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        return;
 
 segv_and_exit:
@@ -229,10 +227,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
        set_fs(old_fs);
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        return;
 segv:
        force_sig(SIGSEGV, current);
@@ -494,12 +489,7 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
        if (err)
                return err;
 
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NOMASK))
-               sigaddset(&current->blocked, signr);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       block_sigmask(ka, signr);
 
        tracehook_signal_handler(signr, info, ka, regs, 0);
 
index 006fe4515886dc6ae2a7a8e6cc9b6df9c16fda46..977e25806a7e52ea1eb77692c1f6847d310cfe1c 100644 (file)
@@ -69,10 +69,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
                                goto do_sigsegv;
                }
                sigdelsetmask(&set, ~_BLOCKABLE);
-               spin_lock_irq(&current->sighand->siglock);
-               current->blocked = set;
-               recalc_sigpending();
-               spin_unlock_irq(&current->sighand->siglock);
+               set_current_blocked(&set);
        }
        if (test_thread_flag(TIF_32BIT)) {
                pc &= 0xffffffff;
@@ -241,12 +238,13 @@ struct rt_signal_frame {
 
 static long _sigpause_common(old_sigset_t set)
 {
-       set &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
+       sigset_t blocked;
+
        current->saved_sigmask = current->blocked;
-       siginitset(&current->blocked, set);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+
+       set &= _BLOCKABLE;
+       siginitset(&blocked, set);
+       set_current_blocked(&blocked);
 
        current->state = TASK_INTERRUPTIBLE;
        schedule();
@@ -341,10 +339,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
        pt_regs_clear_syscall(regs);
 
        sigdelsetmask(&set, ~_BLOCKABLE);
-       spin_lock_irq(&current->sighand->siglock);
-       current->blocked = set;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+       set_current_blocked(&set);
        return;
 segv:
        force_sig(SIGSEGV, current);
@@ -504,12 +499,8 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
                             (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
        if (err)
                return err;
-       spin_lock_irq(&current->sighand->siglock);
-       sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-       if (!(ka->sa.sa_flags & SA_NOMASK))
-               sigaddset(&current->blocked,signr);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
+
+       block_sigmask(ka, signr);
 
        tracehook_signal_handler(signr, info, ka, regs, 0);