Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sh: Fix up spurious syscall restarting.

The T-bit manipulation for syscall error checking had the side effect of
spuriously returning ERESTART* errno values over EINTR. So, we simplify
the error checking a bit and leave the T-bit alone.

Reported-by: Kaz Kojima <kkojima@rr.iij4u.or.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

+8 -44
+3 -19
arch/sh/include/asm/syscall_32.h
··· 21 21 */ 22 22 } 23 23 24 - static inline bool syscall_has_error(struct pt_regs *regs) 25 - { 26 - return (regs->sr & 0x1) ? true : false; 27 - } 28 - static inline void syscall_set_error(struct pt_regs *regs) 29 - { 30 - regs->sr |= 0x1; 31 - } 32 - static inline void syscall_clear_error(struct pt_regs *regs) 33 - { 34 - regs->sr &= ~0x1; 35 - } 36 - 37 24 static inline long syscall_get_error(struct task_struct *task, 38 25 struct pt_regs *regs) 39 26 { 40 - return syscall_has_error(regs) ? regs->regs[0] : 0; 27 + return IS_ERR_VALUE(regs->regs[0]) ? regs->regs[0] : 0; 41 28 } 42 29 43 30 static inline long syscall_get_return_value(struct task_struct *task, ··· 37 50 struct pt_regs *regs, 38 51 int error, long val) 39 52 { 40 - if (error) { 41 - syscall_set_error(regs); 53 + if (error) 42 54 regs->regs[0] = -error; 43 - } else { 44 - syscall_clear_error(regs); 55 + else 45 56 regs->regs[0] = val; 46 - } 47 57 } 48 58 49 59 static inline void syscall_get_arguments(struct task_struct *task,
+3 -19
arch/sh/include/asm/syscall_64.h
··· 21 21 */ 22 22 } 23 23 24 - static inline bool syscall_has_error(struct pt_regs *regs) 25 - { 26 - return (regs->sr & 0x1) ? true : false; 27 - } 28 - static inline void syscall_set_error(struct pt_regs *regs) 29 - { 30 - regs->sr |= 0x1; 31 - } 32 - static inline void syscall_clear_error(struct pt_regs *regs) 33 - { 34 - regs->sr &= ~0x1; 35 - } 36 - 37 24 static inline long syscall_get_error(struct task_struct *task, 38 25 struct pt_regs *regs) 39 26 { 40 - return syscall_has_error(regs) ? regs->regs[9] : 0; 27 + return IS_ERR_VALUE(regs->regs[9]) ? regs->regs[9] : 0; 41 28 } 42 29 43 30 static inline long syscall_get_return_value(struct task_struct *task, ··· 37 50 struct pt_regs *regs, 38 51 int error, long val) 39 52 { 40 - if (error) { 41 - syscall_set_error(regs); 53 + if (error) 42 54 regs->regs[9] = -error; 43 - } else { 44 - syscall_clear_error(regs); 55 + else 45 56 regs->regs[9] = val; 46 - } 47 57 } 48 58 49 59 static inline void syscall_get_arguments(struct task_struct *task,
+1 -3
arch/sh/kernel/signal_32.c
··· 510 510 case -ERESTARTNOHAND: 511 511 no_system_call_restart: 512 512 regs->regs[0] = -EINTR; 513 - regs->sr |= 1; 514 513 break; 515 514 516 515 case -ERESTARTSYS: ··· 588 589 589 590 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 590 591 if (signr > 0) { 591 - if (regs->sr & 1) 592 - handle_syscall_restart(save_r0, regs, &ka.sa); 592 + handle_syscall_restart(save_r0, regs, &ka.sa); 593 593 594 594 /* Whee! Actually deliver the signal. */ 595 595 if (handle_signal(signr, &ka, &info, oldset,
+1 -3
arch/sh/kernel/signal_64.c
··· 60 60 case -ERESTARTNOHAND: 61 61 no_system_call_restart: 62 62 regs->regs[REG_RET] = -EINTR; 63 - regs->sr |= 1; 64 63 break; 65 64 66 65 case -ERESTARTSYS: ··· 108 109 109 110 signr = get_signal_to_deliver(&info, &ka, regs, 0); 110 111 if (signr > 0) { 111 - if (regs->sr & 1) 112 - handle_syscall_restart(regs, &ka.sa); 112 + handle_syscall_restart(regs, &ka.sa); 113 113 114 114 /* Whee! Actually deliver the signal. */ 115 115 if (handle_signal(signr, &info, &ka, oldset, regs) == 0) {