Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
authorLinus Torvalds <torvalds@linux-foundation.org>
Fri, 1 Jun 2012 18:53:44 +0000 (11:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 1 Jun 2012 18:53:44 +0000 (11:53 -0700)
Pull third pile of signal handling patches from Al Viro:
 "This time it's mostly helpers and conversions to them; there's a lot
  of stuff remaining in the tree, but that'll either go in -rc2
  (isolated bug fixes, ideally via arch maintainers' trees) or will sit
  there until the next cycle."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal:
  x86: get rid of calling do_notify_resume() when returning to kernel mode
  blackfin: check __get_user() return value
  whack-a-mole with TIF_FREEZE
  FRV: Optimise the system call exit path in entry.S [ver #2]
  FRV: Shrink TIF_WORK_MASK [ver #2]
  FRV: Prevent syscall exit tracing and notify_resume at end of kernel exceptions
  new helper: signal_delivered()
  powerpc: get rid of restore_sigmask()
  most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set
  set_restore_sigmask() is never called without SIGPENDING (and never should be)
  TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set
  don't call try_to_freeze() from do_signal()
  pull clearing RESTORE_SIGMASK into block_sigmask()
  sh64: failure to build sigframe != signal without handler
  openrisc: tracehook_signal_handler() is supposed to be called on success
  new helper: sigmask_to_save()
  new helper: restore_saved_sigmask()
  new helpers: {clear,test,test_and_clear}_restore_sigmask()
  HAVE_RESTORE_SIGMASK is defined on all architectures now

68 files changed:
arch/alpha/kernel/signal.c
arch/arm/kernel/signal.c
arch/avr32/kernel/entry-avr32b.S
arch/avr32/kernel/signal.c
arch/blackfin/include/asm/thread_info.h
arch/blackfin/kernel/signal.c
arch/blackfin/mach-common/entry.S
arch/c6x/kernel/signal.c
arch/cris/arch-v10/kernel/signal.c
arch/cris/arch-v32/kernel/signal.c
arch/frv/include/asm/thread_info.h
arch/frv/kernel/entry.S
arch/frv/kernel/signal.c
arch/h8300/kernel/signal.c
arch/hexagon/kernel/signal.c
arch/ia64/include/asm/thread_info.h
arch/ia64/kernel/signal.c
arch/m32r/kernel/signal.c
arch/m68k/kernel/signal.c
arch/microblaze/include/asm/thread_info.h
arch/microblaze/kernel/signal.c
arch/mips/kernel/signal-common.h
arch/mips/kernel/signal.c
arch/mips/kernel/signal32.c
arch/mips/kernel/signal_n32.c
arch/mn10300/kernel/signal.c
arch/openrisc/kernel/signal.c
arch/parisc/include/asm/thread_info.h
arch/parisc/kernel/entry.S
arch/parisc/kernel/signal.c
arch/parisc/kernel/signal32.c
arch/powerpc/include/asm/thread_info.h
arch/powerpc/kernel/signal.c
arch/powerpc/kernel/signal.h
arch/powerpc/kernel/signal_32.c
arch/powerpc/kernel/signal_64.c
arch/s390/kernel/compat_signal.c
arch/s390/kernel/entry.h
arch/s390/kernel/signal.c
arch/score/kernel/signal.c
arch/sh/include/asm/thread_info.h
arch/sh/kernel/signal_32.c
arch/sh/kernel/signal_64.c
arch/sparc/include/asm/thread_info_32.h
arch/sparc/include/asm/thread_info_64.h
arch/sparc/kernel/signal32.c
arch/sparc/kernel/signal_32.c
arch/sparc/kernel/signal_64.c
arch/tile/include/asm/thread_info.h
arch/tile/kernel/compat_signal.c
arch/tile/kernel/signal.c
arch/um/include/shared/frame_kern.h
arch/um/kernel/signal.c
arch/unicore32/kernel/signal.c
arch/x86/ia32/ia32_signal.c
arch/x86/include/asm/sighandling.h
arch/x86/include/asm/thread_info.h
arch/x86/kernel/entry_32.S
arch/x86/kernel/signal.c
arch/x86/um/signal.c
arch/xtensa/kernel/signal.c
fs/compat.c
fs/eventpoll.c
fs/select.c
include/linux/sched.h
include/linux/signal.h
include/linux/thread_info.h
kernel/signal.c

index f6db3032ddf0b5b7283c4dd83b135062719e88db..a8c97d42ec8eaef9215c32a40f743bd94505bc55 100644 (file)
@@ -226,7 +226,6 @@ do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
        if (__get_user(set.sig[0], &sc->sc_mask))
                goto give_sigsegv;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(sc, regs, sw))
@@ -261,7 +260,6 @@ do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto give_sigsegv;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
@@ -468,12 +466,9 @@ static inline void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
              struct pt_regs * regs, struct switch_stack *sw)
 {
-       sigset_t *oldset = &current->blocked;
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-
        if (ka->sa.sa_flags & SA_SIGINFO)
                ret = setup_rt_frame(sig, ka, info, oldset, regs, sw);
        else
@@ -483,12 +478,7 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
                force_sigsegv(sig, current);
                return;
        }
-       block_sigmask(ka, sig);
-       /* A signal was successfully delivered, and the
-          saved sigmask was stored on the signal frame,
-          and will be restored by sigreturn.  So we can
-          simply clear the restore sigmask flag.  */
-       clear_thread_flag(TIF_RESTORE_SIGMASK);
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 static inline void
@@ -572,9 +562,7 @@ do_signal(struct pt_regs * regs, struct switch_stack * sw,
        }
 
        /* If there's no signal to deliver, we just restore the saved mask.  */
-       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
-               set_current_blocked(&current->saved_sigmask);
-
+       restore_saved_sigmask();
        if (single_stepping)
                ptrace_set_bpt(current);        /* re-set breakpoint */
 }
index 63f327dd519814b28a5c092b203e089ec4d732ea..fd2392a17ac1befb3464b5a0e77960a0f862b4ca 100644 (file)
@@ -22,8 +22,6 @@
 
 #include "signal.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * For ARM syscalls, we encode the syscall number into the instruction.
  */
@@ -210,10 +208,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
        int err;
 
        err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
-       if (err == 0) {
-               sigdelsetmask(&set, ~_BLOCKABLE);
+       if (err == 0)
                set_current_blocked(&set);
-       }
 
        __get_user_error(regs->ARM_r0, &sf->uc.uc_mcontext.arm_r0, err);
        __get_user_error(regs->ARM_r1, &sf->uc.uc_mcontext.arm_r1, err);
@@ -528,13 +524,13 @@ setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
 /*
  * OK, we're invoking a handler
  */    
-static int
+static void
 handle_signal(unsigned long sig, struct k_sigaction *ka,
-             siginfo_t *info, sigset_t *oldset,
-             struct pt_regs * regs)
+             siginfo_t *info, struct pt_regs *regs)
 {
        struct thread_info *thread = current_thread_info();
        struct task_struct *tsk = current;
+       sigset_t *oldset = sigmask_to_save();
        int usig = sig;
        int ret;
 
@@ -559,17 +555,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
 
        if (ret != 0) {
                force_sigsegv(sig, tsk);
-               return ret;
+               return;
        }
-
-       /*
-        * Block the signal if we were successful.
-        */
-       block_sigmask(ka, sig);
-
-       tracehook_signal_handler(sig, info, ka, regs, 0);
-
-       return 0;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -617,8 +605,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
         */
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
-               sigset_t *oldset;
-
                /*
                 * Depending on the signal settings we may need to revert the
                 * decision to restart the system call.  But skip this if a
@@ -635,20 +621,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
                        clear_thread_flag(TIF_SYSCALL_RESTARTSYS);
                }
 
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       oldset = &current->saved_sigmask;
-               else
-                       oldset = &current->blocked;
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag.
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
+               handle_signal(signr, &ka, &info, regs);
                return;
        }
 
@@ -663,11 +636,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
                        set_thread_flag(TIF_SYSCALL_RESTARTSYS);
        }
 
-       /* If there's no signal to deliver, we just put the saved sigmask
-        * back.
-        */
-       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
-               set_current_blocked(&current->saved_sigmask);
+       restore_saved_sigmask();
 }
 
 asmlinkage void
index 5e6beb2597a837d53aed33e052f6772bc757653f..df28841813139f658a3511daaacb5aa14012dd80 100644 (file)
@@ -281,7 +281,7 @@ syscall_exit_work:
        ld.w    r1, r0[TI_flags]
        rjmp    1b
 
-2:     mov     r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
+2:     mov     r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
        tst     r1, r2
        breq    3f
        unmask_interrupts
@@ -587,7 +587,7 @@ fault_exit_work:
        ld.w    r1, r0[TI_flags]
        rjmp    fault_exit_work
 
-1:     mov     r2, _TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NOTIFY_RESUME
+1:     mov     r2, _TIF_SIGPENDING | _TIF_NOTIFY_RESUME
        tst     r1, r2
        breq    2f
        unmask_interrupts
index e7595ef74f51f76a1b86723569e47441b02cd4bc..c140f9b41dce48fed05240ff531dc22e42f29095 100644 (file)
@@ -22,8 +22,6 @@
 #include <asm/ucontext.h>
 #include <asm/syscalls.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 asmlinkage int sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                               struct pt_regs *regs)
 {
@@ -89,7 +87,6 @@ asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@@ -224,30 +221,27 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
 
 static inline void
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs *regs, int syscall)
+             struct pt_regs *regs, int syscall)
 {
        int ret;
 
        /*
         * Set up the stack frame
         */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
+       ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
 
        /*
         * Check that the resulting registers are sane
         */
        ret |= !valid_user_regs(regs);
 
-       if (ret != 0) {
-               force_sigsegv(sig, current);
-               return;
-       }
-
        /*
         * Block the signal if we were successful.
         */
-       block_sigmask(ka, sig);
-       clear_thread_flag(TIF_RESTORE_SIGMASK);
+       if (ret != 0)
+               force_sigsegv(sig, current);
+       else
+               signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -255,7 +249,7 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
  * doesn't want to handle. Thus you cannot kill init even with a
  * SIGKILL even by mistake.
  */
-int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
+static void do_signal(struct pt_regs *regs, int syscall)
 {
        siginfo_t info;
        int signr;
@@ -267,12 +261,7 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
         * without doing anything if so.
         */
        if (!user_mode(regs))
-               return 0;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else if (!oldset)
-               oldset = &current->blocked;
+               return;
 
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (syscall) {
@@ -297,15 +286,11 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset, int syscall)
 
        if (signr == 0) {
                /* No signal to deliver -- put the saved sigmask back */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-               }
-               return 0;
+               restore_saved_sigmask();
+               return;
        }
 
-       handle_signal(signr, &ka, &info, oldset, regs, syscall);
-       return 1;
+       handle_signal(signr, &ka, &info, regs, syscall);
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
@@ -315,8 +300,8 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, struct thread_info *ti)
        if ((sysreg_read(SR) & MODE_MASK) == MODE_SUPERVISOR)
                syscall = 1;
 
-       if (ti->flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
-               do_signal(regs, &current->blocked, syscall);
+       if (ti->flags & _TIF_SIGPENDING))
+               do_signal(regs, syscall);
 
        if (ti->flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
index 02560fd8a12182f019802e2f7b4c392110c2eb66..53ad10005ae37db4fbf6c3d6cb21eee6485b8db6 100644 (file)
@@ -100,7 +100,6 @@ static inline struct thread_info *current_thread_info(void)
                                           TIF_NEED_RESCHED */
 #define TIF_MEMDIE             4       /* is terminating due to OOM killer */
 #define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
-#define TIF_FREEZE             6       /* is freezing for suspend */
 #define TIF_IRQ_SYNC           7       /* sync pipeline stage */
 #define TIF_NOTIFY_RESUME      8       /* callback before returning to user */
 #define TIF_SINGLESTEP         9
@@ -111,7 +110,6 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_NEED_RESCHED      (1<<TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_RESTORE_SIGMASK   (1<<TIF_RESTORE_SIGMASK)
-#define _TIF_FREEZE            (1<<TIF_FREEZE)
 #define _TIF_IRQ_SYNC          (1<<TIF_IRQ_SYNC)
 #define _TIF_NOTIFY_RESUME     (1<<TIF_NOTIFY_RESUME)
 #define _TIF_SINGLESTEP                (1<<TIF_SINGLESTEP)
index fc9ecce8b6cee28d4352f1e3f06ddaac30682bcc..6682b73a8523f789bf2e3fa722f068f1ef4ebf79 100644 (file)
@@ -19,8 +19,6 @@
 #include <asm/fixed_code.h>
 #include <asm/syscall.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /* Location of the trace bit in SYSCFG. */
 #define TRACE_BITS 0x0001
 
@@ -98,7 +96,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (rt_restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
@@ -190,17 +187,22 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
        err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
        if (err)
-               goto give_sigsegv;
+               return -EFAULT;
 
        /* Set up registers for signal handler */
-       wrusp((unsigned long)frame);
        if (current->personality & FDPIC_FUNCPTRS) {
                struct fdpic_func_descriptor __user *funcptr =
                        (struct fdpic_func_descriptor *) ka->sa.sa_handler;
-               __get_user(regs->pc, &funcptr->text);
-               __get_user(regs->p3, &funcptr->GOT);
+               u32 pc, p3;
+               err |= __get_user(pc, &funcptr->text);
+               err |= __get_user(p3, &funcptr->GOT);
+               if (err)
+                       return -EFAULT;
+               regs->pc = pc;
+               regs->p3 = p3;
        } else
                regs->pc = (unsigned long)ka->sa.sa_handler;
+       wrusp((unsigned long)frame);
        regs->rets = SIGRETURN_STUB;
 
        regs->r0 = frame->sig;
@@ -208,10 +210,6 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t * info,
        regs->r2 = (unsigned long)(&frame->uc);
 
        return 0;
-
- give_sigsegv:
-       force_sigsegv(sig, current);
-       return -EFAULT;
 }
 
 static inline void
@@ -247,24 +245,21 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
 /*
  * OK, we're invoking a handler
  */
-static int
+static void
 handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
-             sigset_t *oldset, struct pt_regs *regs)
+             struct pt_regs *regs)
 {
-       int ret;
-
        /* are we from a system call? to see pt_regs->orig_p0 */
        if (regs->orig_p0 >= 0)
                /* If so, check system call restarting.. */
                handle_restart(regs, ka, 1);
 
        /* set up the stack frame */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
-
-       if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+       if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
+               force_sigsegv(sig, current);
+       else 
+               signal_delivered(sig, info, ka, regs,
+                               test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -281,37 +276,16 @@ asmlinkage void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 
        current->thread.esp0 = (unsigned long)regs;
 
-       if (try_to_freeze())
-               goto no_signal;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-                       tracehook_signal_handler(signr, &info, &ka, regs,
-                               test_thread_flag(TIF_SINGLESTEP));
-               }
-
+               handle_signal(signr, &info, &ka, regs);
                return;
        }
 
- no_signal:
        /* Did we come from a system call? */
        if (regs->orig_p0 >= 0)
                /* Restart the system call - no handlers present */
@@ -319,10 +293,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 /*
@@ -330,7 +301,7 @@ asmlinkage void do_signal(struct pt_regs *regs)
  */
 asmlinkage void do_notify_resume(struct pt_regs *regs)
 {
-       if (test_thread_flag(TIF_SIGPENDING) || test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (test_thread_flag(TIF_SIGPENDING))
                do_signal(regs);
 
        if (test_thread_flag(TIF_NOTIFY_RESUME)) {
index 80aa2535e2c9f2be80c6f78d6a49c832f7e8be3d..04c2fbe41a7ff3e7193532b1e809b8dbcb7474ee 100644 (file)
@@ -711,8 +711,6 @@ ENTRY(_system_call)
        jump .Lresume_userspace_1;
 
 .Lsyscall_sigpending:
-       cc = BITTST(r7, TIF_RESTORE_SIGMASK);
-       if cc jump .Lsyscall_do_signals;
        cc = BITTST(r7, TIF_SIGPENDING);
        if cc jump .Lsyscall_do_signals;
        cc = BITTST(r7, TIF_NOTIFY_RESUME);
index 9493f0bbf0a6f1b045dd18ee443fea83ca8b4aea..3d8f3c22a94fa0adf7e66fe2a793a65326759990 100644 (file)
@@ -20,8 +20,6 @@
 #include <asm/cacheflush.h>
 
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * Do a signal return, undo the signal stack.
  */
@@ -87,7 +85,6 @@ asmlinkage int do_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@@ -248,10 +245,9 @@ do_restart:
 /*
  * handle the actual delivery of a signal to userspace
  */
-static int handle_signal(int sig,
+static void handle_signal(int sig,
                         siginfo_t *info, struct k_sigaction *ka,
-                        sigset_t *oldset, struct pt_regs *regs,
-                        int syscall)
+                        struct pt_regs *regs, int syscall)
 {
        int ret;
 
@@ -278,11 +274,9 @@ static int handle_signal(int sig,
        }
 
        /* Set up the stack frame */
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
-       if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+       if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
+               return;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -292,7 +286,6 @@ static void do_signal(struct pt_regs *regs, int syscall)
 {
        struct k_sigaction ka;
        siginfo_t info;
-       sigset_t *oldset;
        int signr;
 
        /* we want the common case to go fast, which is why we may in certain
@@ -300,25 +293,9 @@ static void do_signal(struct pt_regs *regs, int syscall)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
-               if (handle_signal(signr, &info, &ka, oldset,
-                                 regs, syscall) == 0) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-                       tracehook_signal_handler(signr, &info, &ka, regs, 0);
-               }
-
+               handle_signal(signr, &info, &ka, regs, syscall);
                return;
        }
 
@@ -343,10 +320,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 /*
@@ -357,8 +331,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags,
                                 int syscall)
 {
        /* deal with pending signal delivery */
-       if (thread_info_flags & ((1 << TIF_SIGPENDING) |
-                                (1 << TIF_RESTORE_SIGMASK)))
+       if (thread_info_flags & (1 << TIF_SIGPENDING))
                do_signal(regs, syscall);
 
        if (thread_info_flags & (1 << TIF_NOTIFY_RESUME)) {
index e16f8f297f61a0376f8b6b4497675a742ee9bf87..0bb477c13a4e08b6bd09ceee6e22e9a11ac2a6b0 100644 (file)
@@ -31,8 +31,6 @@
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /* a syscall in Linux/CRIS is a break 13 instruction which is 2 bytes */
 /* manipulate regs so that upon return, it will be re-executed */
 
@@ -176,7 +174,6 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
                                    sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc))
@@ -212,7 +209,6 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@@ -415,10 +411,11 @@ give_sigsegv:
  * OK, we're invoking a handler
  */
 
-static inline int handle_signal(int canrestart, unsigned long sig,
+static inline void handle_signal(int canrestart, unsigned long sig,
        siginfo_t *info, struct k_sigaction *ka,
-       sigset_t *oldset, struct pt_regs *regs)
+       struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Are we from a system call? */
@@ -456,9 +453,7 @@ static inline int handle_signal(int canrestart, unsigned long sig,
                ret = setup_frame(sig, ka, oldset, regs);
 
        if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+               signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -478,7 +473,6 @@ void do_signal(int canrestart, struct pt_regs *regs)
        siginfo_t info;
        int signr;
         struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -489,23 +483,10 @@ void do_signal(int canrestart, struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(canrestart, signr, &info, &ka,
-                               oldset, regs)) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
+               handle_signal(canrestart, signr, &info, &ka, regs);
                return;
        }
 
@@ -525,8 +506,5 @@ void do_signal(int canrestart, struct pt_regs *regs)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
index b338d8fc0c1241c12aa66495e474d16cd5d49f4a..b60d1b65a4267ef5cbdb14758058b5c9ca6707a0 100644 (file)
@@ -24,9 +24,6 @@
 
 extern unsigned long cris_signal_return_page;
 
-/* Flag to check if a signal is blockable. */
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * A syscall in CRIS is really a "break 13" instruction, which is 2
  * bytes. The registers is manipulated so upon return the instruction
@@ -167,7 +164,6 @@ sys_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
                                                 sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc))
@@ -208,7 +204,6 @@ sys_rt_sigreturn(long r10, long r11, long r12, long r13, long mof, long srp,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@@ -434,11 +429,12 @@ give_sigsegv:
 }
 
 /* Invoke a signal handler to, well, handle the signal. */
-static inline int
+static inline void
 handle_signal(int canrestart, unsigned long sig,
              siginfo_t *info, struct k_sigaction *ka,
-              sigset_t *oldset, struct pt_regs * regs)
+              struct pt_regs * regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Check if this got called from a system call. */
@@ -489,9 +485,7 @@ handle_signal(int canrestart, unsigned long sig,
                ret = setup_frame(sig, ka, oldset, regs);
 
        if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+               signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -511,7 +505,6 @@ do_signal(int canrestart, struct pt_regs *regs)
        int signr;
        siginfo_t info;
         struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * The common case should go fast, which is why this point is
@@ -521,25 +514,11 @@ do_signal(int canrestart, struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(canrestart, signr, &info, &ka,
-                               oldset, regs)) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
-
+               handle_signal(canrestart, signr, &info, &ka, regs);
                return;
        }
 
@@ -560,10 +539,7 @@ do_signal(int canrestart, struct pt_regs *regs)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 asmlinkage void
index 54ab13a0de415c1c76d2449626ad5d3ef92c3565..0ff03a33c81e8b193da81f690ce94c0f0c9ad82b 100644 (file)
@@ -94,8 +94,8 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_SINGLESTEP         4       /* restore singlestep on return to user mode */
 #define TIF_RESTORE_SIGMASK    5       /* restore signal mask in do_signal() */
-#define TIF_POLLING_NRFLAG     16      /* true if poll_idle() is polling TIF_NEED_RESCHED */
-#define TIF_MEMDIE             17      /* is terminating due to OOM killer */
+#define TIF_POLLING_NRFLAG           /* true if poll_idle() is polling TIF_NEED_RESCHED */
+#define TIF_MEMDIE                   /* is terminating due to OOM killer */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
@@ -105,8 +105,16 @@ register struct thread_info *__current_thread_info asm("gr15");
 #define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 
-#define _TIF_WORK_MASK         0x0000FFFE      /* work to do on interrupt/exception return */
-#define _TIF_ALLWORK_MASK      0x0000FFFF      /* work to do on any return to u-space */
+/* work to do on interrupt/exception return */
+#define _TIF_WORK_MASK         \
+       (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED | _TIF_SINGLESTEP)
+
+/* work to do on any return to u-space */
+#define _TIF_ALLWORK_MASK      (_TIF_WORK_MASK | _TIF_SYSCALL_TRACE)
+
+#if _TIF_ALLWORK_MASK >= 0x2000
+#error "_TIF_ALLWORK_MASK won't fit in an ANDI now (see entry.S)"
+#endif
 
 /*
  * Thread-synchronous status.
index 5ba23f715ea5e7f0f3dfcc0cab6a860519e41ec6..7d5e000fd32e0e4d40c78c2fcec1806f17bb1286 100644 (file)
@@ -905,18 +905,19 @@ __syscall_call:
 __syscall_exit:
        LEDS            0x6300
 
-       sti             gr8,@(gr28,#REG_GR(8))  ; save return value
+       # keep current PSR in GR23
+       movsg           psr,gr23
 
-       # rebuild saved psr - execve will change it for init/main.c
        ldi             @(gr28,#REG_PSR),gr22
+
+       sti.p           gr8,@(gr28,#REG_GR(8))  ; save return value
+
+       # rebuild saved psr - execve will change it for init/main.c
        srli            gr22,#1,gr5
        andi.p          gr22,#~PSR_PS,gr22
        andi            gr5,#PSR_PS,gr5
        or              gr5,gr22,gr22
-       ori             gr22,#PSR_S,gr22
-
-       # keep current PSR in GR23
-       movsg           psr,gr23
+       ori.p           gr22,#PSR_S,gr22
 
        # make sure we don't miss an interrupt setting need_resched or sigpending between
        # sampling and the RETT
@@ -924,9 +925,7 @@ __syscall_exit:
        movgs           gr23,psr
 
        ldi             @(gr15,#TI_FLAGS),gr4
-       sethi.p         %hi(_TIF_ALLWORK_MASK),gr5
-       setlo           %lo(_TIF_ALLWORK_MASK),gr5
-       andcc           gr4,gr5,gr0,icc0
+       andicc          gr4,#_TIF_ALLWORK_MASK,gr0,icc0
        bne             icc0,#0,__syscall_exit_work
 
        # restore all registers and return
@@ -1111,9 +1110,7 @@ __entry_resume_userspace:
 __entry_return_from_user_interrupt:
        LEDS            0x6402
        ldi             @(gr15,#TI_FLAGS),gr4
-       sethi.p         %hi(_TIF_WORK_MASK),gr5
-       setlo           %lo(_TIF_WORK_MASK),gr5
-       andcc           gr4,gr5,gr0,icc0
+       andicc          gr4,#_TIF_WORK_MASK,gr0,icc0
        beq             icc0,#1,__entry_return_direct
 
 __entry_work_pending:
@@ -1133,9 +1130,7 @@ __entry_work_resched:
 
        LEDS            0x6401
        ldi             @(gr15,#TI_FLAGS),gr4
-       sethi.p         %hi(_TIF_WORK_MASK),gr5
-       setlo           %lo(_TIF_WORK_MASK),gr5
-       andcc           gr4,gr5,gr0,icc0
+       andicc          gr4,#_TIF_WORK_MASK,gr0,icc0
        beq             icc0,#1,__entry_return_direct
        andicc          gr4,#_TIF_NEED_RESCHED,gr0,icc0
        bne             icc0,#1,__entry_work_resched
@@ -1163,7 +1158,9 @@ __syscall_trace_entry:
        # perform syscall exit tracing
 __syscall_exit_work:
        LEDS            0x6340
-       andicc          gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
+       andicc          gr22,#PSR_PS,gr0,icc1   ; don't handle on return to kernel mode
+       andicc.p        gr4,#_TIF_SYSCALL_TRACE,gr0,icc0
+       bne             icc1,#0,__entry_return_direct
        beq             icc0,#1,__entry_work_pending
 
        movsg           psr,gr23
index 595bf1e5a5dc0262bfc6897fb3b2999ab259fdc7..f3b9064c548c1e3b3870c5a450b9f333d64ff082 100644 (file)
@@ -28,8 +28,6 @@
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 struct fdpic_func_descriptor {
        unsigned long   text;
        unsigned long   GOT;
@@ -149,7 +147,6 @@ asmlinkage int sys_sigreturn(void)
            __copy_from_user(&set.sig[1], &frame->extramask, sizeof(frame->extramask)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(&frame->sc, &gr8))
@@ -172,7 +169,6 @@ asmlinkage int sys_rt_sigreturn(void)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(&frame->uc.uc_mcontext, &gr8))
@@ -426,9 +422,10 @@ give_sigsegv:
 /*
  * OK, we're invoking a handler
  */
-static int handle_signal(unsigned long sig, siginfo_t *info,
-                        struct k_sigaction *ka, sigset_t *oldset)
+static void handle_signal(unsigned long sig, siginfo_t *info,
+                        struct k_sigaction *ka)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Are we from a system call? */
@@ -460,11 +457,11 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        else
                ret = setup_frame(sig, ka, oldset);
 
-       if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+       if (ret)
+               return;
 
+       signal_delivered(sig, info, ka, __frame,
+                                test_thread_flag(TIF_SINGLESTEP));
 } /* end handle_signal() */
 
 /*****************************************************************************/
@@ -477,44 +474,14 @@ static void do_signal(void)
 {
        struct k_sigaction ka;
        siginfo_t info;
-       sigset_t *oldset;
        int signr;
 
-       /*
-        * We want the common case to go fast, which
-        * is why we may in certain cases get here from
-        * kernel mode. Just return without doing anything
-        * if so.
-        */
-       if (!user_mode(__frame))
-               return;
-
-       if (try_to_freeze())
-               goto no_signal;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, __frame, NULL);
        if (signr > 0) {
-               if (handle_signal(signr, &info, &ka, oldset) == 0) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-                       tracehook_signal_handler(signr, &info, &ka, __frame,
-                                                test_thread_flag(TIF_SINGLESTEP));
-               }
-
+               handle_signal(signr, &info, &ka);
                return;
        }
 
-no_signal:
        /* Did we come from a system call? */
        if (__frame->syscallno != -1) {
                /* Restart the system call - no handlers present */
@@ -536,11 +503,7 @@ no_signal:
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
-
+       restore_saved_sigmask();
 } /* end do_signal() */
 
 /*****************************************************************************/
@@ -555,7 +518,7 @@ asmlinkage void do_notify_resume(__u32 thread_info_flags)
                clear_thread_flag(TIF_SINGLESTEP);
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING))
                do_signal();
 
        /* deal with notification on about to resume userspace execution */
index e58992ad789ef0a0822f52616c03aec1126fa699..fca10378701bb9c818b8c123fb4d3c05522cd0c6 100644 (file)
@@ -47,8 +47,6 @@
 #include <asm/traps.h>
 #include <asm/ucontext.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -186,7 +184,6 @@ asmlinkage int do_sigreturn(unsigned long __unused,...)
                              sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        
        if (restore_sigcontext(regs, &frame->sc, &er0))
@@ -211,7 +208,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused,...)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &er0))
@@ -412,8 +408,9 @@ give_sigsegv:
  */
 static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-             sigset_t *oldset, struct pt_regs * regs)
+             struct pt_regs * regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
        /* are we from a system call? */
        if (regs->orig_er0 >= 0) {
@@ -441,10 +438,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (!ret) {
-               block_sigmask(ka, sig);
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-       }
+       if (!ret)
+               signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -457,7 +452,6 @@ statis void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -468,23 +462,14 @@ statis void do_signal(struct pt_regs *regs)
        if ((regs->ccr & 0x10))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        current->thread.esp0 = (unsigned long) regs;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &info, &ka, oldset, regs);
+               handle_signal(signr, &info, &ka, regs);
                return;
        }
- no_signal:
        /* Did we come from a system call? */
        if (regs->orig_er0 >= 0) {
                /* Restart the system call - no handlers present */
@@ -501,8 +486,7 @@ statis void do_signal(struct pt_regs *regs)
        }
 
        /* If there's no signal to deliver, we just restore the saved mask.  */
-       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
-               set_current_blocked(&current->saved_sigmask);
+       restore_saved_sigmask();
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
index 21a3018cb9bf78d9e480737ec87ccd885b2de422..304b0808d07213f0853ee256d781a114f561a947 100644 (file)
@@ -31,8 +31,6 @@
 #include <asm/signal.h>
 #include <asm/vdso.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 struct rt_sigframe {
        unsigned long tramp[2];
        struct siginfo info;
@@ -149,11 +147,9 @@ sigsegv:
 /*
  * Setup invocation of signal handler
  */
-static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
-                        sigset_t *oldset, struct pt_regs *regs)
+static void handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
+                        struct pt_regs *regs)
 {
-       int rc;
-
        /*
         * If we're handling a signal that aborted a system call,
         * set up the error return value before adding the signal
@@ -186,15 +182,12 @@ static int handle_signal(int sig, siginfo_t *info, struct k_sigaction *ka,
         * Set up the stack frame; not doing the SA_SIGINFO thing.  We
         * only set up the rt_frame flavor.
         */
-       rc = setup_rt_frame(sig, ka, info, oldset, regs);
-
        /* If there was an error on setup, no signal was delivered. */
-       if (rc)
-               return rc;
-
-       block_sigmask(ka, sig);
+       if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs) < 0)
+               return;
 
-       return 0;
+       signal_delivered(sig, info, ka, regs,
+                       test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -209,34 +202,13 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        signo = get_signal_to_deliver(&info, &sigact, regs, NULL);
 
        if (signo > 0) {
-               sigset_t *oldset;
-
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       oldset = &current->saved_sigmask;
-               else
-                       oldset = &current->blocked;
-
-               if (handle_signal(signo, &info, &sigact, oldset, regs) == 0) {
-                       /*
-                        * Successful delivery case.  The saved sigmask is
-                        * stored in the signal frame, and will be restored
-                        * by sigreturn.  We can clear the TIF flag.
-                        */
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-                       tracehook_signal_handler(signo, &info, &sigact, regs,
-                               test_thread_flag(TIF_SINGLESTEP));
-               }
+               handle_signal(signo, &info, &sigact, regs);
                return;
        }
 
-no_signal:
        /*
         * If we came from a system call, handle the restart.
         */
@@ -259,10 +231,7 @@ no_signal:
 
 no_restart:
        /* If there's no signal to deliver, put the saved sigmask back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
@@ -301,7 +270,6 @@ asmlinkage int sys_rt_sigreturn(void)
        if (__copy_from_user(&blocked, &frame->uc.uc_sigmask, sizeof(blocked)))
                goto badframe;
 
-       sigdelsetmask(&blocked, ~_BLOCKABLE);
        set_current_blocked(&blocked);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
index 310d9734f02d11a2537311b6860a736ff5fa63a7..f7ee85378311a0f2d241a458640f697b4940a2a1 100644 (file)
@@ -141,7 +141,23 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->status |= TS_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, &ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
 }
 #endif /* !__ASSEMBLY__ */
 
index 7523501d3bc087bbb39a22573776ba365d131aeb..a199be1fe619bc12d00a9e87198b6f919a9f2c74 100644 (file)
@@ -30,7 +30,6 @@
 
 #define DEBUG_SIG      0
 #define STACK_ALIGN    16              /* minimal alignment for stack pointer */
-#define _BLOCKABLE     (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 
 #if _NSIG_WORDS > 1
 # define PUT_SIGSET(k,u)       __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t))
@@ -200,7 +199,6 @@ ia64_rt_sigreturn (struct sigscratch *scr)
        if (GET_SIGSET(&set, &sc->sc_mask))
                goto give_sigsegv;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(sc, scr))
@@ -415,18 +413,13 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
 }
 
 static long
-handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset,
+handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
               struct sigscratch *scr)
 {
-       if (!setup_frame(sig, ka, info, oldset, scr))
+       if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
                return 0;
 
-       block_sigmask(ka, sig);
-
-       /*
-        * Let tracing know that we've done the handler setup.
-        */
-       tracehook_signal_handler(sig, info, ka, &scr->pt,
+       signal_delivered(sig, info, ka, &scr->pt,
                                 test_thread_flag(TIF_SINGLESTEP));
 
        return 1;
@@ -440,7 +433,6 @@ void
 ia64_do_signal (struct sigscratch *scr, long in_syscall)
 {
        struct k_sigaction ka;
-       sigset_t *oldset;
        siginfo_t info;
        long restart = in_syscall;
        long errno = scr->pt.r8;
@@ -453,11 +445,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
        if (!user_mode(&scr->pt))
                return;
 
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        /*
         * This only loops in the rare cases of handle_signal() failing, in which case we
         * need to push through a forced SIGSEGV.
@@ -507,16 +494,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
                 * Whee!  Actually deliver the signal.  If the delivery failed, we need to
                 * continue to iterate in this loop so we can deliver the SIGSEGV...
                 */
-               if (handle_signal(signr, &ka, &info, oldset, scr)) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TS_RESTORE_SIGMASK flag.
-                        */
-                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+               if (handle_signal(signr, &ka, &info, scr))
                        return;
-               }
        }
 
        /* Did we come from a system call? */
@@ -538,8 +517,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
index 64804f1f5141dcb2a82e21784cfb4598d803b0ef..f3fb2c029cfcab061fbbfb5697273067e57c38e8 100644 (file)
@@ -28,8 +28,6 @@
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 asmlinkage int
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                unsigned long r2, unsigned long r3, unsigned long r4,
@@ -111,7 +109,6 @@ sys_rt_sigreturn(unsigned long r0, unsigned long r1,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &result))
@@ -267,9 +264,9 @@ static int prev_insn(struct pt_regs *regs)
  * OK, we're invoking a handler
  */
 
-static int
+static void
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs *regs)
+             struct pt_regs *regs)
 {
        /* Are we from a system call? */
        if (regs->syscall_nr >= 0) {
@@ -294,11 +291,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
        }
 
        /* Set up the stack frame */
-       if (setup_rt_frame(sig, ka, info, oldset, regs))
-               return -EFAULT;
+       if (setup_rt_frame(sig, ka, info, sigmask_to_save(), regs))
+               return;
 
-       block_sigmask(ka, sig);
-       return 0;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -311,7 +307,6 @@ static void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -322,14 +317,6 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze()) 
-               goto no_signal;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Re-enable any watchpoints before delivering the
@@ -339,13 +326,11 @@ static void do_signal(struct pt_regs *regs)
                 */
 
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0)
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+               handle_signal(signr, &ka, &info, regs);
 
                return;
        }
 
- no_signal:
        /* Did we come from a system call? */
        if (regs->syscall_nr >= 0) {
                /* Restart the system call - no handlers present */
@@ -360,10 +345,7 @@ static void do_signal(struct pt_regs *regs)
                        prev_insn(regs);
                }
        }
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 /*
index 973eec60cad45527a872181e60d9c81d6630fa98..710a528b928b8580ac4281449586ee4507966db9 100644 (file)
@@ -51,8 +51,6 @@
 #include <asm/traps.h>
 #include <asm/ucontext.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 #ifdef CONFIG_MMU
 
 /*
@@ -795,7 +793,6 @@ asmlinkage int do_sigreturn(unsigned long __unused)
                              sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc, frame + 1))
@@ -820,7 +817,6 @@ asmlinkage int do_rt_sigreturn(unsigned long __unused)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (rt_restore_ucontext(regs, sw, &frame->uc))
@@ -1123,8 +1119,9 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
  */
 static void
 handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs *regs)
+             struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int err;
        /* are we from a system call? */
        if (regs->orig_d0 >= 0)
@@ -1140,14 +1137,12 @@ handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
        if (err)
                return;
 
-       block_sigmask(ka, sig);
+       signal_delivered(sig, info, ka, regs, 0);
 
        if (test_thread_flag(TIF_DELAYED_TRACE)) {
                regs->sr &= ~0x8000;
                send_sig(SIGTRAP, current, 1);
        }
-
-       clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 
 /*
@@ -1160,19 +1155,13 @@ static void do_signal(struct pt_regs *regs)
        siginfo_t info;
        struct k_sigaction ka;
        int signr;
-       sigset_t *oldset;
 
        current->thread.esp0 = (unsigned long) regs;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               handle_signal(signr, &ka, &info, oldset, regs);
+               handle_signal(signr, &ka, &info, regs);
                return;
        }
 
@@ -1182,10 +1171,7 @@ static void do_signal(struct pt_regs *regs)
                handle_restart(regs, NULL, 0);
 
        /* If there's no signal to deliver, we just restore the saved mask.  */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs)
index 1a8ab6a5c03fc3ab399cd8fa75003b4220e69cd5..6c610234ffab96c8d849dfc8dac498bfaf1c9919 100644 (file)
@@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->status |= TS_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
 }
 #endif
 
index 5d796e32786ea55bb9960e875b55d1e8c0757c3e..76b9722557db77e99a3500154a34b8ed6556d958 100644 (file)
@@ -41,8 +41,6 @@
 #include <asm/cacheflush.h>
 #include <asm/syscalls.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 asmlinkage long
 sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
                struct pt_regs *regs)
@@ -106,7 +104,6 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &rval))
@@ -310,10 +307,11 @@ do_restart:
  * OK, we're invoking a handler
  */
 
-static int
+static void
 handle_signal(unsigned long sig, struct k_sigaction *ka,
-               siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+               siginfo_t *info, struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Set up the stack frame */
@@ -323,11 +321,9 @@ handle_signal(unsigned long sig, struct k_sigaction *ka,
                ret = setup_rt_frame(sig, ka, NULL, oldset, regs);
 
        if (ret)
-               return ret;
-
-       block_sigmask(ka, sig);
+               return;
 
-       return 0;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -344,33 +340,18 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 #ifdef DEBUG_SIG
        printk(KERN_INFO "do signal: %p %d\n", regs, in_syscall);
        printk(KERN_INFO "do signal2: %lx %lx %ld [%lx]\n", regs->pc, regs->r1,
                        regs->r12, current_thread_info()->flags);
 #endif
 
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee! Actually deliver the signal. */
                if (in_syscall)
                        handle_restart(regs, &ka, 1);
-               if (!handle_signal(signr, &ka, &info, oldset, regs)) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TS_RESTORE_SIGMASK flag.
-                        */
-                       current_thread_info()->status &=
-                           ~TS_RESTORE_SIGMASK;
-               }
+               handle_signal(signr, &ka, &info, regs);
                return;
        }
 
@@ -381,10 +362,7 @@ static void do_signal(struct pt_regs *regs, int in_syscall)
         * If there's no signal to deliver, we just put the saved sigmask
         * back.
         */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs, int in_syscall)
index 10263b405981f0eb4604f1d38bd3887e10f1c129..9c60d09e62a71521007c3cae0894cdcf09f01424 100644 (file)
@@ -19,8 +19,6 @@
 #  define DEBUGP(fmt, args...)
 #endif
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * Determine which stack to use..
  */
index 8a6e6d116ab0399b2697d6a67660c23107229bf5..f2c09cfc60ac338dc9300f3487bae83e48a8cbd1 100644 (file)
@@ -339,7 +339,6 @@ asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
        if (__copy_from_user(&blocked, &frame->sf_mask, sizeof(blocked)))
                goto badframe;
 
-       sigdelsetmask(&blocked, ~_BLOCKABLE);
        set_current_blocked(&blocked);
 
        sig = restore_sigcontext(&regs, &frame->sf_sc);
@@ -375,7 +374,6 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
@@ -514,9 +512,10 @@ struct mips_abi mips_abi = {
        .restart        = __NR_restart_syscall
 };
 
-static int handle_signal(unsigned long sig, siginfo_t *info,
-       struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
+static void handle_signal(unsigned long sig, siginfo_t *info,
+       struct k_sigaction *ka, struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
        struct mips_abi *abi = current->thread.abi;
        void *vdso = current->mm->context.vdso;
@@ -550,17 +549,14 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
                                       ka, regs, sig, oldset);
 
        if (ret)
-               return ret;
-
-       block_sigmask(ka, sig);
+               return;
 
-       return ret;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 static void do_signal(struct pt_regs *regs)
 {
        struct k_sigaction ka;
-       sigset_t *oldset;
        siginfo_t info;
        int signr;
 
@@ -572,25 +568,10 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag.
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
-
+               handle_signal(signr, &info, &ka, regs);
                return;
        }
 
@@ -614,10 +595,7 @@ static void do_signal(struct pt_regs *regs)
         * If there's no signal to deliver, we just put the saved sigmask
         * back
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 /*
@@ -630,7 +608,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, void *unused,
        local_irq_enable();
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
index b4fe2eacbd5d258a55146f5d51154491119569e8..da1b56a39ac77815b4989183fd07821286468dfe 100644 (file)
@@ -465,7 +465,6 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
        if (__copy_conv_sigset_from_user(&blocked, &frame->sf_mask))
                goto badframe;
 
-       sigdelsetmask(&blocked, ~_BLOCKABLE);
        set_current_blocked(&blocked);
 
        sig = restore_sigcontext32(&regs, &frame->sf_sc);
@@ -503,7 +502,6 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        sig = restore_sigcontext32(&regs, &frame->rs_uc.uc_mcontext);
index 63ffac9af7c5b61fa9fa966e641889f935b7d747..3574c145511be486b0feb82177ced3c80679d180 100644 (file)
@@ -109,7 +109,6 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
index b8b6aa1a68379d7d563baa2263858ec640d0fa0f..6ab0bee2a54fd38efeccbaa683b4437f26406a34 100644 (file)
@@ -31,8 +31,6 @@
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * atomically swap in the new signal mask, and wait for a signal.
  */
@@ -163,7 +161,6 @@ asmlinkage long sys_sigreturn(void)
                             sizeof(frame->extramask)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(current_frame(), &frame->sc, &d0))
@@ -191,7 +188,6 @@ asmlinkage long sys_rt_sigreturn(void)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(current_frame(), &frame->uc.uc_mcontext, &d0))
@@ -430,8 +426,9 @@ static inline void stepback(struct pt_regs *regs)
  */
 static int handle_signal(int sig,
                         siginfo_t *info, struct k_sigaction *ka,
-                        sigset_t *oldset, struct pt_regs *regs)
+                        struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Are we from a system call? */
@@ -461,11 +458,11 @@ static int handle_signal(int sig,
                ret = setup_rt_frame(sig, ka, info, oldset, regs);
        else
                ret = setup_frame(sig, ka, oldset, regs);
+       if (ret)
+               return;
 
-       if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+       signal_delivered(sig, info, ka, regs,
+                                test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -475,7 +472,6 @@ static void do_signal(struct pt_regs *regs)
 {
        struct k_sigaction ka;
        siginfo_t info;
-       sigset_t *oldset;
        int signr;
 
        /* we want the common case to go fast, which is why we may in certain
@@ -483,23 +479,9 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
-               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-                       tracehook_signal_handler(signr, &info, &ka, regs,
-                                                test_thread_flag(TIF_SINGLESTEP));
+               if (handle_signal(signr, &info, &ka, regs) == 0) {
                }
 
                return;
@@ -525,10 +507,7 @@ static void do_signal(struct pt_regs *regs)
 
        /* if there's no signal to deliver, we just put the saved sigmask
         * back */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 /*
@@ -548,7 +527,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, u32 thread_info_flags)
        }
 
        /* deal with pending signal delivery */
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs);
 
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
index 9ae61152295348e7d5bc4e05e731884703d8018b..30110297f4f9509d6437c8f5c3e80220add6e2a9 100644 (file)
@@ -33,8 +33,6 @@
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 asmlinkage long
 _sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
 {
@@ -101,7 +99,6 @@ asmlinkage long _sys_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@@ -251,20 +248,19 @@ give_sigsegv:
        return -EFAULT;
 }
 
-static inline int
+static inline void
 handle_signal(unsigned long sig,
              siginfo_t *info, struct k_sigaction *ka,
-             sigset_t *oldset, struct pt_regs *regs)
+             struct pt_regs *regs)
 {
        int ret;
 
-       ret = setup_rt_frame(sig, ka, info, oldset, regs);
+       ret = setup_rt_frame(sig, ka, info, sigmask_to_save(), regs);
        if (ret)
-               return ret;
-
-       block_sigmask(ka, sig);
+               return;
 
-       return 0;
+       signal_delivered(sig, info, ka, regs,
+                                test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -339,30 +335,10 @@ void do_signal(struct pt_regs *regs)
        if (signr <= 0) {
                /* no signal to deliver so we just put the saved sigmask
                 * back */
-               if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-               }
-
+               restore_saved_sigmask();
        } else {                /* signr > 0 */
-               sigset_t *oldset;
-
-               if (current_thread_info()->flags & _TIF_RESTORE_SIGMASK)
-                       oldset = &current->saved_sigmask;
-               else
-                       oldset = &current->blocked;
-
                /* Whee!  Actually deliver the signal.  */
-               if (!handle_signal(signr, &info, &ka, oldset, regs)) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag */
-                       clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
-
-               tracehook_signal_handler(signr, &info, &ka, regs,
-                                        test_thread_flag(TIF_SINGLESTEP));
+               handle_signal(signr, &info, &ka, regs);
        }
 
        return;
index 83ae7dd4d99ea721adbdc16a751435db902da354..22b4726dee494403c80bdf2f88c583ba32043b94 100644 (file)
@@ -74,7 +74,7 @@ struct thread_info {
 #define _TIF_BLOCKSTEP         (1 << TIF_BLOCKSTEP)
 
 #define _TIF_USER_WORK_MASK     (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | \
-                                 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
+                                 _TIF_NEED_RESCHED)
 
 #endif /* __KERNEL__ */
 
index c7fbc96472f3f9e8ae8013fb72528d9f81d584d8..18670a078849b96d92d4dd4ff406a79c2caa28a4 100644 (file)
@@ -924,7 +924,7 @@ intr_check_sig:
        /* As above */
        mfctl   %cr30,%r1
        LDREG   TI_FLAGS(%r1),%r19
-       ldi     (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r20
+       ldi     (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r20
        and,COND(<>)    %r19, %r20, %r0
        b,n     intr_restore    /* skip past if we've nothing to do */
 
@@ -2032,7 +2032,7 @@ syscall_check_resched:
        .import do_signal,code
 syscall_check_sig:
        LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
-       ldi     (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK|_TIF_NOTIFY_RESUME), %r26
+       ldi     (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), %r26
        and,COND(<>)    %r19, %r26, %r0
        b,n     syscall_restore /* skip past if we've nothing to do */
 
index e7a7cd3e112009272fbe584de682d856e7e52ac5..594459bde14ed3c927b7dddce88e1d9cf9863e74 100644 (file)
@@ -48,9 +48,6 @@
 #define DBG(LEVEL, ...)
 #endif
        
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /* gcc will complain if a pointer is cast to an integer of different
  * size.  If you really need to do this (and we do for an ELF32 user
  * application in an ELF64 kernel) then you have to do a cast to an
@@ -131,7 +128,6 @@ sys_rt_sigreturn(struct pt_regs *regs, int in_syscall)
                        goto give_sigsegv;
        }
                
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        /* Good thing we saved the old gr[30], eh? */
@@ -443,8 +439,9 @@ give_sigsegv:
 
 static long
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-               sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+               struct pt_regs *regs, int in_syscall)
 {
+       sigset_t *oldset = sigmask_to_save();
        DBG(1,"handle_signal: sig=%ld, ka=%p, info=%p, oldset=%p, regs=%p\n",
               sig, ka, info, oldset, regs);
        
@@ -452,12 +449,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        if (!setup_rt_frame(sig, ka, info, oldset, regs, in_syscall))
                return 0;
 
-       block_sigmask(ka, sig);
-
-       tracehook_signal_handler(sig, info, ka, regs, 
+       signal_delivered(sig, info, ka, regs, 
                test_thread_flag(TIF_SINGLESTEP) ||
                test_thread_flag(TIF_BLOCKSTEP));
 
+       DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
+               regs->gr[28]);
+
        return 1;
 }
 
@@ -568,28 +566,17 @@ do_signal(struct pt_regs *regs, long in_syscall)
        siginfo_t info;
        struct k_sigaction ka;
        int signr;
-       sigset_t *oldset;
 
-       DBG(1,"\ndo_signal: oldset=0x%p, regs=0x%p, sr7 %#lx, in_syscall=%d\n",
-              oldset, regs, regs->sr[7], in_syscall);
+       DBG(1,"\ndo_signal: regs=0x%p, sr7 %#lx, in_syscall=%d\n",
+              regs, regs->sr[7], in_syscall);
 
        /* Everyone else checks to see if they are in kernel mode at
           this point and exits if that's the case.  I'm not sure why
           we would be called in that case, but for some reason we
           are. */
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
-       DBG(1,"do_signal: oldset %08lx / %08lx\n", 
-               oldset->sig[0], oldset->sig[1]);
-
-
        /* May need to force signal if handle_signal failed to deliver */
        while (1) {
-         
                signr = get_signal_to_deliver(&info, &ka, regs, NULL);
                DBG(3,"do_signal: signr = %d, regs->gr[28] = %ld\n", signr, regs->gr[28]); 
        
@@ -603,14 +590,8 @@ do_signal(struct pt_regs *regs, long in_syscall)
                /* Whee!  Actually deliver the signal.  If the
                   delivery failed, we need to continue to iterate in
                   this loop so we can deliver the SIGSEGV... */
-               if (handle_signal(signr, &info, &ka, oldset,
-                                 regs, in_syscall)) {
-                       DBG(1,KERN_DEBUG "do_signal: Exit (success), regs->gr[28] = %ld\n",
-                               regs->gr[28]);
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               if (handle_signal(signr, &info, &ka, regs, in_syscall))
                        return;
-               }
        }
        /* end of while(1) looping forever if we can't force a signal */
 
@@ -621,18 +602,12 @@ do_signal(struct pt_regs *regs, long in_syscall)
        DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
                regs->gr[28]);
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
-
-       return;
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs, long in_syscall)
 {
-       if (test_thread_flag(TIF_SIGPENDING) ||
-           test_thread_flag(TIF_RESTORE_SIGMASK))
+       if (test_thread_flag(TIF_SIGPENDING))
                do_signal(regs, in_syscall);
 
        if (test_thread_flag(TIF_NOTIFY_RESUME)) {
index e14132430762414166a729ae57e647ec5b9f1316..fd49aeda9eb8b0c4fef656e3dc00228c59251b99 100644 (file)
@@ -47,8 +47,6 @@
 #define DBG(LEVEL, ...)
 #endif
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 inline void
 sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
 {
index a556ccc16b58d4560b004c1ee797f8e92c7c6506..68831e9cf82f01ddf8f12164962d8db438b93af3 100644 (file)
@@ -140,7 +140,23 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->local_flags |= _TLF_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, &ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->local_flags & _TLF_RESTORE_SIGMASK))
+               return false;
+       ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
+       return true;
 }
 
 static inline bool test_thread_local_flags(unsigned int flags)
index bfc3ec1382fbf4edb3530857e21152d0539cd64b..5c023c9cf16ee70a7a3b281af2ad9807028c3b13 100644 (file)
@@ -51,16 +51,6 @@ void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
         return (void __user *)newsp;
 }
 
-
-/*
- * Restore the user process's signal mask
- */
-void restore_sigmask(sigset_t *set)
-{
-       sigdelsetmask(set, ~_BLOCKABLE);
-       set_current_blocked(set);
-}
-
 static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
                                  int has_handler)
 {
@@ -114,30 +104,21 @@ static void check_syscall_restart(struct pt_regs *regs, struct k_sigaction *ka,
 
 static int do_signal(struct pt_regs *regs)
 {
-       sigset_t *oldset;
+       sigset_t *oldset = sigmask_to_save();
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
        int ret;
        int is32 = is_32bit_task();
 
-       if (current_thread_info()->local_flags & _TLF_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
        /* Is there any syscall restart business here ? */
        check_syscall_restart(regs, &ka, signr > 0);
 
        if (signr <= 0) {
-               struct thread_info *ti = current_thread_info();
                /* No signal to deliver -- put the saved sigmask back */
-               if (ti->local_flags & _TLF_RESTORE_SIGMASK) {
-                       ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
-                       sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-               }
+               restore_saved_sigmask();
                regs->trap = 0;
                return 0;               /* no signals delivered */
        }
@@ -167,18 +148,7 @@ static int do_signal(struct pt_regs *regs)
 
        regs->trap = 0;
        if (ret) {
-               block_sigmask(&ka, signr);
-
-               /*
-                * A signal was successfully delivered; the saved sigmask is in
-                * its frame, and we can clear the TLF_RESTORE_SIGMASK flag.
-                */
-               current_thread_info()->local_flags &= ~_TLF_RESTORE_SIGMASK;
-
-               /*
-                * Let tracing know that we've done the handler setup.
-                */
-               tracehook_signal_handler(signr, &info, &ka, regs,
+               signal_delivered(signr, &info, &ka, regs,
                                         test_thread_flag(TIF_SINGLESTEP));
        }
 
index 8dde973aaaf513ffd4c39a41f0f3bf2bead0d7db..e00acb4139346074ddfbda1c6553010614a2d78c 100644 (file)
 #ifndef _POWERPC_ARCH_SIGNAL_H
 #define _POWERPC_ARCH_SIGNAL_H
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 extern void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags);
 
 extern void __user * get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
                                  size_t frame_size, int is_32);
-extern void restore_sigmask(sigset_t *set);
 
 extern int handle_signal32(unsigned long sig, struct k_sigaction *ka,
                           siginfo_t *info, sigset_t *oldset,
index 61f6aff25edc3f94010bda48710d6a1f27e65161..8b4c049aee20e8604fa83a9a017366213d0ab6d9 100644 (file)
@@ -919,7 +919,7 @@ static int do_setcontext(struct ucontext __user *ucp, struct pt_regs *regs, int
        if (!access_ok(VERIFY_READ, mcp, sizeof(*mcp)))
                return -EFAULT;
 #endif
-       restore_sigmask(&set);
+       set_current_blocked(&set);
        if (restore_user_regs(regs, mcp, sig))
                return -EFAULT;
 
@@ -1273,7 +1273,7 @@ long sys_sigreturn(int r3, int r4, int r5, int r6, int r7, int r8,
        set.sig[0] = sigctx.oldmask;
        set.sig[1] = sigctx._unused[3];
 #endif
-       restore_sigmask(&set);
+       set_current_blocked(&set);
 
        sr = (struct mcontext __user *)from_user_ptr(sigctx.regs);
        addr = sr;
index 2692efdb154e210a5aa787e021ed960cb3bde591..d183f8719a505ce18e4cc8cb06ee4df3e8fa8674 100644 (file)
@@ -335,7 +335,7 @@ int sys_swapcontext(struct ucontext __user *old_ctx,
 
        if (__copy_from_user(&set, &new_ctx->uc_sigmask, sizeof(set)))
                do_exit(SIGSEGV);
-       restore_sigmask(&set);
+       set_current_blocked(&set);
        if (restore_sigcontext(regs, NULL, 0, &new_ctx->uc_mcontext))
                do_exit(SIGSEGV);
 
@@ -364,7 +364,7 @@ int sys_rt_sigreturn(unsigned long r3, unsigned long r4, unsigned long r5,
 
        if (__copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
                goto badframe;
-       restore_sigmask(&set);
+       set_current_blocked(&set);
        if (restore_sigcontext(regs, NULL, 1, &uc->uc_mcontext))
                goto badframe;
 
index 377c096ca4a72c658327b543127692c1e1a91f0c..3c0c19830c37f5a0f7896d0a292762b794b30a74 100644 (file)
@@ -32,8 +32,6 @@
 #include "compat_ptrace.h"
 #include "entry.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 typedef struct 
 {
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE32];
@@ -364,7 +362,6 @@ asmlinkage long sys32_sigreturn(void)
                goto badframe;
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE32))
                goto badframe;
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->sregs))
                goto badframe;
@@ -390,7 +387,6 @@ asmlinkage long sys32_rt_sigreturn(void)
                goto badframe;
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        if (restore_sigregs32(regs, &frame->uc.uc_mcontext))
                goto badframe;
@@ -572,7 +568,7 @@ give_sigsegv:
  * OK, we're invoking a handler
  */    
 
-int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+void handle_signal32(unsigned long sig, struct k_sigaction *ka,
                    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
 {
        int ret;
@@ -583,8 +579,8 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
        else
                ret = setup_frame32(sig, ka, oldset, regs);
        if (ret)
-               return ret;
-       block_sigmask(ka, sig);
-       return 0;
+               return;
+       signal_delivered(sig, info, ka, regs,
+                                test_thread_flag(TIF_SINGLE_STEP));
 }
 
index 6cdddac93a2e48ed47f58d74648c5d858c7d8557..f66a229ab0b3fdf52308cb55c0ab627ef9564a7b 100644 (file)
@@ -31,7 +31,7 @@ void do_per_trap(struct pt_regs *regs);
 void syscall_trace(struct pt_regs *regs, int entryexit);
 void kernel_stack_overflow(struct pt_regs * regs);
 void do_signal(struct pt_regs *regs);
-int handle_signal32(unsigned long sig, struct k_sigaction *ka,
+void handle_signal32(unsigned long sig, struct k_sigaction *ka,
                    siginfo_t *info, sigset_t *oldset, struct pt_regs *regs);
 void do_notify_resume(struct pt_regs *regs);
 
index 42a6e8b47f06ca1ff8c7dd3009e63107f8dacead..ac565b44aabbf76c23da00540f8f2884e06f07a6 100644 (file)
@@ -33,9 +33,6 @@
 #include <asm/switch_to.h>
 #include "entry.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-
 typedef struct 
 {
        __u8 callee_used_stack[__SIGNAL_FRAMESIZE];
@@ -169,7 +166,6 @@ SYSCALL_DEFINE0(sigreturn)
                goto badframe;
        if (__copy_from_user(&set.sig, &frame->sc.oldmask, _SIGMASK_COPY_SIZE))
                goto badframe;
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        if (restore_sigregs(regs, &frame->sregs))
                goto badframe;
@@ -189,7 +185,6 @@ SYSCALL_DEFINE0(rt_sigreturn)
                goto badframe;
        if (__copy_from_user(&set.sig, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        if (restore_sigregs(regs, &frame->uc.uc_mcontext))
                goto badframe;
@@ -367,7 +362,7 @@ give_sigsegv:
        return -EFAULT;
 }
 
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
+static void handle_signal(unsigned long sig, struct k_sigaction *ka,
                         siginfo_t *info, sigset_t *oldset,
                         struct pt_regs *regs)
 {
@@ -379,9 +374,9 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
        else
                ret = setup_frame(sig, ka, oldset, regs);
        if (ret)
-               return ret;
-       block_sigmask(ka, sig);
-       return 0;
+               return;
+       signal_delivered(sig, info, ka, regs,
+                                test_thread_flag(TIF_SINGLE_STEP));
 }
 
 /*
@@ -398,12 +393,7 @@ void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
+       sigset_t *oldset = sigmask_to_save();
 
        /*
         * Get signal to deliver. When running under ptrace, at this point
@@ -441,24 +431,10 @@ void do_signal(struct pt_regs *regs)
                /* No longer in a system call */
                clear_thread_flag(TIF_SYSCALL);
 
-               if ((is_compat_task() ?
-                    handle_signal32(signr, &ka, &info, oldset, regs) :
-                    handle_signal(signr, &ka, &info, oldset, regs)) == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag.
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-
-                       /*
-                        * Let tracing know that we've done the handler setup.
-                        */
-                       tracehook_signal_handler(signr, &info, &ka, regs,
-                                        test_thread_flag(TIF_SINGLE_STEP));
-               }
+               if (is_compat_task())
+                       handle_signal32(signr, &ka, &info, oldset, regs);
+               else
+                       handle_signal(signr, &ka, &info, oldset, regs);
                return;
        }
 
@@ -484,10 +460,7 @@ void do_signal(struct pt_regs *regs)
        /*
         * If there's no signal to deliver, we just put the saved sigmask back.
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs)
index 302838d3acf6ce890e56a06b57e4a337421b1089..e382c52ca0d90b455d9bee68f7587f4278d36bc8 100644 (file)
@@ -34,8 +34,6 @@
 #include <asm/syscalls.h>
 #include <asm/ucontext.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 struct rt_sigframe {
        u32 rs_ass[4];          /* argument save space */
        u32 rs_code[2];         /* signal trampoline */
@@ -162,7 +160,6 @@ score_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        sig = restore_sigcontext(regs, &frame->rs_uc.uc_mcontext);
@@ -241,11 +238,9 @@ give_sigsegv:
        return -EFAULT;
 }
 
-static int handle_signal(unsigned long sig, siginfo_t *info,
-       struct k_sigaction *ka, sigset_t *oldset, struct pt_regs *regs)
+static void handle_signal(unsigned long sig, siginfo_t *info,
+       struct k_sigaction *ka, struct pt_regs *regs)
 {
-       int ret;
-
        if (regs->is_syscall) {
                switch (regs->regs[4]) {
                case ERESTART_RESTARTBLOCK:
@@ -269,18 +264,15 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        /*
         * Set up the stack frame
         */
-       ret = setup_rt_frame(ka, regs, sig, oldset, info);
-
-       if (ret == 0)
-               block_sigmask(ka, sig);
+       if (setup_rt_frame(ka, regs, sig, sigmask_to_save(), info) < 0)
+               return;
 
-       return ret;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 static void do_signal(struct pt_regs *regs)
 {
        struct k_sigaction ka;
-       sigset_t *oldset;
        siginfo_t info;
        int signr;
 
@@ -292,25 +284,10 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Actually deliver the signal.  */
-               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag.
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
-
+               handle_signal(signr, &info, &ka, regs);
                return;
        }
 
@@ -337,10 +314,7 @@ static void do_signal(struct pt_regs *regs)
         * If there's no signal to deliver, we just put the saved sigmask
         * back
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 /*
index 0c04ffc4f12c41d344eded872aea06aaf7232e2b..bc13b57cdc834210b95aaa70ea603298ed55f468 100644 (file)
@@ -169,7 +169,7 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->status |= TS_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
 }
 
 #define TI_FLAG_FAULT_CODE_SHIFT       24
@@ -189,6 +189,23 @@ static inline unsigned int get_thread_fault_code(void)
        struct thread_info *ti = current_thread_info();
        return ti->flags >> TI_FLAG_FAULT_CODE_SHIFT;
 }
+
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
+}
 #endif /* !__ASSEMBLY__ */
 
 #endif /* __KERNEL__ */
index 9d7bfd66f189c4024665e6f486aea1fded24b3d8..d6b7b6154f8764576abac916033326ba1c1e6bd2 100644 (file)
@@ -32,8 +32,6 @@
 #include <asm/syscalls.h>
 #include <asm/fpu.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 struct fdpic_func_descriptor {
        unsigned long   text;
        unsigned long   GOT;
@@ -226,7 +224,6 @@ asmlinkage int sys_sigreturn(unsigned long r4, unsigned long r5,
                                    sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc, &r0))
@@ -256,7 +253,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r4, unsigned long r5,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
@@ -522,10 +518,11 @@ handle_syscall_restart(unsigned long save_r0, struct pt_regs *regs,
 /*
  * OK, we're invoking a handler
  */
-static int
+static void
 handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
-             sigset_t *oldset, struct pt_regs *regs, unsigned int save_r0)
+             struct pt_regs *regs, unsigned int save_r0)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Set up the stack frame */
@@ -534,10 +531,10 @@ handle_signal(unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ret == 0)
-               block_sigmask(ka, sig);
-
-       return ret;
+       if (ret)
+               return;
+       signal_delivered(sig, info, ka, regs,
+                       test_thread_flag(TIF_SINGLESTEP));
 }
 
 /*
@@ -554,7 +551,6 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -565,30 +561,12 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
        if (!user_mode(regs))
                return;
 
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                handle_syscall_restart(save_r0, regs, &ka.sa);
 
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &ka, &info, oldset,
-                                 regs, save_r0) == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TS_RESTORE_SIGMASK flag
-                        */
-                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-
-                       tracehook_signal_handler(signr, &info, &ka, regs,
-                                       test_thread_flag(TIF_SINGLESTEP));
-               }
-
+               handle_signal(signr, &ka, &info, regs, save_r0);
                return;
        }
 
@@ -610,10 +588,7 @@ static void do_signal(struct pt_regs *regs, unsigned int save_r0)
         * If there's no signal to deliver, we just put the saved sigmask
         * back.
         */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned int save_r0,
index aa6428430842a25399c06e7df21c4dd9ee0b9803..6b5b3dfe886b2d3c15a4b08a4d4f21ab74e90da0 100644 (file)
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-static int
+static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-               sigset_t *oldset, struct pt_regs * regs);
+               struct pt_regs * regs);
 
 static inline void
 handle_syscall_restart(struct pt_regs *regs, struct sigaction *sa)
@@ -88,7 +86,6 @@ static void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * We want the common case to go fast, which
@@ -99,28 +96,13 @@ static void do_signal(struct pt_regs *regs)
        if (!user_mode(regs))
                return;
 
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, 0);
        if (signr > 0) {
                handle_syscall_restart(regs, &ka.sa);
 
                /* Whee!  Actually deliver the signal.  */
-               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /*
-                        * If a signal was successfully delivered, the
-                        * saved sigmask is in its frame, and we can
-                        * clear the TS_RESTORE_SIGMASK flag.
-                        */
-                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-
-                       tracehook_signal_handler(signr, &info, &ka, regs,
-                                       test_thread_flag(TIF_SINGLESTEP));
-                       return;
-               }
+               handle_signal(signr, &info, &ka, regs);
+               return;
        }
 
        /* Did we come from a system call? */
@@ -143,12 +125,7 @@ static void do_signal(struct pt_regs *regs)
        }
 
        /* No signal to deliver -- put the saved sigmask back */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
-
-       return;
+       restore_saved_sigmask();
 }
 
 /*
@@ -351,7 +328,6 @@ asmlinkage int sys_sigreturn(unsigned long r2, unsigned long r3,
                                    sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc, &ret))
@@ -384,7 +360,6 @@ asmlinkage int sys_rt_sigreturn(unsigned long r2, unsigned long r3,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ret))
@@ -659,10 +634,11 @@ give_sigsegv:
 /*
  * OK, we're invoking a handler
  */
-static int
+static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
-               sigset_t *oldset, struct pt_regs * regs)
+               struct pt_regs * regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Set up the stack frame */
@@ -671,10 +647,11 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
        else
                ret = setup_frame(sig, ka, oldset, regs);
 
-       if (ret == 0)
-               block_sigmask(ka, sig);
+       if (ret)
+               return;
 
-       return ret;
+       signal_delivered(sig, info, ka, regs,
+                       test_thread_flag(TIF_SINGLESTEP));
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
index 5af664932452190e66543500d21c9dcd6ba48763..e6cd224506a9355168ebea0c5ed0be8c3b625120 100644 (file)
@@ -131,8 +131,7 @@ register struct thread_info *current_thread_info_reg asm("g6");
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 
 #define _TIF_DO_NOTIFY_RESUME_MASK     (_TIF_NOTIFY_RESUME | \
-                                        _TIF_SIGPENDING | \
-                                        _TIF_RESTORE_SIGMASK)
+                                        _TIF_SIGPENDING)
 
 #endif /* __KERNEL__ */
 
index 7f0981b094517aace2b461e2f6d7db9aa6d0fbfa..cfa8c38fb9c8511d51cfbe17e3d8792584d8b241 100644 (file)
@@ -238,7 +238,23 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->status |= TS_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, &ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
 }
 #endif /* !__ASSEMBLY__ */
 
index bb1513e45f1a811b05a07979995726b99eca1a94..a53e0a5fd3a3d944a5eb42391e2862c92a23c044 100644 (file)
@@ -32,8 +32,6 @@
 
 #include "sigutil.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /* This magic should be in g_upper[0] for all upper parts
  * to be valid.
  */
@@ -274,7 +272,6 @@ void do_sigreturn32(struct pt_regs *regs)
                case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32);
                case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32);
        }
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        return;
 
@@ -376,7 +373,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
                case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32);
                case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32);
        }
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        return;
 segv:
@@ -775,7 +771,7 @@ sigsegv:
        return -EFAULT;
 }
 
-static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
+static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
                                  siginfo_t *info,
                                  sigset_t *oldset, struct pt_regs *regs)
 {
@@ -787,12 +783,9 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka,
                err = setup_frame32(ka, regs, signr, oldset);
 
        if (err)
-               return err;
-
-       block_sigmask(ka, signr);
-       tracehook_signal_handler(signr, info, ka, regs, 0);
+               return;
 
-       return 0;
+       signal_delivered(signr, info, ka, regs, 0);
 }
 
 static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs,
@@ -841,14 +834,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)
        if (signr > 0) {
                if (restart_syscall)
                        syscall_restart32(orig_i0, regs, &ka.sa);
-               if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) {
-                       /* A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TS_RESTORE_SIGMASK flag.
-                        */
-                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               }
+               handle_signal32(signr, &ka, &info, oldset, regs);
                return;
        }
        if (restart_syscall &&
@@ -872,10 +858,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs)
        /* If there's no signal to deliver, we just put the saved sigmask
         * back
         */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               set_current_blocked(&current->saved_sigmask);
-       }
+       restore_saved_sigmask();
 }
 
 struct sigstack32 {
index 6b42e8622d1280a98f4bf8daee177f8328920d55..68f9c8650af47b2731c622cc8ada8768b63d90cb 100644 (file)
@@ -29,8 +29,6 @@
 
 #include "sigutil.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 extern void fpsave(unsigned long *fpregs, unsigned long *fsr,
                   void *fpqueue, unsigned long *fpqdepth);
 extern void fpload(unsigned long *fpregs, unsigned long *fsr);
@@ -130,7 +128,6 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
        if (err)
                goto segv_and_exit;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        return;
 
@@ -197,7 +194,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
                        goto segv;
        }
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        return;
 segv:
@@ -449,10 +445,11 @@ sigsegv:
        return -EFAULT;
 }
 
-static inline int
+static inline void
 handle_signal(unsigned long signr, struct k_sigaction *ka,
-             siginfo_t *info, sigset_t *oldset, struct pt_regs *regs)
+             siginfo_t *info, struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int err;
 
        if (ka->sa.sa_flags & SA_SIGINFO)
@@ -461,12 +458,9 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
                err = setup_frame(ka, regs, signr, oldset);
 
        if (err)
-               return err;
-
-       block_sigmask(ka, signr);
-       tracehook_signal_handler(signr, info, ka, regs, 0);
+               return;
 
-       return 0;
+       signal_delivered(signr, info, ka, regs, 0);
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -498,7 +492,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 {
        struct k_sigaction ka;
        int restart_syscall;
-       sigset_t *oldset;
        siginfo_t info;
        int signr;
 
@@ -523,11 +516,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C))
                regs->u_regs[UREG_G6] = orig_i0;
 
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 
        /* If the debugger messes with the program counter, it clears
@@ -544,15 +532,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        if (signr > 0) {
                if (restart_syscall)
                        syscall_restart(orig_i0, regs, &ka.sa);
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
-                       /* a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag.
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
+               handle_signal(signr, &ka, &info, regs);
                return;
        }
        if (restart_syscall &&
@@ -576,16 +556,13 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        /* if there's no signal to deliver, we just put the saved sigmask
         * back
         */
-       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               set_current_blocked(&current->saved_sigmask);
-       }
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0,
                      unsigned long thread_info_flags)
 {
-       if (thread_info_flags & (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK))
+       if (thread_info_flags & _TIF_SIGPENDING)
                do_signal(regs, orig_i0);
        if (thread_info_flags & _TIF_NOTIFY_RESUME) {
                clear_thread_flag(TIF_NOTIFY_RESUME);
index c82cf1cc39652e719469a6f291bd74a2e6b8bb33..867de2f8189c32acf359fe5575cd139ede6b7048 100644 (file)
@@ -38,8 +38,6 @@
 #include "systbls.h"
 #include "sigutil.h"
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /* {set, get}context() needed for 64-bit SparcLinux userland. */
 asmlinkage void sparc64_set_context(struct pt_regs *regs)
 {
@@ -71,7 +69,6 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
                        if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t)))
                                goto do_sigsegv;
                }
-               sigdelsetmask(&set, ~_BLOCKABLE);
                set_current_blocked(&set);
        }
        if (test_thread_flag(TIF_32BIT)) {
@@ -315,7 +312,6 @@ void do_rt_sigreturn(struct pt_regs *regs)
        /* Prevent syscall restart.  */
        pt_regs_clear_syscall(regs);
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
        return;
 segv:
@@ -466,7 +462,7 @@ sigsegv:
        return -EFAULT;
 }
 
-static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
+static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
                                siginfo_t *info,
                                sigset_t *oldset, struct pt_regs *regs)
 {
@@ -475,12 +471,9 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka,
        err = setup_rt_frame(ka, regs, signr, oldset,
                             (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL);
        if (err)
-               return err;
-
-       block_sigmask(ka, signr);
-       tracehook_signal_handler(signr, info, ka, regs, 0);
+               return;
 
-       return 0;
+       signal_delivered(signr, info, ka, regs, 0);
 }
 
 static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
@@ -512,7 +505,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
 {
        struct k_sigaction ka;
        int restart_syscall;
-       sigset_t *oldset;
+       sigset_t *oldset = sigmask_to_save();
        siginfo_t info;
        int signr;
        
@@ -538,11 +531,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
            (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)))
                regs->u_regs[UREG_G6] = orig_i0;
 
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
 #ifdef CONFIG_COMPAT
        if (test_thread_flag(TIF_32BIT)) {
                extern void do_signal32(sigset_t *, struct pt_regs *);
@@ -563,14 +551,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        if (signr > 0) {
                if (restart_syscall)
                        syscall_restart(orig_i0, regs, &ka.sa);
-               if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
-                       /* A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TS_RESTORE_SIGMASK flag.
-                        */
-                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               }
+               handle_signal(signr, &ka, &info, oldset, regs);
                return;
        }
        if (restart_syscall &&
@@ -594,10 +575,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
        /* If there's no signal to deliver, we just put the saved sigmask
         * back
         */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               set_current_blocked(&current->saved_sigmask);
-       }
+       restore_saved_sigmask();
 }
 
 void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags)
index 656c486e64fafd424863fabe0f66d52a36e5c243..7e1fef36bde6651f2f199115919c887e494448f4 100644 (file)
@@ -166,7 +166,23 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->status |= TS_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, &ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
 }
 #endif /* !__ASSEMBLY__ */
 
index cdef6e5ec022cdbe6ab4c1c139f56dffc7fbcd8e..474571b8408584d37743678ce02b2ca77c3c9938 100644 (file)
@@ -118,8 +118,6 @@ struct compat_rt_sigframe {
        struct compat_ucontext uc;
 };
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
                             struct compat_sigaction __user *oact,
                             size_t sigsetsize)
@@ -302,7 +300,6 @@ long compat_sys_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
index f79d4b88c747ae97db505a7f54143e610e37e24d..e29b0553211d611af9802dfe190f9d0d9d868f69 100644 (file)
@@ -37,8 +37,6 @@
 
 #define DEBUG_SIG 0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 SYSCALL_DEFINE3(sigaltstack, const stack_t __user *, uss,
                stack_t __user *, uoss, struct pt_regs *, regs)
 {
@@ -96,7 +94,6 @@ SYSCALL_DEFINE1(rt_sigreturn, struct pt_regs *, regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
@@ -242,10 +239,11 @@ give_sigsegv:
  * OK, we're invoking a handler
  */
 
-static int handle_signal(unsigned long sig, siginfo_t *info,
-                        struct k_sigaction *ka, sigset_t *oldset,
+static void handle_signal(unsigned long sig, siginfo_t *info,
+                        struct k_sigaction *ka,
                         struct pt_regs *regs)
 {
+       sigset_t *oldset = sigmask_to_save();
        int ret;
 
        /* Are we from a system call? */
@@ -278,15 +276,9 @@ static int handle_signal(unsigned long sig, siginfo_t *info,
        else
 #endif
                ret = setup_rt_frame(sig, ka, info, oldset, regs);
-       if (ret == 0) {
-               /* This code is only called from system calls or from
-                * the work_pending path in the return-to-user code, and
-                * either way we can re-enable interrupts unconditionally.
-                */
-               block_sigmask(ka, sig);
-       }
-
-       return ret;
+       if (ret)
+               return;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -299,7 +291,6 @@ void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t *oldset;
 
        /*
         * i386 will check if we're coming from kernel mode and bail out
@@ -308,24 +299,10 @@ void do_signal(struct pt_regs *regs)
         * helpful, we can reinstate the check on "!user_mode(regs)".
         */
 
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee! Actually deliver the signal.  */
-               if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TS_RESTORE_SIGMASK flag.
-                        */
-                       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               }
-
+               handle_signal(signr, &info, &ka, regs);
                goto done;
        }
 
@@ -350,10 +327,7 @@ void do_signal(struct pt_regs *regs)
        }
 
        /* If there's no signal to deliver, just put the saved sigmask back. */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       restore_saved_sigmask();
 
 done:
        /* Avoid double syscall restart if there are nested signals. */
index 76078490c2581c92a2c40cc039419e918f8b6f9d..e584e40ee8320f62e82e67abe6230a40ac75b19d 100644 (file)
@@ -6,9 +6,6 @@
 #ifndef __FRAME_KERN_H_
 #define __FRAME_KERN_H_
 
-#define _S(nr) (1<<((nr)-1))
-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-
 extern int setup_signal_stack_sc(unsigned long stack_top, int sig, 
                                 struct k_sigaction *ka,
                                 struct pt_regs *regs, 
index 292e706016c521842b3654ea0e1de2619211dc60..7362d58efc29612c1ffaad64558b3a986b820515 100644 (file)
 EXPORT_SYMBOL(block_signals);
 EXPORT_SYMBOL(unblock_signals);
 
-#define _S(nr) (1<<((nr)-1))
-
-#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP)))
-
 /*
  * OK, we're invoking a handler
  */
-static int handle_signal(struct pt_regs *regs, unsigned long signr,
-                        struct k_sigaction *ka, siginfo_t *info,
-                        sigset_t *oldset)
+static void handle_signal(struct pt_regs *regs, unsigned long signr,
+                        struct k_sigaction *ka, siginfo_t *info)
 {
+       sigset_t *oldset = sigmask_to_save();
        unsigned long sp;
        int err;
 
@@ -65,9 +61,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr,
        if (err)
                force_sigsegv(signr, current);
        else
-               block_sigmask(ka, signr);
-
-       return err;
+               signal_delivered(signr, info, ka, regs, 0);
 }
 
 static int kern_do_signal(struct pt_regs *regs)
@@ -77,24 +71,9 @@ static int kern_do_signal(struct pt_regs *regs)
        int sig, handled_sig = 0;
 
        while ((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0) {
-               sigset_t *oldset;
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       oldset = &current->saved_sigmask;
-               else
-                       oldset = &current->blocked;
                handled_sig = 1;
                /* Whee!  Actually deliver the signal.  */
-               if (!handle_signal(regs, sig, &ka_copy, &info, oldset)) {
-                       /*
-                        * a signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-                       break;
-               }
+               handle_signal(regs, sig, &ka_copy, &info);
        }
 
        /* Did we come from a system call? */
@@ -130,10 +109,8 @@ static int kern_do_signal(struct pt_regs *regs)
         * if there's no signal to deliver, we just put the saved sigmask
         * back
         */
-       if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) {
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-       }
+       if (!handled_sig)
+               restore_saved_sigmask();
        return handled_sig;
 }
 
index 28782ad47b93ee5d778cfa225776f87cebbb5719..8adedb37720a0e997dea9ea88abff76113904830 100644 (file)
@@ -21,8 +21,6 @@
 #include <asm/cacheflush.h>
 #include <asm/ucontext.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 /*
  * For UniCore syscalls, we encode the syscall number into the instruction.
  */
@@ -61,10 +59,8 @@ static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
        int err;
 
        err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
-       if (err == 0) {
-               sigdelsetmask(&set, ~_BLOCKABLE);
+       if (err == 0)
                set_current_blocked(&set);
-       }
 
        err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
        err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
@@ -312,13 +308,12 @@ static inline void setup_syscall_restart(struct pt_regs *regs)
 /*
  * OK, we're invoking a handler
  */
-static int handle_signal(unsigned long sig, struct k_sigaction *ka,
-             siginfo_t *info, sigset_t *oldset,
-             struct pt_regs *regs, int syscall)
+static void handle_signal(unsigned long sig, struct k_sigaction *ka,
+             siginfo_t *info, struct pt_regs *regs, int syscall)
 {
        struct thread_info *thread = current_thread_info();
        struct task_struct *tsk = current;
-       sigset_t blocked;
+       sigset_t *oldset = sigmask_to_save();
        int usig = sig;
        int ret;
 
@@ -364,15 +359,10 @@ static int handle_signal(unsigned long sig, struct k_sigaction *ka,
 
        if (ret != 0) {
                force_sigsegv(sig, tsk);
-               return ret;
+               return;
        }
 
-       /*
-        * Block the signal if we were successful.
-        */
-       block_sigmask(ka, sig);
-
-       return 0;
+       signal_delivered(sig, info, ka, regs, 0);
 }
 
 /*
@@ -399,32 +389,12 @@ static void do_signal(struct pt_regs *regs, int syscall)
        if (!user_mode(regs))
                return;
 
-       if (try_to_freeze())
-               goto no_signal;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
-               sigset_t *oldset;
-
-               if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                       oldset = &current->saved_sigmask;
-               else
-                       oldset = &current->blocked;
-               if (handle_signal(signr, &ka, &info, oldset, regs, syscall)
-                               == 0) {
-                       /*
-                        * A signal was successfully delivered; the saved
-                        * sigmask will have been stored in the signal frame,
-                        * and will be restored by sigreturn, so we can simply
-                        * clear the TIF_RESTORE_SIGMASK flag.
-                        */
-                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-                               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               }
+               handle_signal(signr, &ka, &info, regs, syscall);
                return;
        }
 
- no_signal:
        /*
         * No signal to deliver to the process - restart the syscall.
         */
@@ -451,8 +421,7 @@ static void do_signal(struct pt_regs *regs, int syscall)
        /* If there's no signal to deliver, we just put the saved
         * sigmask back.
         */
-       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
-               set_current_blocked(&current->saved_sigmask);
+       restore_saved_sigmask();
 }
 
 asmlinkage void do_notify_resume(struct pt_regs *regs,
index 98bd70faccc50cb0bb07ad96066a74a990870239..daeca56211e39b13babd4504cb19e9797f6e7810 100644 (file)
@@ -273,7 +273,6 @@ asmlinkage long sys32_sigreturn(struct pt_regs *regs)
                                    sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (ia32_restore_sigcontext(regs, &frame->sc, &ax))
@@ -299,7 +298,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
index ada93b3b8c66fb79f5e3a9fe91d9f15d67234edf..beff97f7df3790d04dfba1906fe657b1d024e579 100644 (file)
@@ -7,8 +7,6 @@
 
 #include <asm/processor-flags.h>
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 #define __FIX_EFLAGS   (X86_EFLAGS_AC | X86_EFLAGS_OF | \
                         X86_EFLAGS_DF | X86_EFLAGS_TF | X86_EFLAGS_SF | \
                         X86_EFLAGS_ZF | X86_EFLAGS_AF | X86_EFLAGS_PF | \
index 5c25de07cba82fca1fbd027a3038f5f6cedf66ec..89f794f007ec1e4aa5bbd029bcb32182fffe1f48 100644 (file)
@@ -248,7 +248,23 @@ static inline void set_restore_sigmask(void)
 {
        struct thread_info *ti = current_thread_info();
        ti->status |= TS_RESTORE_SIGMASK;
-       set_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags);
+       WARN_ON(!test_bit(TIF_SIGPENDING, (unsigned long *)&ti->flags));
+}
+static inline void clear_restore_sigmask(void)
+{
+       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
+}
+static inline bool test_restore_sigmask(void)
+{
+       return current_thread_info()->status & TS_RESTORE_SIGMASK;
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       struct thread_info *ti = current_thread_info();
+       if (!(ti->status & TS_RESTORE_SIGMASK))
+               return false;
+       ti->status &= ~TS_RESTORE_SIGMASK;
+       return true;
 }
 
 static inline bool is_ia32_task(void)
index 01ccf9b71473ce18ffe0cccf5fa09fd379dcf4cf..623f288374763286ec9e58aa66ecabb4e3fc2f6b 100644 (file)
@@ -316,7 +316,6 @@ ret_from_exception:
        preempt_stop(CLBR_ANY)
 ret_from_intr:
        GET_THREAD_INFO(%ebp)
-resume_userspace_sig:
 #ifdef CONFIG_VM86
        movl PT_EFLAGS(%esp), %eax      # mix EFLAGS and CS
        movb PT_CS(%esp), %al
@@ -615,9 +614,13 @@ work_notifysig:                            # deal with pending signals and
                                        # vm86-space
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
+       movb PT_CS(%esp), %bl
+       andb $SEGMENT_RPL_MASK, %bl
+       cmpb $USER_RPL, %bl
+       jb resume_kernel
        xorl %edx, %edx
        call do_notify_resume
-       jmp resume_userspace_sig
+       jmp resume_userspace
 
        ALIGN
 work_notifysig_v86:
@@ -630,9 +633,13 @@ work_notifysig_v86:
 #endif
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
+       movb PT_CS(%esp), %bl
+       andb $SEGMENT_RPL_MASK, %bl
+       cmpb $USER_RPL, %bl
+       jb resume_kernel
        xorl %edx, %edx
        call do_notify_resume
-       jmp resume_userspace_sig
+       jmp resume_userspace
 END(work_pending)
 
        # perform syscall exit tracing
index 2e937a5ad53154b4ff3a047e181894ec1a44633e..21af737053aad05fb726a0e1023dfad428064518 100644 (file)
@@ -555,7 +555,6 @@ unsigned long sys_sigreturn(struct pt_regs *regs)
                                    sizeof(frame->extramask))))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->sc, &ax))
@@ -581,7 +580,6 @@ long sys_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
@@ -647,42 +645,28 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                struct pt_regs *regs)
 {
        int usig = signr_convert(sig);
-       sigset_t *set = &current->blocked;
-       int ret;
-
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK)
-               set = &current->saved_sigmask;
+       sigset_t *set = sigmask_to_save();
 
        /* Set up the stack frame */
        if (is_ia32) {
                if (ka->sa.sa_flags & SA_SIGINFO)
-                       ret = ia32_setup_rt_frame(usig, ka, info, set, regs);
+                       return ia32_setup_rt_frame(usig, ka, info, set, regs);
                else
-                       ret = ia32_setup_frame(usig, ka, set, regs);
+                       return ia32_setup_frame(usig, ka, set, regs);
 #ifdef CONFIG_X86_X32_ABI
        } else if (is_x32) {
-               ret = x32_setup_rt_frame(usig, ka, info,
+               return x32_setup_rt_frame(usig, ka, info,
                                         (compat_sigset_t *)set, regs);
 #endif
        } else {
-               ret = __setup_rt_frame(sig, ka, info, set, regs);
-       }
-
-       if (ret) {
-               force_sigsegv(sig, current);
-               return -EFAULT;
+               return __setup_rt_frame(sig, ka, info, set, regs);
        }
-
-       current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-       return ret;
 }
 
-static int
+static void
 handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
                struct pt_regs *regs)
 {
-       int ret;
-
        /* Are we from a system call? */
        if (syscall_get_nr(current, regs) >= 0) {
                /* If so, check system call restarting.. */
@@ -713,10 +697,10 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
            likely(test_and_clear_thread_flag(TIF_FORCED_TF)))
                regs->flags &= ~X86_EFLAGS_TF;
 
-       ret = setup_rt_frame(sig, ka, info, regs);
-
-       if (ret)
-               return ret;
+       if (setup_rt_frame(sig, ka, info, regs) < 0) {
+               force_sigsegv(sig, current);
+               return;
+       }
 
        /*
         * Clear the direction flag as per the ABI for function entry.
@@ -731,12 +715,8 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
         */
        regs->flags &= ~X86_EFLAGS_TF;
 
-       block_sigmask(ka, sig);
-
-       tracehook_signal_handler(sig, info, ka, regs,
-                                test_thread_flag(TIF_SINGLESTEP));
-
-       return 0;
+       signal_delivered(sig, info, ka, regs,
+                        test_thread_flag(TIF_SINGLESTEP));
 }
 
 #ifdef CONFIG_X86_32
@@ -757,16 +737,6 @@ static void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
 
-       /*
-        * We want the common case to go fast, which is why we may in certain
-        * cases get here from kernel mode. Just return without doing anything
-        * if so.
-        * X86_32: vm86 regs switched out by assembly code before reaching
-        * here, so testing against kernel CS suffices.
-        */
-       if (!user_mode(regs))
-               return;
-
        signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee! Actually deliver the signal.  */
@@ -796,10 +766,7 @@ static void do_signal(struct pt_regs *regs)
         * If there's no signal to deliver, we just put the saved sigmask
         * back.
         */
-       if (current_thread_info()->status & TS_RESTORE_SIGMASK) {
-               current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
-               set_current_blocked(&current->saved_sigmask);
-       }
+       restore_saved_sigmask();
 }
 
 /*
@@ -934,7 +901,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
index bb0fb03b9f85f268912e7b6851f74787c8ee8e4a..a508cea135033eba3c1c7facba8aebd04a1a0983 100644 (file)
@@ -486,7 +486,6 @@ long sys_sigreturn(struct pt_regs *regs)
            copy_from_user(&set.sig[1], extramask, sig_size))
                goto segfault;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (copy_sc_from_user(&current->thread.regs, sc))
@@ -600,7 +599,6 @@ long sys_rt_sigreturn(struct pt_regs *regs)
        if (copy_from_user(&set, &uc->uc_sigmask, sizeof(set)))
                goto segfault;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (copy_sc_from_user(&current->thread.regs, &uc->uc_mcontext))
index ea7e17778a75546d251b040e30819d26f8acbac3..b9f8e5850d3a4e1c9bc1dbe3ff6ee0b7dbc47cc9 100644 (file)
@@ -30,8 +30,6 @@
 
 #define DEBUG_SIG  0
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
 extern struct task_struct *coproc_owners[];
 
 struct rt_sigframe
@@ -261,7 +259,6 @@ asmlinkage long xtensa_rt_sigreturn(long a0, long a1, long a2, long a3,
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
 
-       sigdelsetmask(&set, ~_BLOCKABLE);
        set_current_blocked(&set);
 
        if (restore_sigcontext(regs, frame))
@@ -452,15 +449,6 @@ static void do_signal(struct pt_regs *regs)
        siginfo_t info;
        int signr;
        struct k_sigaction ka;
-       sigset_t oldset;
-
-       if (try_to_freeze())
-               goto no_signal;
-
-       if (test_thread_flag(TIF_RESTORE_SIGMASK))
-               oldset = &current->saved_sigmask;
-       else
-               oldset = &current->blocked;
 
        task_pt_regs(current)->icountlevel = 0;
 
@@ -501,19 +489,17 @@ static void do_signal(struct pt_regs *regs)
 
                /* Whee!  Actually deliver the signal.  */
                /* Set up the stack frame */
-               ret = setup_frame(signr, &ka, &info, oldset, regs);
+               ret = setup_frame(signr, &ka, &info, sigmask_to_save(), regs);
                if (ret)
                        return;
 
-               clear_thread_flag(TIF_RESTORE_SIGMASK);
-               block_sigmask(&ka, signr);
+               signal_delivered(signr, info, ka, regs, 0);
                if (current->ptrace & PT_SINGLESTEP)
                        task_pt_regs(current)->icountlevel = 1;
 
                return;
        }
 
-no_signal:
        /* Did we come from a system call? */
        if ((signed) regs->syscall >= 0) {
                /* Restart the system call - no handlers present */
@@ -532,8 +518,7 @@ no_signal:
        }
 
        /* If there's no signal to deliver, we just restore the saved mask.  */
-       if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK))
-               set_current_blocked(&current->saved_sigmask);
+       restore_saved_sigmask();
 
        if (current->ptrace & PT_SINGLESTEP)
                task_pt_regs(current)->icountlevel = 1;
index 3004d2bad13f037682becb107ab24a21e61a5e7d..6161255fac45648efdfe437d9d880d390268d14f 100644 (file)
@@ -1542,7 +1542,6 @@ asmlinkage long compat_sys_old_select(struct compat_sel_arg_struct __user *arg)
                                 compat_ptr(a.exp), compat_ptr(a.tvp));
 }
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
 static long do_compat_pselect(int n, compat_ulong_t __user *inp,
        compat_ulong_t __user *outp, compat_ulong_t __user *exp,
        struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask,
@@ -1665,11 +1664,9 @@ asmlinkage long compat_sys_ppoll(struct pollfd __user *ufds,
 
        return ret;
 }
-#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 #ifdef CONFIG_EPOLL
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
 asmlinkage long compat_sys_epoll_pwait(int epfd,
                        struct compat_epoll_event __user *events,
                        int maxevents, int timeout,
@@ -1713,7 +1710,6 @@ asmlinkage long compat_sys_epoll_pwait(int epfd,
 
        return err;
 }
-#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 #endif /* CONFIG_EPOLL */
 
index 079d1be65ba9e61e6f0452ecffc0cd23a6c3987d..74598f67efebb85e71204a832c929dd20ea96771 100644 (file)
@@ -1853,8 +1853,6 @@ error_return:
        return error;
 }
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
-
 /*
  * Implement the event wait interface for the eventpoll file. It is the kernel
  * part of the user space epoll_pwait(2).
@@ -1899,8 +1897,6 @@ SYSCALL_DEFINE6(epoll_pwait, int, epfd, struct epoll_event __user *, events,
        return error;
 }
 
-#endif /* HAVE_SET_RESTORE_SIGMASK */
-
 static int __init eventpoll_init(void)
 {
        struct sysinfo si;
index 17d33d09fc16f4843c72f9c7444dfdb3fb738952..bae321569dfa7283b290a2e2d65c99bb10b622f4 100644 (file)
@@ -614,7 +614,6 @@ SYSCALL_DEFINE5(select, int, n, fd_set __user *, inp, fd_set __user *, outp,
        return ret;
 }
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
 static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
                       fd_set __user *exp, struct timespec __user *tsp,
                       const sigset_t __user *sigmask, size_t sigsetsize)
@@ -686,7 +685,6 @@ SYSCALL_DEFINE6(pselect6, int, n, fd_set __user *, inp, fd_set __user *, outp,
 
        return do_pselect(n, inp, outp, exp, tsp, up, sigsetsize);
 }
-#endif /* HAVE_SET_RESTORE_SIGMASK */
 
 #ifdef __ARCH_WANT_SYS_OLD_SELECT
 struct sel_arg_struct {
@@ -941,7 +939,6 @@ SYSCALL_DEFINE3(poll, struct pollfd __user *, ufds, unsigned int, nfds,
        return ret;
 }
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
 SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
                struct timespec __user *, tsp, const sigset_t __user *, sigmask,
                size_t, sigsetsize)
@@ -992,4 +989,3 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
 
        return ret;
 }
-#endif /* HAVE_SET_RESTORE_SIGMASK */
index 660c8ae93471cfb1a150936fda19e8f5a0945ef8..f34437e835a7069dfdc4660dbed593ebb371d0e9 100644 (file)
@@ -2207,6 +2207,20 @@ extern int send_sigqueue(struct sigqueue *,  struct task_struct *, int group);
 extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *);
 extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long);
 
+static inline void restore_saved_sigmask(void)
+{
+       if (test_and_clear_restore_sigmask())
+               __set_current_blocked(&current->saved_sigmask);
+}
+
+static inline sigset_t *sigmask_to_save(void)
+{
+       sigset_t *res = &current->blocked;
+       if (unlikely(test_restore_sigmask()))
+               res = &current->saved_sigmask;
+       return res;
+}
+
 static inline int kill_cad_pid(int sig, int priv)
 {
        return kill_pid(cad_pid, sig, priv);
index 17046cc484bced6426c36b81f43ce43fdf0ffde4..26b424adc84299b6a53c9ad986e4d9350d16b68a 100644 (file)
@@ -250,12 +250,13 @@ extern long do_sigpending(void __user *, unsigned long);
 extern int do_sigtimedwait(const sigset_t *, siginfo_t *,
                                const struct timespec *);
 extern int sigprocmask(int, sigset_t *, sigset_t *);
-extern void set_current_blocked(const sigset_t *);
+extern void set_current_blocked(sigset_t *);
+extern void __set_current_blocked(const sigset_t *);
 extern int show_unhandled_signals;
 extern int sigsuspend(sigset_t *);
 
 extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
-extern void block_sigmask(struct k_sigaction *ka, int signr);
+extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping);
 extern void exit_signals(struct task_struct *tsk);
 
 extern struct kmem_cache *sighand_cachep;
index db78775eff3b209b534d157d4cec7d90eec8b175..ccc1899bd62e991e4649b72e7145010f93f948f9 100644 (file)
@@ -8,6 +8,7 @@
 #define _LINUX_THREAD_INFO_H
 
 #include <linux/types.h>
+#include <linux/bug.h>
 
 struct timespec;
 struct compat_timespec;
@@ -125,10 +126,26 @@ static inline int test_ti_thread_flag(struct thread_info *ti, int flag)
 static inline void set_restore_sigmask(void)
 {
        set_thread_flag(TIF_RESTORE_SIGMASK);
-       set_thread_flag(TIF_SIGPENDING);
+       WARN_ON(!test_thread_flag(TIF_SIGPENDING));
+}
+static inline void clear_restore_sigmask(void)
+{
+       clear_thread_flag(TIF_RESTORE_SIGMASK);
+}
+static inline bool test_restore_sigmask(void)
+{
+       return test_thread_flag(TIF_RESTORE_SIGMASK);
+}
+static inline bool test_and_clear_restore_sigmask(void)
+{
+       return test_and_clear_thread_flag(TIF_RESTORE_SIGMASK);
 }
 #endif /* TIF_RESTORE_SIGMASK && !HAVE_SET_RESTORE_SIGMASK */
 
+#ifndef HAVE_SET_RESTORE_SIGMASK
+#error "no set_restore_sigmask() provided and default one won't work"
+#endif
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_THREAD_INFO_H */
index 08dfbd748cd2daf9175d22fe085cf5eb7efe689c..677102789cf22d4847936782f6c6f67085421927 100644 (file)
@@ -2368,24 +2368,34 @@ relock:
 }
 
 /**
- * block_sigmask - add @ka's signal mask to current->blocked
- * @ka: action for @signr
- * @signr: signal that has been successfully delivered
+ * signal_delivered - 
+ * @sig:               number of signal being delivered
+ * @info:              siginfo_t of signal being delivered
+ * @ka:                        sigaction setting that chose the handler
+ * @regs:              user register state
+ * @stepping:          nonzero if debugger single-step or block-step in use
  *
  * This function should be called when a signal has succesfully been
- * delivered. It adds the mask of signals for @ka to current->blocked
- * so that they are blocked during the execution of the signal
- * handler. In addition, @signr will be blocked unless %SA_NODEFER is
- * set in @ka->sa.sa_flags.
+ * delivered. It updates the blocked signals accordingly (@ka->sa.sa_mask
+ * is always blocked, and the signal itself is blocked unless %SA_NODEFER
+ * is set in @ka->sa.sa_flags.  Tracing is notified.
  */
-void block_sigmask(struct k_sigaction *ka, int signr)
+void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka,
+                       struct pt_regs *regs, int stepping)
 {
        sigset_t blocked;
 
+       /* A signal was successfully delivered, and the
+          saved sigmask was stored on the signal frame,
+          and will be restored by sigreturn.  So we can
+          simply clear the restore sigmask flag.  */
+       clear_restore_sigmask();
+
        sigorsets(&blocked, &current->blocked, &ka->sa.sa_mask);
        if (!(ka->sa.sa_flags & SA_NODEFER))
-               sigaddset(&blocked, signr);
+               sigaddset(&blocked, sig);
        set_current_blocked(&blocked);
+       tracehook_signal_handler(sig, info, ka, regs, stepping);
 }
 
 /*
@@ -2518,7 +2528,16 @@ static void __set_task_blocked(struct task_struct *tsk, const sigset_t *newset)
  * It is wrong to change ->blocked directly, this helper should be used
  * to ensure the process can't miss a shared signal we are going to block.
  */
-void set_current_blocked(const sigset_t *newset)
+void set_current_blocked(sigset_t *newset)
+{
+       struct task_struct *tsk = current;
+       sigdelsetmask(newset, sigmask(SIGKILL) | sigmask(SIGSTOP));
+       spin_lock_irq(&tsk->sighand->siglock);
+       __set_task_blocked(tsk, newset);
+       spin_unlock_irq(&tsk->sighand->siglock);
+}
+
+void __set_current_blocked(const sigset_t *newset)
 {
        struct task_struct *tsk = current;
 
@@ -2558,7 +2577,7 @@ int sigprocmask(int how, sigset_t *set, sigset_t *oldset)
                return -EINVAL;
        }
 
-       set_current_blocked(&newset);
+       __set_current_blocked(&newset);
        return 0;
 }
 
@@ -3132,7 +3151,7 @@ SYSCALL_DEFINE3(sigprocmask, int, how, old_sigset_t __user *, nset,
                        return -EINVAL;
                }
 
-               set_current_blocked(&new_blocked);
+               __set_current_blocked(&new_blocked);
        }
 
        if (oset) {
@@ -3196,7 +3215,6 @@ SYSCALL_DEFINE1(ssetmask, int, newmask)
        int old = current->blocked.sig[0];
        sigset_t newset;
 
-       siginitset(&newset, newmask & ~(sigmask(SIGKILL) | sigmask(SIGSTOP)));
        set_current_blocked(&newset);
 
        return old;
@@ -3235,11 +3253,8 @@ SYSCALL_DEFINE0(pause)
 
 #endif
 
-#ifdef HAVE_SET_RESTORE_SIGMASK
 int sigsuspend(sigset_t *set)
 {
-       sigdelsetmask(set, sigmask(SIGKILL)|sigmask(SIGSTOP));
-
        current->saved_sigmask = current->blocked;
        set_current_blocked(set);
 
@@ -3248,7 +3263,6 @@ int sigsuspend(sigset_t *set)
        set_restore_sigmask();
        return -ERESTARTNOHAND;
 }
-#endif
 
 #ifdef __ARCH_WANT_SYS_RT_SIGSUSPEND
 /**