From 4ebefe3ec729003443daf153ed6fad1739271283 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 26 Apr 2012 22:29:20 -0400 Subject: new helpers: {clear,test,test_and_clear}_restore_sigmask() helpers parallel to set_restore_sigmask(), used in the next commits Signed-off-by: Al Viro --- arch/sparc/include/asm/thread_info_64.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'arch/sparc') diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index 7f0981b0945..cb9b7a9f5fc 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -240,6 +240,22 @@ static inline void set_restore_sigmask(void) ti->status |= TS_RESTORE_SIGMASK; set_bit(TIF_SIGPENDING, &ti->flags); } +static inline void clear_restore_sigmask(void) +{ + current_thread_info()->status &= ~TS_RESTORE_SIGMASK; +} +static inline bool test_restore_sigmask(void) +{ + return current_thread_info()->status & TS_RESTORE_SIGMASK; +} +static inline bool test_and_clear_restore_sigmask(void) +{ + struct thread_info *ti = current_thread_info(); + if (!(ti->status & TS_RESTORE_SIGMASK)) + return false; + ti->status &= ~TS_RESTORE_SIGMASK; + return true; +} #endif /* !__ASSEMBLY__ */ #endif /* __KERNEL__ */ -- cgit v1.2.3-18-g5258 From 51a7b448d4134e3e8eec633435e3e8faee14a828 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 21 May 2012 23:33:55 -0400 Subject: new helper: restore_saved_sigmask() first fruits of ..._restore_sigmask() helpers: now we can take boilerplate "signal didn't have a handler, clear RESTORE_SIGMASK and restore the blocked mask from ->saved_mask" into a common helper. Open-coded instances switched... Signed-off-by: Al Viro --- arch/sparc/kernel/signal32.c | 5 +---- arch/sparc/kernel/signal_32.c | 5 +---- arch/sparc/kernel/signal_64.c | 5 +---- 3 files changed, 3 insertions(+), 12 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index bb1513e45f1..88e0d8122d2 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -872,10 +872,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs) /* If there's no signal to deliver, we just put the saved sigmask * back */ - if (current_thread_info()->status & TS_RESTORE_SIGMASK) { - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - set_current_blocked(¤t->saved_sigmask); - } + restore_saved_sigmask(); } struct sigstack32 { diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 6b42e8622d1..9dd97d2e171 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -576,10 +576,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) /* if there's no signal to deliver, we just put the saved sigmask * back */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) { - clear_thread_flag(TIF_RESTORE_SIGMASK); - set_current_blocked(¤t->saved_sigmask); - } + restore_saved_sigmask(); } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index c82cf1cc396..55b820ee0ac 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -594,10 +594,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) /* If there's no signal to deliver, we just put the saved sigmask * back */ - if (current_thread_info()->status & TS_RESTORE_SIGMASK) { - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - set_current_blocked(¤t->saved_sigmask); - } + restore_saved_sigmask(); } void do_notify_resume(struct pt_regs *regs, unsigned long orig_i0, unsigned long thread_info_flags) -- cgit v1.2.3-18-g5258 From b7f9a11a6cf1ea9ee6be3eb2b90d91327a09ad14 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 2 May 2012 09:59:21 -0400 Subject: new helper: sigmask_to_save() replace boilerplate "should we use ->saved_sigmask or ->blocked?" with calls of obvious inlined helper... Signed-off-by: Al Viro --- arch/sparc/kernel/signal_32.c | 11 +++-------- arch/sparc/kernel/signal_64.c | 7 +------ 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 9dd97d2e171..5d74410c787 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -451,8 +451,9 @@ sigsegv: static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) + siginfo_t *info, struct pt_regs *regs) { + sigset_t *oldset = sigmask_to_save(); int err; if (ka->sa.sa_flags & SA_SIGINFO) @@ -498,7 +499,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; - sigset_t *oldset; siginfo_t info; int signr; @@ -523,11 +523,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (pt_regs_is_syscall(regs) && (regs->psr & PSR_C)) regs->u_regs[UREG_G6] = orig_i0; - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - signr = get_signal_to_deliver(&info, &ka, regs, NULL); /* If the debugger messes with the program counter, it clears @@ -544,7 +539,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { + if (handle_signal(signr, &ka, &info, regs) == 0) { /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 55b820ee0ac..088a733f83f 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -512,7 +512,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) { struct k_sigaction ka; int restart_syscall; - sigset_t *oldset; + sigset_t *oldset = sigmask_to_save(); siginfo_t info; int signr; @@ -538,11 +538,6 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) regs->u_regs[UREG_G6] = orig_i0; - if (current_thread_info()->status & TS_RESTORE_SIGMASK) - oldset = ¤t->saved_sigmask; - else - oldset = ¤t->blocked; - #ifdef CONFIG_COMPAT if (test_thread_flag(TIF_32BIT)) { extern void do_signal32(sigset_t *, struct pt_regs *); -- cgit v1.2.3-18-g5258 From a610d6e672d6d3723e8da257ad4a8a288a8f2f89 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Mon, 21 May 2012 23:42:15 -0400 Subject: pull clearing RESTORE_SIGMASK into block_sigmask() Signed-off-by: Al Viro --- arch/sparc/kernel/signal32.c | 15 +++------------ arch/sparc/kernel/signal_32.c | 16 +++------------- arch/sparc/kernel/signal_64.c | 15 +++------------ 3 files changed, 9 insertions(+), 37 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 88e0d8122d2..8c93c00922a 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -775,7 +775,7 @@ sigsegv: return -EFAULT; } -static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, +static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -787,12 +787,10 @@ static inline int handle_signal32(unsigned long signr, struct k_sigaction *ka, err = setup_frame32(ka, regs, signr, oldset); if (err) - return err; + return; block_sigmask(ka, signr); tracehook_signal_handler(signr, info, ka, regs, 0); - - return 0; } static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, @@ -841,14 +839,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs) if (signr > 0) { if (restart_syscall) syscall_restart32(orig_i0, regs, &ka.sa); - if (handle_signal32(signr, &ka, &info, oldset, regs) == 0) { - /* A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TS_RESTORE_SIGMASK flag. - */ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - } + handle_signal32(signr, &ka, &info, oldset, regs); return; } if (restart_syscall && diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 5d74410c787..ee81b90c532 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -449,7 +449,7 @@ sigsegv: return -EFAULT; } -static inline int +static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, struct pt_regs *regs) { @@ -462,12 +462,10 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, err = setup_frame(ka, regs, signr, oldset); if (err) - return err; + return; block_sigmask(ka, signr); tracehook_signal_handler(signr, info, ka, regs, 0); - - return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -539,15 +537,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - if (handle_signal(signr, &ka, &info, regs) == 0) { - /* a signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TIF_RESTORE_SIGMASK flag. - */ - if (test_thread_flag(TIF_RESTORE_SIGMASK)) - clear_thread_flag(TIF_RESTORE_SIGMASK); - } + handle_signal(signr, &ka, &info, regs); return; } if (restart_syscall && diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 088a733f83f..febbc4b697b 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -466,7 +466,7 @@ sigsegv: return -EFAULT; } -static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, +static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { @@ -475,12 +475,10 @@ static inline int handle_signal(unsigned long signr, struct k_sigaction *ka, err = setup_rt_frame(ka, regs, signr, oldset, (ka->sa.sa_flags & SA_SIGINFO) ? info : NULL); if (err) - return err; + return; block_sigmask(ka, signr); tracehook_signal_handler(signr, info, ka, regs, 0); - - return 0; } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, @@ -558,14 +556,7 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) if (signr > 0) { if (restart_syscall) syscall_restart(orig_i0, regs, &ka.sa); - if (handle_signal(signr, &ka, &info, oldset, regs) == 0) { - /* A signal was successfully delivered; the saved - * sigmask will have been stored in the signal frame, - * and will be restored by sigreturn, so we can simply - * clear the TS_RESTORE_SIGMASK flag. - */ - current_thread_info()->status &= ~TS_RESTORE_SIGMASK; - } + handle_signal(signr, &ka, &info, oldset, regs); return; } if (restart_syscall && -- cgit v1.2.3-18-g5258 From 6fd84c0831ec78d98736b76dc5e9b849f1dbfc9e Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 May 2012 15:28:58 -0400 Subject: TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set Signed-off-by: Al Viro --- arch/sparc/include/asm/thread_info_32.h | 3 +-- arch/sparc/kernel/signal_32.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index 5af66493245..e6cd224506a 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h @@ -131,8 +131,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); #define _TIF_POLLING_NRFLAG (1< Date: Fri, 27 Apr 2012 13:42:45 -0400 Subject: set_restore_sigmask() is never called without SIGPENDING (and never should be) Signed-off-by: Al Viro --- arch/sparc/include/asm/thread_info_64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/sparc') diff --git a/arch/sparc/include/asm/thread_info_64.h b/arch/sparc/include/asm/thread_info_64.h index cb9b7a9f5fc..cfa8c38fb9c 100644 --- a/arch/sparc/include/asm/thread_info_64.h +++ b/arch/sparc/include/asm/thread_info_64.h @@ -238,7 +238,7 @@ static inline void set_restore_sigmask(void) { struct thread_info *ti = current_thread_info(); ti->status |= TS_RESTORE_SIGMASK; - set_bit(TIF_SIGPENDING, &ti->flags); + WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags)); } static inline void clear_restore_sigmask(void) { -- cgit v1.2.3-18-g5258 From 77097ae503b170120ab66dd1d547f8577193f91f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 27 Apr 2012 13:58:59 -0400 Subject: most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set Only 3 out of 63 do not. Renamed the current variant to __set_current_blocked(), added set_current_blocked() that will exclude unblockable signals, switched open-coded instances to it. Signed-off-by: Al Viro --- arch/sparc/kernel/signal32.c | 4 ---- arch/sparc/kernel/signal_32.c | 4 ---- arch/sparc/kernel/signal_64.c | 4 ---- 3 files changed, 12 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index 8c93c00922a..ba3dbfcdb28 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -32,8 +32,6 @@ #include "sigutil.h" -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - /* This magic should be in g_upper[0] for all upper parts * to be valid. */ @@ -274,7 +272,6 @@ void do_sigreturn32(struct pt_regs *regs) case 2: set.sig[1] = seta[2] + (((long)seta[3]) << 32); case 1: set.sig[0] = seta[0] + (((long)seta[1]) << 32); } - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; @@ -376,7 +373,6 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs) case 2: set.sig[1] = seta.sig[2] + (((long)seta.sig[3]) << 32); case 1: set.sig[0] = seta.sig[0] + (((long)seta.sig[1]) << 32); } - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index f6722427203..1bfa854be60 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -29,8 +29,6 @@ #include "sigutil.h" -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - extern void fpsave(unsigned long *fpregs, unsigned long *fsr, void *fpqueue, unsigned long *fpqdepth); extern void fpload(unsigned long *fpregs, unsigned long *fsr); @@ -130,7 +128,6 @@ asmlinkage void do_sigreturn(struct pt_regs *regs) if (err) goto segv_and_exit; - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; @@ -197,7 +194,6 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs) goto segv; } - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index febbc4b697b..23b60caa6c4 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -38,8 +38,6 @@ #include "systbls.h" #include "sigutil.h" -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - /* {set, get}context() needed for 64-bit SparcLinux userland. */ asmlinkage void sparc64_set_context(struct pt_regs *regs) { @@ -71,7 +69,6 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs) if (__copy_from_user(&set, &ucp->uc_sigmask, sizeof(sigset_t))) goto do_sigsegv; } - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); } if (test_thread_flag(TIF_32BIT)) { @@ -315,7 +312,6 @@ void do_rt_sigreturn(struct pt_regs *regs) /* Prevent syscall restart. */ pt_regs_clear_syscall(regs); - sigdelsetmask(&set, ~_BLOCKABLE); set_current_blocked(&set); return; segv: -- cgit v1.2.3-18-g5258 From efee984c27b67e3ebef40410f35671997441b57c Mon Sep 17 00:00:00 2001 From: Al Viro Date: Sat, 28 Apr 2012 02:04:15 -0400 Subject: new helper: signal_delivered() Does block_sigmask() + tracehook_signal_handler(); called when sigframe has been successfully built. All architectures converted to it; block_sigmask() itself is gone now (merged into this one). I'm still not too happy with the signature, but that's a separate story (IMO we need a structure that would contain signal number + siginfo + k_sigaction, so that get_signal_to_deliver() would fill one, signal_delivered(), handle_signal() and probably setup...frame() - take one). Signed-off-by: Al Viro --- arch/sparc/kernel/signal32.c | 3 +-- arch/sparc/kernel/signal_32.c | 3 +-- arch/sparc/kernel/signal_64.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'arch/sparc') diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c index ba3dbfcdb28..a53e0a5fd3a 100644 --- a/arch/sparc/kernel/signal32.c +++ b/arch/sparc/kernel/signal32.c @@ -785,8 +785,7 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, if (err) return; - block_sigmask(ka, signr); - tracehook_signal_handler(signr, info, ka, regs, 0); + signal_delivered(signr, info, ka, regs, 0); } static inline void syscall_restart32(unsigned long orig_i0, struct pt_regs *regs, diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c index 1bfa854be60..68f9c8650af 100644 --- a/arch/sparc/kernel/signal_32.c +++ b/arch/sparc/kernel/signal_32.c @@ -460,8 +460,7 @@ handle_signal(unsigned long signr, struct k_sigaction *ka, if (err) return; - block_sigmask(ka, signr); - tracehook_signal_handler(signr, info, ka, regs, 0); + signal_delivered(signr, info, ka, regs, 0); } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c index 23b60caa6c4..867de2f8189 100644 --- a/arch/sparc/kernel/signal_64.c +++ b/arch/sparc/kernel/signal_64.c @@ -473,8 +473,7 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, if (err) return; - block_sigmask(ka, signr); - tracehook_signal_handler(signr, info, ka, regs, 0); + signal_delivered(signr, info, ka, regs, 0); } static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs, -- cgit v1.2.3-18-g5258