diff options
Diffstat (limited to 'arch/ia64/ia32/ia32_signal.c')
-rw-r--r-- | arch/ia64/ia32/ia32_signal.c | 65 |
1 files changed, 15 insertions, 50 deletions
diff --git a/arch/ia64/ia32/ia32_signal.c b/arch/ia64/ia32/ia32_signal.c index 10510e585204..85e82f32e480 100644 --- a/arch/ia64/ia32/ia32_signal.c +++ b/arch/ia64/ia32/ia32_signal.c | |||
@@ -451,59 +451,20 @@ sigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int r | |||
451 | sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); | 451 | sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler); |
452 | } | 452 | } |
453 | 453 | ||
454 | long | 454 | asmlinkage long |
455 | __ia32_rt_sigsuspend (compat_sigset_t *sset, unsigned int sigsetsize, struct sigscratch *scr) | 455 | sys32_sigsuspend (int history0, int history1, old_sigset_t mask) |
456 | { | 456 | { |
457 | extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall); | 457 | mask &= _BLOCKABLE; |
458 | sigset_t oldset, set; | ||
459 | |||
460 | scr->scratch_unat = 0; /* avoid leaking kernel bits to user level */ | ||
461 | memset(&set, 0, sizeof(set)); | ||
462 | |||
463 | memcpy(&set.sig, &sset->sig, sigsetsize); | ||
464 | |||
465 | sigdelsetmask(&set, ~_BLOCKABLE); | ||
466 | |||
467 | spin_lock_irq(¤t->sighand->siglock); | 458 | spin_lock_irq(¤t->sighand->siglock); |
468 | { | 459 | current->saved_sigmask = current->blocked; |
469 | oldset = current->blocked; | 460 | siginitset(¤t->blocked, mask); |
470 | current->blocked = set; | 461 | recalc_sigpending(); |
471 | recalc_sigpending(); | ||
472 | } | ||
473 | spin_unlock_irq(¤t->sighand->siglock); | 462 | spin_unlock_irq(¤t->sighand->siglock); |
474 | 463 | ||
475 | /* | 464 | current->state = TASK_INTERRUPTIBLE; |
476 | * The return below usually returns to the signal handler. We need to pre-set the | 465 | schedule(); |
477 | * correct error code here to ensure that the right values get saved in sigcontext | 466 | set_thread_flag(TIF_RESTORE_SIGMASK); |
478 | * by ia64_do_signal. | 467 | return -ERESTARTNOHAND; |
479 | */ | ||
480 | scr->pt.r8 = -EINTR; | ||
481 | while (1) { | ||
482 | current->state = TASK_INTERRUPTIBLE; | ||
483 | schedule(); | ||
484 | if (ia64_do_signal(&oldset, scr, 1)) | ||
485 | return -EINTR; | ||
486 | } | ||
487 | } | ||
488 | |||
489 | asmlinkage long | ||
490 | ia32_rt_sigsuspend (compat_sigset_t __user *uset, unsigned int sigsetsize, struct sigscratch *scr) | ||
491 | { | ||
492 | compat_sigset_t set; | ||
493 | |||
494 | if (sigsetsize > sizeof(compat_sigset_t)) | ||
495 | return -EINVAL; | ||
496 | |||
497 | if (copy_from_user(&set.sig, &uset->sig, sigsetsize)) | ||
498 | return -EFAULT; | ||
499 | |||
500 | return __ia32_rt_sigsuspend(&set, sigsetsize, scr); | ||
501 | } | ||
502 | |||
503 | asmlinkage long | ||
504 | ia32_sigsuspend (unsigned int mask, struct sigscratch *scr) | ||
505 | { | ||
506 | return __ia32_rt_sigsuspend((compat_sigset_t *) &mask, sizeof(mask), scr); | ||
507 | } | 468 | } |
508 | 469 | ||
509 | asmlinkage long | 470 | asmlinkage long |
@@ -810,7 +771,11 @@ get_sigframe (struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size) | |||
810 | } | 771 | } |
811 | /* Legacy stack switching not supported */ | 772 | /* Legacy stack switching not supported */ |
812 | 773 | ||
813 | return (void __user *)((esp - frame_size) & -8ul); | 774 | esp -= frame_size; |
775 | /* Align the stack pointer according to the i386 ABI, | ||
776 | * i.e. so that on function entry ((sp + 4) & 15) == 0. */ | ||
777 | esp = ((esp + 4) & -16ul) - 4; | ||
778 | return (void __user *) esp; | ||
814 | } | 779 | } |
815 | 780 | ||
816 | static int | 781 | static int |