[PARISC] Add TIF_RESTORE_SIGMASK support
authorKyle McMartin <kyle@parisc-linux.org>
Mon, 8 Jan 2007 21:28:06 +0000 (16:28 -0500)
committerKyle McMartin <kyle@athena.road.mcmartin.ca>
Sat, 17 Feb 2007 06:06:04 +0000 (01:06 -0500)
And unmask the pselect6/ppoll system calls.

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>
arch/parisc/kernel/entry.S
arch/parisc/kernel/signal.c
arch/parisc/kernel/syscall_table.S
include/asm-parisc/thread_info.h
include/asm-parisc/unistd.h

index 39a12c1fc6f591466f9a888b34e710102e2c40ca..f965673e68631ddd9524683a4c677ffb0eba2b5c 100644 (file)
@@ -978,11 +978,39 @@ intr_check_resched:
        LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_NEED_RESCHED */
        bb,<,n  %r19,31-TIF_NEED_RESCHED,intr_do_resched /* forward */
 
+       .import do_notify_resume,code
 intr_check_sig:
        /* As above */
        mfctl   %cr30,%r1
-       LDREG   TI_FLAGS(%r1),%r19      /* sched.h: TIF_SIGPENDING */
-       bb,<,n %r19, 31-TIF_SIGPENDING, intr_do_signal /* forward */
+       LDREG   TI_FLAGS(%r1),%r19
+       load32  (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r20
+       and,COND(<>)    %r19, %r20, %r0
+       b,n     intr_restore    /* skip past if we've nothing to do */
+
+       /* This check is critical to having LWS
+        * working. The IASQ is zero on the gateway
+        * page and we cannot deliver any signals until
+        * we get off the gateway page.
+        *
+        * Only do signals if we are returning to user space
+        */
+       LDREG   PT_IASQ0(%r16), %r20
+       CMPIB= 0,%r20,intr_restore /* backward */
+       nop
+       LDREG   PT_IASQ1(%r16), %r20
+       CMPIB= 0,%r20,intr_restore /* backward */
+       nop
+
+       copy    %r0, %r25                       /* long in_syscall = 0 */
+#ifdef CONFIG_64BIT
+       ldo     -16(%r30),%r29                  /* Reference param save area */
+#endif
+
+       BL      do_notify_resume,%r2
+       copy    %r16, %r26                      /* struct pt_regs *regs */
+
+       b       intr_check_sig
+       nop
 
 intr_restore:
        copy            %r16,%r29
@@ -1072,35 +1100,6 @@ intr_do_preempt:
        b,n     intr_restore            /* ssm PSW_SM_I done by intr_restore */
 #endif /* CONFIG_PREEMPT */
 
-       .import do_signal,code
-intr_do_signal:
-       /* 
-               This check is critical to having LWS
-               working. The IASQ is zero on the gateway
-               page and we cannot deliver any signals until
-               we get off the gateway page.
-
-               Only do signals if we are returning to user space 
-       */
-       LDREG   PT_IASQ0(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
-       nop
-       LDREG   PT_IASQ1(%r16), %r20
-       CMPIB= 0,%r20,intr_restore /* backward */
-       nop
-
-       copy    %r0, %r24                       /* unsigned long in_syscall */
-       copy    %r16, %r25                      /* struct pt_regs *regs */
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29                  /* Reference param save area */
-#endif
-
-       BL      do_signal,%r2
-       copy    %r0, %r26                       /* sigset_t *oldset = NULL */
-
-       b       intr_check_sig
-       nop
-
        /*
         * External interrupts.
         */
@@ -2024,32 +2023,6 @@ sys32_sigaltstack_wrapper:
        nop
 #endif
 
-       .export sys_rt_sigsuspend_wrapper
-sys_rt_sigsuspend_wrapper:
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
-       ldo     TASK_REGS(%r1),%r24
-       reg_save %r24
-
-       STREG   %r2, -RP_OFFSET(%r30)
-#ifdef CONFIG_64BIT
-       ldo     FRAME_SIZE(%r30), %r30
-       BL      sys_rt_sigsuspend,%r2
-       ldo     -16(%r30),%r29          /* Reference param save area */
-#else
-       BL      sys_rt_sigsuspend,%r2
-       ldo     FRAME_SIZE(%r30), %r30
-#endif
-
-       ldo     -FRAME_SIZE(%r30), %r30
-       LDREG   -RP_OFFSET(%r30), %r2
-
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1
-       ldo     TASK_REGS(%r1),%r1
-       reg_restore %r1
-
-       bv      %r0(%r2)
-       nop
-
        .export syscall_exit
 syscall_exit:
 
@@ -2115,9 +2088,35 @@ syscall_check_resched:
        LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19   /* long */
        bb,<,n  %r19, 31-TIF_NEED_RESCHED, syscall_do_resched /* forward */
 
+       .import do_signal,code
 syscall_check_sig:
-       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19    /* get ti flags */
-       bb,<,n  %r19, 31-TIF_SIGPENDING, syscall_do_signal /* forward */
+       LDREG   TI_FLAGS-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r19
+       load32  (_TIF_SIGPENDING|_TIF_RESTORE_SIGMASK), %r26
+       and,COND(<>)    %r19, %r26, %r0
+       b,n     syscall_restore /* skip past if we've nothing to do */
+
+syscall_do_signal:
+       /* Save callee-save registers (for sigcontext).
+        * FIXME: After this point the process structure should be
+        * consistent with all the relevant state of the process
+        * before the syscall.  We need to verify this.
+        */
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+       ldo     TASK_REGS(%r1), %r26            /* struct pt_regs *regs */
+       reg_save %r26
+
+#ifdef CONFIG_64BIT
+       ldo     -16(%r30),%r29                  /* Reference param save area */
+#endif
+
+       BL      do_notify_resume,%r2
+       ldi     1, %r25                         /* long in_syscall = 1 */
+
+       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
+       ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
+       reg_restore %r20
+
+       b,n     syscall_check_sig
 
 syscall_restore:
        /* Are we being ptraced? */
@@ -2256,30 +2255,6 @@ syscall_do_resched:
        b       syscall_check_bh  /* if resched, we start over again */
        nop
 
-       .import do_signal,code
-syscall_do_signal:
-       /* Save callee-save registers (for sigcontext).
-          FIXME: After this point the process structure should be
-          consistent with all the relevant state of the process
-          before the syscall.  We need to verify this. */
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1 
-       ldo     TASK_REGS(%r1), %r25            /* struct pt_regs *regs */
-       reg_save %r25
-
-       ldi     1, %r24                         /* unsigned long in_syscall */
-
-#ifdef CONFIG_64BIT
-       ldo     -16(%r30),%r29                  /* Reference param save area */
-#endif
-       BL      do_signal,%r2
-       copy    %r0, %r26                       /* sigset_t *oldset = NULL */
-
-       LDREG   TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r1
-       ldo     TASK_REGS(%r1), %r20            /* reload pt_regs */
-       reg_restore %r20
-
-       b,n     syscall_check_sig
-
        /*
         * get_register is used by the non access tlb miss handlers to
         * copy the value of the general register specified in r8 into
index ee6653edeb7a1b83da64572c03d9d0620319558f..8d781b0e668b3fd41cdb59c0ef336d512bba4d6b 100644 (file)
@@ -59,8 +59,6 @@
  * this. */
 #define A(__x) ((unsigned long)(__x))
 
-int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
-
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -68,49 +66,6 @@ int do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall);
 #include "sys32.h"
 #endif
 
-asmlinkage int
-sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize, struct pt_regs *regs)
-{
-       sigset_t saveset, newset;
-#ifdef __LP64__
-       compat_sigset_t newset32;
-
-       if (is_compat_task()) {
-               /* XXX: Don't preclude handling different sized sigset_t's.  */
-               if (sigsetsize != sizeof(compat_sigset_t))
-                       return -EINVAL;
-               if (copy_from_user(&newset32, (compat_sigset_t __user *)unewset, sizeof(newset32)))
-                       return -EFAULT;
-               sigset_32to64(&newset,&newset32);
-               
-       } else 
-#endif
-       {
-               /* XXX: Don't preclude handling different sized sigset_t's.  */
-               if (sigsetsize != sizeof(sigset_t))
-                       return -EINVAL;
-       
-               if (copy_from_user(&newset, unewset, sizeof(newset)))
-                       return -EFAULT;
-       }
-
-       sigdelsetmask(&newset, ~_BLOCKABLE);
-
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       current->blocked = newset;
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-
-       regs->gr[28] = -EINTR;
-       while (1) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule();
-               if (do_signal(&saveset, regs, 1))
-                       return -EINTR;
-       }
-}
-
 /*
  * Do a signal return - restore sigcontext.
  */
@@ -528,12 +483,13 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
  * us due to the magic of delayed branching.
  */
 
-asmlinkage int
-do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
+asmlinkage void
+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);
@@ -543,7 +499,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
           we would be called in that case, but for some reason we
           are. */
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else
                oldset = &current->blocked;
 
        DBG(1,"do_signal: oldset %08lx / %08lx\n", 
@@ -592,7 +550,9 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
                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]);
-                       return 1;
+                       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                               clear_thread_flag(TIF_RESTORE_SIGMASK);
+                       return;
                }
        }
        /* end of while(1) looping forever if we can't force a signal */
@@ -653,5 +613,17 @@ do_signal(sigset_t *oldset, struct pt_regs *regs, int in_syscall)
        DBG(1,"do_signal: Exit (not delivered), regs->gr[28] = %ld\n", 
                regs->gr[28]);
 
-       return 0;
+       if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+               clear_thread_flag(TIF_RESTORE_SIGMASK);
+               sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+       }
+
+       return;
+}
+
+void do_notify_resume(struct pt_regs *regs, long in_syscall)
+{
+       if (test_thread_flag(TIF_SIGPENDING) ||
+           test_thread_flag(TIF_RESTORE_SIGMASK))
+               do_signal(regs, in_syscall);
 }
index 15d9c635d6a66ccc4a8921c3327d6837d8acb75c..7f037b72ad038b2d76c7b1cfcc570a2014ded783 100644 (file)
         * struct from a 32-bit user-space app.
         */
        ENTRY_SAME(rt_sigqueueinfo)
-       ENTRY_SAME(rt_sigsuspend_wrapper) /* not really SAME -- see the code */
+       ENTRY_COMP(rt_sigsuspend)
        ENTRY_SAME(chown)               /* 180 */
        /* setsockopt() used by iptables: SO_SET_REPLACE/SO_SET_ADD_COUNTERS */
        ENTRY_COMP(setsockopt)
        ENTRY_SAME(inotify_init)
        ENTRY_SAME(inotify_add_watch)   /* 270 */
        ENTRY_SAME(inotify_rm_watch)
-       ENTRY_SAME(ni_syscall)          /* 271 ENTRY_COMP(pselect6) */
-       ENTRY_SAME(ni_syscall)          /* 272 ENTRY_COMP(ppoll) */
+       ENTRY_COMP(pselect6)
+       ENTRY_COMP(ppoll)
        ENTRY_SAME(migrate_pages)
        ENTRY_COMP(openat)              /* 275 */
        ENTRY_SAME(mkdirat)
index f2f83b04cd8b8fad0c1bc5c19fa3b839d5cc1704..949314cf6188998dae95213b930e79a7edbb4c7b 100644 (file)
@@ -62,6 +62,7 @@ struct thread_info {
 #define TIF_POLLING_NRFLAG     4       /* true if poll_idle() is polling TIF_NEED_RESCHED */
 #define TIF_32BIT               5       /* 32 bit binary */
 #define TIF_MEMDIE             6
+#define TIF_RESTORE_SIGMASK    7       /* restore saved signal mask */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
@@ -69,9 +70,10 @@ struct thread_info {
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
 #define _TIF_POLLING_NRFLAG    (1 << TIF_POLLING_NRFLAG)
 #define _TIF_32BIT             (1 << TIF_32BIT)
+#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 
 #define _TIF_USER_WORK_MASK     (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
-                                 _TIF_NEED_RESCHED)
+                                 _TIF_NEED_RESCHED | _TIF_RESTORE_SIGMASK)
 
 #endif /* __KERNEL__ */
 
index 3fb37cfcb86427dd2d5376599dac3c235f291095..7c1bb8b0a96bbcdf06dffc83953d03b9ed21b18e 100644 (file)
@@ -955,6 +955,8 @@ type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5)       \
 #define __ARCH_WANT_SYS_SIGPENDING
 #define __ARCH_WANT_SYS_SIGPROCMASK
 #define __ARCH_WANT_SYS_RT_SIGACTION
+#define __ARCH_WANT_SYS_RT_SIGSUSPEND
+#define __ARCH_WANT_COMPAT_SYS_RT_SIGSUSPEND
 
 #endif /* __ASSEMBLY__ */