sh64: ppoll/pselect6() and restartable syscalls.
authorPaul Mundt <lethal@linux-sh.org>
Mon, 14 May 2007 00:12:39 +0000 (09:12 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Mon, 14 May 2007 00:12:39 +0000 (09:12 +0900)
This patch was hanging around for some time while we were waiting
for the compiler situation to improve.. now that all is well again,
finally merge it.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
arch/sh64/kernel/entry.S
arch/sh64/kernel/signal.c
include/asm-sh64/thread_info.h

index 40d4534..7013fcb 100644 (file)
@@ -947,14 +947,14 @@ ret_with_reschedule:
        ! FIXME:!!!
        ! no handling of TIF_SYSCALL_TRACE yet!!
 
-       movi    (1 << TIF_NEED_RESCHED), r8
+       movi    _TIF_NEED_RESCHED, r8
        and     r8, r7, r8
        pta     work_resched, tr0
        bne     r8, ZERO, tr0
 
        pta     restore_all, tr1
 
-       movi    (1 << TIF_SIGPENDING), r8
+       movi    (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK), r8
        and     r8, r7, r8
        pta     work_notifysig, tr0
        bne     r8, ZERO, tr0
index b76bdfa..c8525ad 100644 (file)
@@ -698,7 +698,9 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
        if (try_to_freeze())
                goto no_signal;
 
-       if (!oldset)
+       if (test_thread_flag(TIF_RESTORE_SIGMASK))
+               oldset = &current->saved_sigmask;
+       else if (!oldset)
                oldset = &current->blocked;
 
        signr = get_signal_to_deliver(&info, &ka, regs, 0);
@@ -706,6 +708,15 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset)
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
                handle_signal(signr, &info, &ka, oldset, regs);
+
+               /*
+                * If a signal was successfully delivered, the saved sigmask
+                * is in its frame, and we can clear the TIF_RESTORE_SIGMASK
+                * flag.
+                */
+               if (test_thread_flag(TIF_RESTORE_SIGMASK))
+                       clear_thread_flag(TIF_RESTORE_SIGMASK);
+
                return 1;
        }
 
@@ -713,13 +724,27 @@ no_signal:
        /* Did we come from a system call? */
        if (regs->syscall_nr >= 0) {
                /* Restart the system call - no handlers present */
-               if (regs->regs[REG_RET] == -ERESTARTNOHAND ||
-                   regs->regs[REG_RET] == -ERESTARTSYS ||
-                   regs->regs[REG_RET] == -ERESTARTNOINTR) {
+               switch (regs->regs[REG_RET]) {
+               case -ERESTARTNOHAND:
+               case -ERESTARTSYS:
+               case -ERESTARTNOINTR:
                        /* Decode Syscall # */
                        regs->regs[REG_RET] = regs->syscall_nr;
                        regs->pc -= 4;
+                       break;
+
+               case -ERESTART_RESTARTBLOCK:
+                       regs->regs[REG_RET] = __NR_restart_syscall;
+                       regs->pc -= 4;
+                       break;
                }
        }
+
+       /* 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;
 }
index 1f825cb..f6d5117 100644 (file)
@@ -78,7 +78,13 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SIGPENDING         2       /* signal pending */
 #define TIF_NEED_RESCHED       3       /* rescheduling necessary */
 #define TIF_MEMDIE             4
+#define TIF_RESTORE_SIGMASK    5       /* Restore signal mask in do_signal */
 
+#define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
+#define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_MEMDIE            (1 << TIF_MEMDIE)
+#define _TIF_RESTORE_SIGMASK   (1 << TIF_RESTORE_SIGMASK)
 
 #endif /* __KERNEL__ */