Sfoglia il codice sorgente

sh64: ppoll/pselect6() and restartable syscalls.

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>
Paul Mundt 18 anni fa
parent
commit
c18fe9a046
3 ha cambiato i file con 37 aggiunte e 6 eliminazioni
  1. 2 2
      arch/sh64/kernel/entry.S
  2. 29 4
      arch/sh64/kernel/signal.c
  3. 6 0
      include/asm-sh64/thread_info.h

+ 2 - 2
arch/sh64/kernel/entry.S

@@ -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

+ 29 - 4
arch/sh64/kernel/signal.c

@@ -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;
 }

+ 6 - 0
include/asm-sh64/thread_info.h

@@ -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__ */