aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ia64
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-06-01 14:53:44 -0400
commit86c47b70f62a7072d441ba212aab33c2f82627c2 (patch)
treed03988bd2226966352bb7f3c2e82ff545353d2c4 /arch/ia64
parent1193755ac6328ad240ba987e6ec41d5e8baf0680 (diff)
parent44fbbb3dc687c9709a6f2236197316e5c79ab1eb (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull third pile of signal handling patches from Al Viro: "This time it's mostly helpers and conversions to them; there's a lot of stuff remaining in the tree, but that'll either go in -rc2 (isolated bug fixes, ideally via arch maintainers' trees) or will sit there until the next cycle." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: x86: get rid of calling do_notify_resume() when returning to kernel mode blackfin: check __get_user() return value whack-a-mole with TIF_FREEZE FRV: Optimise the system call exit path in entry.S [ver #2] FRV: Shrink TIF_WORK_MASK [ver #2] FRV: Prevent syscall exit tracing and notify_resume at end of kernel exceptions new helper: signal_delivered() powerpc: get rid of restore_sigmask() most of set_current_blocked() callers want SIGKILL/SIGSTOP removed from set set_restore_sigmask() is never called without SIGPENDING (and never should be) TIF_RESTORE_SIGMASK can be set only when TIF_SIGPENDING is set don't call try_to_freeze() from do_signal() pull clearing RESTORE_SIGMASK into block_sigmask() sh64: failure to build sigframe != signal without handler openrisc: tracehook_signal_handler() is supposed to be called on success new helper: sigmask_to_save() new helper: restore_saved_sigmask() new helpers: {clear,test,test_and_clear}_restore_sigmask() HAVE_RESTORE_SIGMASK is defined on all architectures now
Diffstat (limited to 'arch/ia64')
-rw-r--r--arch/ia64/include/asm/thread_info.h18
-rw-r--r--arch/ia64/kernel/signal.c34
2 files changed, 22 insertions, 30 deletions
diff --git a/arch/ia64/include/asm/thread_info.h b/arch/ia64/include/asm/thread_info.h
index 310d9734f02d..f7ee85378311 100644
--- a/arch/ia64/include/asm/thread_info.h
+++ b/arch/ia64/include/asm/thread_info.h
@@ -141,7 +141,23 @@ static inline void set_restore_sigmask(void)
141{ 141{
142 struct thread_info *ti = current_thread_info(); 142 struct thread_info *ti = current_thread_info();
143 ti->status |= TS_RESTORE_SIGMASK; 143 ti->status |= TS_RESTORE_SIGMASK;
144 set_bit(TIF_SIGPENDING, &ti->flags); 144 WARN_ON(!test_bit(TIF_SIGPENDING, &ti->flags));
145}
146static inline void clear_restore_sigmask(void)
147{
148 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
149}
150static inline bool test_restore_sigmask(void)
151{
152 return current_thread_info()->status & TS_RESTORE_SIGMASK;
153}
154static inline bool test_and_clear_restore_sigmask(void)
155{
156 struct thread_info *ti = current_thread_info();
157 if (!(ti->status & TS_RESTORE_SIGMASK))
158 return false;
159 ti->status &= ~TS_RESTORE_SIGMASK;
160 return true;
145} 161}
146#endif /* !__ASSEMBLY__ */ 162#endif /* !__ASSEMBLY__ */
147 163
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c
index 7523501d3bc0..a199be1fe619 100644
--- a/arch/ia64/kernel/signal.c
+++ b/arch/ia64/kernel/signal.c
@@ -30,7 +30,6 @@
30 30
31#define DEBUG_SIG 0 31#define DEBUG_SIG 0
32#define STACK_ALIGN 16 /* minimal alignment for stack pointer */ 32#define STACK_ALIGN 16 /* minimal alignment for stack pointer */
33#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
34 33
35#if _NSIG_WORDS > 1 34#if _NSIG_WORDS > 1
36# define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t)) 35# define PUT_SIGSET(k,u) __copy_to_user((u)->sig, (k)->sig, sizeof(sigset_t))
@@ -200,7 +199,6 @@ ia64_rt_sigreturn (struct sigscratch *scr)
200 if (GET_SIGSET(&set, &sc->sc_mask)) 199 if (GET_SIGSET(&set, &sc->sc_mask))
201 goto give_sigsegv; 200 goto give_sigsegv;
202 201
203 sigdelsetmask(&set, ~_BLOCKABLE);
204 set_current_blocked(&set); 202 set_current_blocked(&set);
205 203
206 if (restore_sigcontext(sc, scr)) 204 if (restore_sigcontext(sc, scr))
@@ -415,18 +413,13 @@ setup_frame (int sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *set,
415} 413}
416 414
417static long 415static long
418handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset, 416handle_signal (unsigned long sig, struct k_sigaction *ka, siginfo_t *info,
419 struct sigscratch *scr) 417 struct sigscratch *scr)
420{ 418{
421 if (!setup_frame(sig, ka, info, oldset, scr)) 419 if (!setup_frame(sig, ka, info, sigmask_to_save(), scr))
422 return 0; 420 return 0;
423 421
424 block_sigmask(ka, sig); 422 signal_delivered(sig, info, ka, &scr->pt,
425
426 /*
427 * Let tracing know that we've done the handler setup.
428 */
429 tracehook_signal_handler(sig, info, ka, &scr->pt,
430 test_thread_flag(TIF_SINGLESTEP)); 423 test_thread_flag(TIF_SINGLESTEP));
431 424
432 return 1; 425 return 1;
@@ -440,7 +433,6 @@ void
440ia64_do_signal (struct sigscratch *scr, long in_syscall) 433ia64_do_signal (struct sigscratch *scr, long in_syscall)
441{ 434{
442 struct k_sigaction ka; 435 struct k_sigaction ka;
443 sigset_t *oldset;
444 siginfo_t info; 436 siginfo_t info;
445 long restart = in_syscall; 437 long restart = in_syscall;
446 long errno = scr->pt.r8; 438 long errno = scr->pt.r8;
@@ -453,11 +445,6 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
453 if (!user_mode(&scr->pt)) 445 if (!user_mode(&scr->pt))
454 return; 446 return;
455 447
456 if (current_thread_info()->status & TS_RESTORE_SIGMASK)
457 oldset = &current->saved_sigmask;
458 else
459 oldset = &current->blocked;
460
461 /* 448 /*
462 * This only loops in the rare cases of handle_signal() failing, in which case we 449 * This only loops in the rare cases of handle_signal() failing, in which case we
463 * need to push through a forced SIGSEGV. 450 * need to push through a forced SIGSEGV.
@@ -507,16 +494,8 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
507 * Whee! Actually deliver the signal. If the delivery failed, we need to 494 * Whee! Actually deliver the signal. If the delivery failed, we need to
508 * continue to iterate in this loop so we can deliver the SIGSEGV... 495 * continue to iterate in this loop so we can deliver the SIGSEGV...
509 */ 496 */
510 if (handle_signal(signr, &ka, &info, oldset, scr)) { 497 if (handle_signal(signr, &ka, &info, scr))
511 /*
512 * A signal was successfully delivered; the saved
513 * sigmask will have been stored in the signal frame,
514 * and will be restored by sigreturn, so we can simply
515 * clear the TS_RESTORE_SIGMASK flag.
516 */
517 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
518 return; 498 return;
519 }
520 } 499 }
521 500
522 /* Did we come from a system call? */ 501 /* Did we come from a system call? */
@@ -538,8 +517,5 @@ ia64_do_signal (struct sigscratch *scr, long in_syscall)
538 517
539 /* if there's no signal to deliver, we just put the saved sigmask 518 /* if there's no signal to deliver, we just put the saved sigmask
540 * back */ 519 * back */
541 if (current_thread_info()->status & TS_RESTORE_SIGMASK) { 520 restore_saved_sigmask();
542 current_thread_info()->status &= ~TS_RESTORE_SIGMASK;
543 sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
544 }
545} 521}