diff options
Diffstat (limited to 'arch/ia64/kernel/signal.c')
| -rw-r--r-- | arch/ia64/kernel/signal.c | 101 |
1 files changed, 0 insertions, 101 deletions
diff --git a/arch/ia64/kernel/signal.c b/arch/ia64/kernel/signal.c index 463f6bb44d07..1d7903ee2126 100644 --- a/arch/ia64/kernel/signal.c +++ b/arch/ia64/kernel/signal.c | |||
| @@ -588,104 +588,3 @@ ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall) | |||
| 588 | } | 588 | } |
| 589 | return 0; | 589 | return 0; |
| 590 | } | 590 | } |
| 591 | |||
| 592 | /* Set a delayed signal that was detected in MCA/INIT/NMI/PMI context where it | ||
| 593 | * could not be delivered. It is important that the target process is not | ||
| 594 | * allowed to do any more work in user space. Possible cases for the target | ||
| 595 | * process: | ||
| 596 | * | ||
| 597 | * - It is sleeping and will wake up soon. Store the data in the current task, | ||
| 598 | * the signal will be sent when the current task returns from the next | ||
| 599 | * interrupt. | ||
| 600 | * | ||
| 601 | * - It is running in user context. Store the data in the current task, the | ||
| 602 | * signal will be sent when the current task returns from the next interrupt. | ||
| 603 | * | ||
| 604 | * - It is running in kernel context on this or another cpu and will return to | ||
| 605 | * user context. Store the data in the target task, the signal will be sent | ||
| 606 | * to itself when the target task returns to user space. | ||
| 607 | * | ||
| 608 | * - It is running in kernel context on this cpu and will sleep before | ||
| 609 | * returning to user context. Because this is also the current task, the | ||
| 610 | * signal will not get delivered and the task could sleep indefinitely. | ||
| 611 | * Store the data in the idle task for this cpu, the signal will be sent | ||
| 612 | * after the idle task processes its next interrupt. | ||
| 613 | * | ||
| 614 | * To cover all cases, store the data in the target task, the current task and | ||
| 615 | * the idle task on this cpu. Whatever happens, the signal will be delivered | ||
| 616 | * to the target task before it can do any useful user space work. Multiple | ||
| 617 | * deliveries have no unwanted side effects. | ||
| 618 | * | ||
| 619 | * Note: This code is executed in MCA/INIT/NMI/PMI context, with interrupts | ||
| 620 | * disabled. It must not take any locks nor use kernel structures or services | ||
| 621 | * that require locks. | ||
| 622 | */ | ||
| 623 | |||
| 624 | /* To ensure that we get the right pid, check its start time. To avoid extra | ||
| 625 | * include files in thread_info.h, convert the task start_time to unsigned long, | ||
| 626 | * giving us a cycle time of > 580 years. | ||
| 627 | */ | ||
| 628 | static inline unsigned long | ||
| 629 | start_time_ul(const struct task_struct *t) | ||
| 630 | { | ||
| 631 | return t->start_time.tv_sec * NSEC_PER_SEC + t->start_time.tv_nsec; | ||
| 632 | } | ||
| 633 | |||
| 634 | void | ||
| 635 | set_sigdelayed(pid_t pid, int signo, int code, void __user *addr) | ||
| 636 | { | ||
| 637 | struct task_struct *t; | ||
| 638 | unsigned long start_time = 0; | ||
| 639 | int i; | ||
| 640 | |||
| 641 | for (i = 1; i <= 3; ++i) { | ||
| 642 | switch (i) { | ||
| 643 | case 1: | ||
| 644 | t = find_task_by_pid(pid); | ||
| 645 | if (t) | ||
| 646 | start_time = start_time_ul(t); | ||
| 647 | break; | ||
| 648 | case 2: | ||
| 649 | t = current; | ||
| 650 | break; | ||
| 651 | default: | ||
| 652 | t = idle_task(smp_processor_id()); | ||
| 653 | break; | ||
| 654 | } | ||
| 655 | |||
| 656 | if (!t) | ||
| 657 | return; | ||
| 658 | task_thread_info(t)->sigdelayed.signo = signo; | ||
| 659 | task_thread_info(t)->sigdelayed.code = code; | ||
| 660 | task_thread_info(t)->sigdelayed.addr = addr; | ||
| 661 | task_thread_info(t)->sigdelayed.start_time = start_time; | ||
| 662 | task_thread_info(t)->sigdelayed.pid = pid; | ||
| 663 | wmb(); | ||
| 664 | set_tsk_thread_flag(t, TIF_SIGDELAYED); | ||
| 665 | } | ||
| 666 | } | ||
| 667 | |||
| 668 | /* Called from entry.S when it detects TIF_SIGDELAYED, a delayed signal that | ||
| 669 | * was detected in MCA/INIT/NMI/PMI context where it could not be delivered. | ||
| 670 | */ | ||
| 671 | |||
| 672 | void | ||
| 673 | do_sigdelayed(void) | ||
| 674 | { | ||
| 675 | struct siginfo siginfo; | ||
| 676 | pid_t pid; | ||
| 677 | struct task_struct *t; | ||
| 678 | |||
| 679 | clear_thread_flag(TIF_SIGDELAYED); | ||
| 680 | memset(&siginfo, 0, sizeof(siginfo)); | ||
| 681 | siginfo.si_signo = current_thread_info()->sigdelayed.signo; | ||
| 682 | siginfo.si_code = current_thread_info()->sigdelayed.code; | ||
| 683 | siginfo.si_addr = current_thread_info()->sigdelayed.addr; | ||
| 684 | pid = current_thread_info()->sigdelayed.pid; | ||
| 685 | t = find_task_by_pid(pid); | ||
| 686 | if (!t) | ||
| 687 | return; | ||
| 688 | if (current_thread_info()->sigdelayed.start_time != start_time_ul(t)) | ||
| 689 | return; | ||
| 690 | force_sig_info(siginfo.si_signo, &siginfo, t); | ||
| 691 | } | ||
