diff options
Diffstat (limited to 'kernel/hrtimer.c')
| -rw-r--r-- | kernel/hrtimer.c | 49 |
1 files changed, 25 insertions, 24 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 0237a556eb1f..f181ff4dd32e 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
| @@ -606,6 +606,9 @@ static inline void run_hrtimer_queue(struct hrtimer_base *base) | |||
| 606 | { | 606 | { |
| 607 | struct rb_node *node; | 607 | struct rb_node *node; |
| 608 | 608 | ||
| 609 | if (!base->first) | ||
| 610 | return; | ||
| 611 | |||
| 609 | if (base->get_softirq_time) | 612 | if (base->get_softirq_time) |
| 610 | base->softirq_time = base->get_softirq_time(); | 613 | base->softirq_time = base->get_softirq_time(); |
| 611 | 614 | ||
| @@ -655,29 +658,28 @@ void hrtimer_run_queues(void) | |||
| 655 | /* | 658 | /* |
| 656 | * Sleep related functions: | 659 | * Sleep related functions: |
| 657 | */ | 660 | */ |
| 658 | 661 | static int hrtimer_wakeup(struct hrtimer *timer) | |
| 659 | struct sleep_hrtimer { | ||
| 660 | struct hrtimer timer; | ||
| 661 | struct task_struct *task; | ||
| 662 | int expired; | ||
| 663 | }; | ||
| 664 | |||
| 665 | static int nanosleep_wakeup(struct hrtimer *timer) | ||
| 666 | { | 662 | { |
| 667 | struct sleep_hrtimer *t = | 663 | struct hrtimer_sleeper *t = |
| 668 | container_of(timer, struct sleep_hrtimer, timer); | 664 | container_of(timer, struct hrtimer_sleeper, timer); |
| 665 | struct task_struct *task = t->task; | ||
| 669 | 666 | ||
| 670 | t->expired = 1; | 667 | t->task = NULL; |
| 671 | wake_up_process(t->task); | 668 | if (task) |
| 669 | wake_up_process(task); | ||
| 672 | 670 | ||
| 673 | return HRTIMER_NORESTART; | 671 | return HRTIMER_NORESTART; |
| 674 | } | 672 | } |
| 675 | 673 | ||
| 676 | static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode) | 674 | void hrtimer_init_sleeper(struct hrtimer_sleeper *sl, task_t *task) |
| 677 | { | 675 | { |
| 678 | t->timer.function = nanosleep_wakeup; | 676 | sl->timer.function = hrtimer_wakeup; |
| 679 | t->task = current; | 677 | sl->task = task; |
| 680 | t->expired = 0; | 678 | } |
| 679 | |||
| 680 | static int __sched do_nanosleep(struct hrtimer_sleeper *t, enum hrtimer_mode mode) | ||
| 681 | { | ||
| 682 | hrtimer_init_sleeper(t, current); | ||
| 681 | 683 | ||
| 682 | do { | 684 | do { |
| 683 | set_current_state(TASK_INTERRUPTIBLE); | 685 | set_current_state(TASK_INTERRUPTIBLE); |
| @@ -685,18 +687,17 @@ static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode) | |||
| 685 | 687 | ||
| 686 | schedule(); | 688 | schedule(); |
| 687 | 689 | ||
| 688 | if (unlikely(!t->expired)) { | 690 | hrtimer_cancel(&t->timer); |
| 689 | hrtimer_cancel(&t->timer); | 691 | mode = HRTIMER_ABS; |
| 690 | mode = HRTIMER_ABS; | 692 | |
| 691 | } | 693 | } while (t->task && !signal_pending(current)); |
| 692 | } while (!t->expired && !signal_pending(current)); | ||
| 693 | 694 | ||
| 694 | return t->expired; | 695 | return t->task == NULL; |
| 695 | } | 696 | } |
| 696 | 697 | ||
| 697 | static long __sched nanosleep_restart(struct restart_block *restart) | 698 | static long __sched nanosleep_restart(struct restart_block *restart) |
| 698 | { | 699 | { |
| 699 | struct sleep_hrtimer t; | 700 | struct hrtimer_sleeper t; |
| 700 | struct timespec __user *rmtp; | 701 | struct timespec __user *rmtp; |
| 701 | struct timespec tu; | 702 | struct timespec tu; |
| 702 | ktime_t time; | 703 | ktime_t time; |
| @@ -729,7 +730,7 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
| 729 | const enum hrtimer_mode mode, const clockid_t clockid) | 730 | const enum hrtimer_mode mode, const clockid_t clockid) |
| 730 | { | 731 | { |
| 731 | struct restart_block *restart; | 732 | struct restart_block *restart; |
| 732 | struct sleep_hrtimer t; | 733 | struct hrtimer_sleeper t; |
| 733 | struct timespec tu; | 734 | struct timespec tu; |
| 734 | ktime_t rem; | 735 | ktime_t rem; |
| 735 | 736 | ||
