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

m68k: Switch to saner sigsuspend()

and saner do_signal() arguments, while we are at it

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>

authored by

Al Viro and committed by
Geert Uytterhoeven
e68847fe 35fc157b

+26 -61
+1
arch/m68k/include/asm/thread_info.h
··· 104 104 #define TIF_SYSCALL_TRACE 15 /* syscall trace active */ 105 105 #define TIF_MEMDIE 16 /* is terminating due to OOM killer */ 106 106 #define TIF_FREEZE 17 /* thread is freezing for suspend */ 107 + #define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal */ 107 108 108 109 #endif /* _ASM_M68K_THREAD_INFO_H */
+3
arch/m68k/include/asm/unistd.h
··· 373 373 #define __ARCH_WANT_SYS_SIGPENDING 374 374 #define __ARCH_WANT_SYS_SIGPROCMASK 375 375 #define __ARCH_WANT_SYS_RT_SIGACTION 376 + #ifndef __uClinux__ 377 + #define __ARCH_WANT_SYS_RT_SIGSUSPEND 378 + #endif 376 379 377 380 /* 378 381 * "Conditional" syscalls
+1 -18
arch/m68k/kernel/entry.S
··· 174 174 subql #4,%sp | dummy return address 175 175 SAVE_SWITCH_STACK 176 176 pea %sp@(SWITCH_STACK_SIZE) 177 - clrl %sp@- 178 177 bsrl do_signal 179 - addql #8,%sp 178 + addql #4,%sp 180 179 RESTORE_SWITCH_STACK 181 180 addql #4,%sp 182 181 tstl %d0 ··· 285 286 SAVE_SWITCH_STACK 286 287 pea %sp@(SWITCH_STACK_SIZE) 287 288 jbsr m68k_vfork 288 - addql #4,%sp 289 - RESTORE_SWITCH_STACK 290 - rts 291 - 292 - ENTRY(sys_sigsuspend) 293 - SAVE_SWITCH_STACK 294 - pea %sp@(SWITCH_STACK_SIZE) 295 - jbsr do_sigsuspend 296 - addql #4,%sp 297 - RESTORE_SWITCH_STACK 298 - rts 299 - 300 - ENTRY(sys_rt_sigsuspend) 301 - SAVE_SWITCH_STACK 302 - pea %sp@(SWITCH_STACK_SIZE) 303 - jbsr do_rt_sigsuspend 304 289 addql #4,%sp 305 290 RESTORE_SWITCH_STACK 306 291 rts
+21 -43
arch/m68k/kernel/signal.c
··· 51 51 52 52 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) 53 53 54 - asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs); 55 - 56 54 const int frame_extra_sizes[16] = { 57 55 [1] = -1, /* sizeof(((struct frame *)0)->un.fmt1), */ 58 56 [2] = sizeof(((struct frame *)0)->un.fmt2), ··· 72 74 /* 73 75 * Atomically swap in the new signal mask, and wait for a signal. 74 76 */ 75 - asmlinkage int do_sigsuspend(struct pt_regs *regs) 77 + asmlinkage int 78 + sys_sigsuspend(int unused0, int unused1, old_sigset_t mask) 76 79 { 77 - old_sigset_t mask = regs->d3; 78 - sigset_t saveset; 79 - 80 80 mask &= _BLOCKABLE; 81 - saveset = current->blocked; 81 + spin_lock_irq(&current->sighand->siglock); 82 + current->saved_sigmask = current->blocked; 82 83 siginitset(&current->blocked, mask); 83 84 recalc_sigpending(); 85 + spin_unlock_irq(&current->sighand->siglock); 84 86 85 - regs->d0 = -EINTR; 86 - while (1) { 87 - current->state = TASK_INTERRUPTIBLE; 88 - schedule(); 89 - if (do_signal(&saveset, regs)) 90 - return -EINTR; 91 - } 92 - } 87 + current->state = TASK_INTERRUPTIBLE; 88 + schedule(); 89 + set_restore_sigmask(); 93 90 94 - asmlinkage int 95 - do_rt_sigsuspend(struct pt_regs *regs) 96 - { 97 - sigset_t __user *unewset = (sigset_t __user *)regs->d1; 98 - size_t sigsetsize = (size_t)regs->d2; 99 - sigset_t saveset, newset; 100 - 101 - /* XXX: Don't preclude handling different sized sigset_t's. */ 102 - if (sigsetsize != sizeof(sigset_t)) 103 - return -EINVAL; 104 - 105 - if (copy_from_user(&newset, unewset, sizeof(newset))) 106 - return -EFAULT; 107 - sigdelsetmask(&newset, ~_BLOCKABLE); 108 - 109 - saveset = current->blocked; 110 - current->blocked = newset; 111 - recalc_sigpending(); 112 - 113 - regs->d0 = -EINTR; 114 - while (1) { 115 - current->state = TASK_INTERRUPTIBLE; 116 - schedule(); 117 - if (do_signal(&saveset, regs)) 118 - return -EINTR; 119 - } 91 + return -ERESTARTNOHAND; 120 92 } 121 93 122 94 asmlinkage int ··· 985 1017 * want to handle. Thus you cannot kill init even with a SIGKILL even by 986 1018 * mistake. 987 1019 */ 988 - asmlinkage int do_signal(sigset_t *oldset, struct pt_regs *regs) 1020 + asmlinkage int do_signal(struct pt_regs *regs) 989 1021 { 990 1022 siginfo_t info; 991 1023 struct k_sigaction ka; 992 1024 int signr; 1025 + sigset_t *oldset; 993 1026 994 1027 current->thread.esp0 = (unsigned long) regs; 995 1028 996 - if (!oldset) 1029 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) 1030 + oldset = &current->saved_sigmask; 1031 + else 997 1032 oldset = &current->blocked; 998 1033 999 1034 signr = get_signal_to_deliver(&info, &ka, regs, NULL); 1000 1035 if (signr > 0) { 1001 1036 /* Whee! Actually deliver the signal. */ 1002 1037 handle_signal(signr, &ka, &info, oldset, regs); 1038 + clear_thread_flag(TIF_RESTORE_SIGMASK); 1003 1039 return 1; 1004 1040 } 1005 1041 ··· 1011 1039 if (regs->orig_d0 >= 0) 1012 1040 /* Restart the system call - no handlers present */ 1013 1041 handle_restart(regs, NULL, 0); 1042 + 1043 + /* If there's no signal to deliver, we just restore the saved mask. */ 1044 + if (test_thread_flag(TIF_RESTORE_SIGMASK)) { 1045 + clear_thread_flag(TIF_RESTORE_SIGMASK); 1046 + sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); 1047 + } 1014 1048 1015 1049 return 0; 1016 1050 }