diff options
Diffstat (limited to 'kernel/sched.c')
-rw-r--r-- | kernel/sched.c | 188 |
1 files changed, 49 insertions, 139 deletions
diff --git a/kernel/sched.c b/kernel/sched.c index 4c15b1726196..db88b5655aca 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -3697,206 +3697,116 @@ void fastcall complete_all(struct completion *x) | |||
3697 | } | 3697 | } |
3698 | EXPORT_SYMBOL(complete_all); | 3698 | EXPORT_SYMBOL(complete_all); |
3699 | 3699 | ||
3700 | void fastcall __sched wait_for_completion(struct completion *x) | 3700 | static inline long __sched |
3701 | do_wait_for_common(struct completion *x, long timeout, int state) | ||
3701 | { | 3702 | { |
3702 | might_sleep(); | ||
3703 | |||
3704 | spin_lock_irq(&x->wait.lock); | ||
3705 | if (!x->done) { | 3703 | if (!x->done) { |
3706 | DECLARE_WAITQUEUE(wait, current); | 3704 | DECLARE_WAITQUEUE(wait, current); |
3707 | 3705 | ||
3708 | wait.flags |= WQ_FLAG_EXCLUSIVE; | 3706 | wait.flags |= WQ_FLAG_EXCLUSIVE; |
3709 | __add_wait_queue_tail(&x->wait, &wait); | 3707 | __add_wait_queue_tail(&x->wait, &wait); |
3710 | do { | 3708 | do { |
3711 | __set_current_state(TASK_UNINTERRUPTIBLE); | 3709 | if (state == TASK_INTERRUPTIBLE && |
3712 | spin_unlock_irq(&x->wait.lock); | 3710 | signal_pending(current)) { |
3713 | schedule(); | 3711 | __remove_wait_queue(&x->wait, &wait); |
3714 | spin_lock_irq(&x->wait.lock); | 3712 | return -ERESTARTSYS; |
3715 | } while (!x->done); | 3713 | } |
3716 | __remove_wait_queue(&x->wait, &wait); | 3714 | __set_current_state(state); |
3717 | } | ||
3718 | x->done--; | ||
3719 | spin_unlock_irq(&x->wait.lock); | ||
3720 | } | ||
3721 | EXPORT_SYMBOL(wait_for_completion); | ||
3722 | |||
3723 | unsigned long fastcall __sched | ||
3724 | wait_for_completion_timeout(struct completion *x, unsigned long timeout) | ||
3725 | { | ||
3726 | might_sleep(); | ||
3727 | |||
3728 | spin_lock_irq(&x->wait.lock); | ||
3729 | if (!x->done) { | ||
3730 | DECLARE_WAITQUEUE(wait, current); | ||
3731 | |||
3732 | wait.flags |= WQ_FLAG_EXCLUSIVE; | ||
3733 | __add_wait_queue_tail(&x->wait, &wait); | ||
3734 | do { | ||
3735 | __set_current_state(TASK_UNINTERRUPTIBLE); | ||
3736 | spin_unlock_irq(&x->wait.lock); | 3715 | spin_unlock_irq(&x->wait.lock); |
3737 | timeout = schedule_timeout(timeout); | 3716 | timeout = schedule_timeout(timeout); |
3738 | spin_lock_irq(&x->wait.lock); | 3717 | spin_lock_irq(&x->wait.lock); |
3739 | if (!timeout) { | 3718 | if (!timeout) { |
3740 | __remove_wait_queue(&x->wait, &wait); | 3719 | __remove_wait_queue(&x->wait, &wait); |
3741 | goto out; | 3720 | return timeout; |
3742 | } | 3721 | } |
3743 | } while (!x->done); | 3722 | } while (!x->done); |
3744 | __remove_wait_queue(&x->wait, &wait); | 3723 | __remove_wait_queue(&x->wait, &wait); |
3745 | } | 3724 | } |
3746 | x->done--; | 3725 | x->done--; |
3747 | out: | ||
3748 | spin_unlock_irq(&x->wait.lock); | ||
3749 | return timeout; | 3726 | return timeout; |
3750 | } | 3727 | } |
3751 | EXPORT_SYMBOL(wait_for_completion_timeout); | ||
3752 | 3728 | ||
3753 | int fastcall __sched wait_for_completion_interruptible(struct completion *x) | 3729 | static long __sched |
3730 | wait_for_common(struct completion *x, long timeout, int state) | ||
3754 | { | 3731 | { |
3755 | int ret = 0; | ||
3756 | |||
3757 | might_sleep(); | 3732 | might_sleep(); |
3758 | 3733 | ||
3759 | spin_lock_irq(&x->wait.lock); | 3734 | spin_lock_irq(&x->wait.lock); |
3760 | if (!x->done) { | 3735 | timeout = do_wait_for_common(x, timeout, state); |
3761 | DECLARE_WAITQUEUE(wait, current); | ||
3762 | |||
3763 | wait.flags |= WQ_FLAG_EXCLUSIVE; | ||
3764 | __add_wait_queue_tail(&x->wait, &wait); | ||
3765 | do { | ||
3766 | if (signal_pending(current)) { | ||
3767 | ret = -ERESTARTSYS; | ||
3768 | __remove_wait_queue(&x->wait, &wait); | ||
3769 | goto out; | ||
3770 | } | ||
3771 | __set_current_state(TASK_INTERRUPTIBLE); | ||
3772 | spin_unlock_irq(&x->wait.lock); | ||
3773 | schedule(); | ||
3774 | spin_lock_irq(&x->wait.lock); | ||
3775 | } while (!x->done); | ||
3776 | __remove_wait_queue(&x->wait, &wait); | ||
3777 | } | ||
3778 | x->done--; | ||
3779 | out: | ||
3780 | spin_unlock_irq(&x->wait.lock); | 3736 | spin_unlock_irq(&x->wait.lock); |
3737 | return timeout; | ||
3738 | } | ||
3781 | 3739 | ||
3782 | return ret; | 3740 | void fastcall __sched wait_for_completion(struct completion *x) |
3741 | { | ||
3742 | wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); | ||
3783 | } | 3743 | } |
3784 | EXPORT_SYMBOL(wait_for_completion_interruptible); | 3744 | EXPORT_SYMBOL(wait_for_completion); |
3785 | 3745 | ||
3786 | unsigned long fastcall __sched | 3746 | unsigned long fastcall __sched |
3787 | wait_for_completion_interruptible_timeout(struct completion *x, | 3747 | wait_for_completion_timeout(struct completion *x, unsigned long timeout) |
3788 | unsigned long timeout) | ||
3789 | { | 3748 | { |
3790 | might_sleep(); | 3749 | return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE); |
3791 | |||
3792 | spin_lock_irq(&x->wait.lock); | ||
3793 | if (!x->done) { | ||
3794 | DECLARE_WAITQUEUE(wait, current); | ||
3795 | |||
3796 | wait.flags |= WQ_FLAG_EXCLUSIVE; | ||
3797 | __add_wait_queue_tail(&x->wait, &wait); | ||
3798 | do { | ||
3799 | if (signal_pending(current)) { | ||
3800 | timeout = -ERESTARTSYS; | ||
3801 | __remove_wait_queue(&x->wait, &wait); | ||
3802 | goto out; | ||
3803 | } | ||
3804 | __set_current_state(TASK_INTERRUPTIBLE); | ||
3805 | spin_unlock_irq(&x->wait.lock); | ||
3806 | timeout = schedule_timeout(timeout); | ||
3807 | spin_lock_irq(&x->wait.lock); | ||
3808 | if (!timeout) { | ||
3809 | __remove_wait_queue(&x->wait, &wait); | ||
3810 | goto out; | ||
3811 | } | ||
3812 | } while (!x->done); | ||
3813 | __remove_wait_queue(&x->wait, &wait); | ||
3814 | } | ||
3815 | x->done--; | ||
3816 | out: | ||
3817 | spin_unlock_irq(&x->wait.lock); | ||
3818 | return timeout; | ||
3819 | } | 3750 | } |
3820 | EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); | 3751 | EXPORT_SYMBOL(wait_for_completion_timeout); |
3821 | 3752 | ||
3822 | static inline void | 3753 | int __sched wait_for_completion_interruptible(struct completion *x) |
3823 | sleep_on_head(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags) | ||
3824 | { | 3754 | { |
3825 | spin_lock_irqsave(&q->lock, *flags); | 3755 | return wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); |
3826 | __add_wait_queue(q, wait); | ||
3827 | spin_unlock(&q->lock); | ||
3828 | } | 3756 | } |
3757 | EXPORT_SYMBOL(wait_for_completion_interruptible); | ||
3829 | 3758 | ||
3830 | static inline void | 3759 | unsigned long fastcall __sched |
3831 | sleep_on_tail(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags) | 3760 | wait_for_completion_interruptible_timeout(struct completion *x, |
3761 | unsigned long timeout) | ||
3832 | { | 3762 | { |
3833 | spin_lock_irq(&q->lock); | 3763 | return wait_for_common(x, timeout, TASK_INTERRUPTIBLE); |
3834 | __remove_wait_queue(q, wait); | ||
3835 | spin_unlock_irqrestore(&q->lock, *flags); | ||
3836 | } | 3764 | } |
3765 | EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); | ||
3837 | 3766 | ||
3838 | void __sched interruptible_sleep_on(wait_queue_head_t *q) | 3767 | static long __sched |
3768 | sleep_on_common(wait_queue_head_t *q, int state, long timeout) | ||
3839 | { | 3769 | { |
3840 | unsigned long flags; | 3770 | unsigned long flags; |
3841 | wait_queue_t wait; | 3771 | wait_queue_t wait; |
3842 | 3772 | ||
3843 | init_waitqueue_entry(&wait, current); | 3773 | init_waitqueue_entry(&wait, current); |
3844 | 3774 | ||
3845 | current->state = TASK_INTERRUPTIBLE; | 3775 | __set_current_state(state); |
3846 | 3776 | ||
3847 | sleep_on_head(q, &wait, &flags); | 3777 | spin_lock_irqsave(&q->lock, flags); |
3848 | schedule(); | 3778 | __add_wait_queue(q, &wait); |
3849 | sleep_on_tail(q, &wait, &flags); | 3779 | spin_unlock(&q->lock); |
3780 | timeout = schedule_timeout(timeout); | ||
3781 | spin_lock_irq(&q->lock); | ||
3782 | __remove_wait_queue(q, &wait); | ||
3783 | spin_unlock_irqrestore(&q->lock, flags); | ||
3784 | |||
3785 | return timeout; | ||
3786 | } | ||
3787 | |||
3788 | void __sched interruptible_sleep_on(wait_queue_head_t *q) | ||
3789 | { | ||
3790 | sleep_on_common(q, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); | ||
3850 | } | 3791 | } |
3851 | EXPORT_SYMBOL(interruptible_sleep_on); | 3792 | EXPORT_SYMBOL(interruptible_sleep_on); |
3852 | 3793 | ||
3853 | long __sched | 3794 | long __sched |
3854 | interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) | 3795 | interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) |
3855 | { | 3796 | { |
3856 | unsigned long flags; | 3797 | return sleep_on_common(q, TASK_INTERRUPTIBLE, timeout); |
3857 | wait_queue_t wait; | ||
3858 | |||
3859 | init_waitqueue_entry(&wait, current); | ||
3860 | |||
3861 | current->state = TASK_INTERRUPTIBLE; | ||
3862 | |||
3863 | sleep_on_head(q, &wait, &flags); | ||
3864 | timeout = schedule_timeout(timeout); | ||
3865 | sleep_on_tail(q, &wait, &flags); | ||
3866 | |||
3867 | return timeout; | ||
3868 | } | 3798 | } |
3869 | EXPORT_SYMBOL(interruptible_sleep_on_timeout); | 3799 | EXPORT_SYMBOL(interruptible_sleep_on_timeout); |
3870 | 3800 | ||
3871 | void __sched sleep_on(wait_queue_head_t *q) | 3801 | void __sched sleep_on(wait_queue_head_t *q) |
3872 | { | 3802 | { |
3873 | unsigned long flags; | 3803 | sleep_on_common(q, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); |
3874 | wait_queue_t wait; | ||
3875 | |||
3876 | init_waitqueue_entry(&wait, current); | ||
3877 | |||
3878 | current->state = TASK_UNINTERRUPTIBLE; | ||
3879 | |||
3880 | sleep_on_head(q, &wait, &flags); | ||
3881 | schedule(); | ||
3882 | sleep_on_tail(q, &wait, &flags); | ||
3883 | } | 3804 | } |
3884 | EXPORT_SYMBOL(sleep_on); | 3805 | EXPORT_SYMBOL(sleep_on); |
3885 | 3806 | ||
3886 | long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout) | 3807 | long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout) |
3887 | { | 3808 | { |
3888 | unsigned long flags; | 3809 | return sleep_on_common(q, TASK_UNINTERRUPTIBLE, timeout); |
3889 | wait_queue_t wait; | ||
3890 | |||
3891 | init_waitqueue_entry(&wait, current); | ||
3892 | |||
3893 | current->state = TASK_UNINTERRUPTIBLE; | ||
3894 | |||
3895 | sleep_on_head(q, &wait, &flags); | ||
3896 | timeout = schedule_timeout(timeout); | ||
3897 | sleep_on_tail(q, &wait, &flags); | ||
3898 | |||
3899 | return timeout; | ||
3900 | } | 3810 | } |
3901 | EXPORT_SYMBOL(sleep_on_timeout); | 3811 | EXPORT_SYMBOL(sleep_on_timeout); |
3902 | 3812 | ||