diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2012-04-22 00:59:07 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2012-05-21 23:58:06 -0400 |
commit | 9ccc9c75c9117d18a9b1f71a21f0066b1eb9db6f (patch) | |
tree | bbc68a45dc8e98dd12339e4c7df6a088a342bbf3 /arch/xtensa/kernel/signal.c | |
parent | 446cdd13275bfa38b858a1e99dbd61c07c9767c0 (diff) |
xtensa: switch to generic rt_sigsuspend(2)
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'arch/xtensa/kernel/signal.c')
-rw-r--r-- | arch/xtensa/kernel/signal.c | 54 |
1 files changed, 15 insertions, 39 deletions
diff --git a/arch/xtensa/kernel/signal.c b/arch/xtensa/kernel/signal.c index 44e9329a6484..bb00cc470ca9 100644 --- a/arch/xtensa/kernel/signal.c +++ b/arch/xtensa/kernel/signal.c | |||
@@ -31,8 +31,6 @@ | |||
31 | 31 | ||
32 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) | 32 | #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) |
33 | 33 | ||
34 | asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset); | ||
35 | |||
36 | extern struct task_struct *coproc_owners[]; | 34 | extern struct task_struct *coproc_owners[]; |
37 | 35 | ||
38 | struct rt_sigframe | 36 | struct rt_sigframe |
@@ -429,37 +427,6 @@ give_sigsegv: | |||
429 | return -EFAULT; | 427 | return -EFAULT; |
430 | } | 428 | } |
431 | 429 | ||
432 | /* | ||
433 | * Atomically swap in the new signal mask, and wait for a signal. | ||
434 | */ | ||
435 | |||
436 | asmlinkage long xtensa_rt_sigsuspend(sigset_t __user *unewset, | ||
437 | size_t sigsetsize, | ||
438 | long a2, long a3, long a4, long a5, | ||
439 | struct pt_regs *regs) | ||
440 | { | ||
441 | sigset_t saveset, newset; | ||
442 | |||
443 | /* XXX: Don't preclude handling different sized sigset_t's. */ | ||
444 | if (sigsetsize != sizeof(sigset_t)) | ||
445 | return -EINVAL; | ||
446 | |||
447 | if (copy_from_user(&newset, unewset, sizeof(newset))) | ||
448 | return -EFAULT; | ||
449 | |||
450 | sigdelsetmask(&newset, ~_BLOCKABLE); | ||
451 | saveset = current->blocked; | ||
452 | set_current_blocked(&newset); | ||
453 | |||
454 | regs->areg[2] = -EINTR; | ||
455 | while (1) { | ||
456 | current->state = TASK_INTERRUPTIBLE; | ||
457 | schedule(); | ||
458 | if (do_signal(regs, &saveset)) | ||
459 | return -EINTR; | ||
460 | } | ||
461 | } | ||
462 | |||
463 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, | 430 | asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, |
464 | stack_t __user *uoss, | 431 | stack_t __user *uoss, |
465 | long a2, long a3, long a4, long a5, | 432 | long a2, long a3, long a4, long a5, |
@@ -479,19 +446,22 @@ asmlinkage long xtensa_sigaltstack(const stack_t __user *uss, | |||
479 | * the kernel can handle, and then we build all the user-level signal handling | 446 | * the kernel can handle, and then we build all the user-level signal handling |
480 | * stack-frames in one go after that. | 447 | * stack-frames in one go after that. |
481 | */ | 448 | */ |
482 | int do_signal(struct pt_regs *regs, sigset_t *oldset) | 449 | void do_signal(struct pt_regs *regs) |
483 | { | 450 | { |
484 | siginfo_t info; | 451 | siginfo_t info; |
485 | int signr; | 452 | int signr; |
486 | struct k_sigaction ka; | 453 | struct k_sigaction ka; |
454 | sigset_t oldset; | ||
487 | 455 | ||
488 | if (!user_mode(regs)) | 456 | if (!user_mode(regs)) |
489 | return 0; | 457 | return; |
490 | 458 | ||
491 | if (try_to_freeze()) | 459 | if (try_to_freeze()) |
492 | goto no_signal; | 460 | goto no_signal; |
493 | 461 | ||
494 | if (!oldset) | 462 | if (test_thread_flag(TIF_RESTORE_SIGMASK)) |
463 | oldset = ¤t->saved_sigmask; | ||
464 | else | ||
495 | oldset = ¤t->blocked; | 465 | oldset = ¤t->blocked; |
496 | 466 | ||
497 | task_pt_regs(current)->icountlevel = 0; | 467 | task_pt_regs(current)->icountlevel = 0; |
@@ -535,13 +505,14 @@ int do_signal(struct pt_regs *regs, sigset_t *oldset) | |||
535 | /* Set up the stack frame */ | 505 | /* Set up the stack frame */ |
536 | ret = setup_frame(signr, &ka, &info, oldset, regs); | 506 | ret = setup_frame(signr, &ka, &info, oldset, regs); |
537 | if (ret) | 507 | if (ret) |
538 | return ret; | 508 | return; |
539 | 509 | ||
510 | clear_thread_flag(TIF_RESTORE_SIGMASK); | ||
540 | block_sigmask(&ka, signr); | 511 | block_sigmask(&ka, signr); |
541 | if (current->ptrace & PT_SINGLESTEP) | 512 | if (current->ptrace & PT_SINGLESTEP) |
542 | task_pt_regs(current)->icountlevel = 1; | 513 | task_pt_regs(current)->icountlevel = 1; |
543 | 514 | ||
544 | return 1; | 515 | return; |
545 | } | 516 | } |
546 | 517 | ||
547 | no_signal: | 518 | no_signal: |
@@ -561,8 +532,13 @@ no_signal: | |||
561 | break; | 532 | break; |
562 | } | 533 | } |
563 | } | 534 | } |
535 | |||
536 | /* If there's no signal to deliver, we just restore the saved mask. */ | ||
537 | if (test_and_clear_thread_flag(TIF_RESTORE_SIGMASK)) | ||
538 | set_current_blocked(¤t->saved_sigmask); | ||
539 | |||
564 | if (current->ptrace & PT_SINGLESTEP) | 540 | if (current->ptrace & PT_SINGLESTEP) |
565 | task_pt_regs(current)->icountlevel = 1; | 541 | task_pt_regs(current)->icountlevel = 1; |
566 | return 0; | 542 | return; |
567 | } | 543 | } |
568 | 544 | ||