diff options
Diffstat (limited to 'kernel/hrtimer.c')
-rw-r--r-- | kernel/hrtimer.c | 193 |
1 files changed, 96 insertions, 97 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index 14bc9cfa6399..0237a556eb1f 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -123,6 +123,26 @@ void ktime_get_ts(struct timespec *ts) | |||
123 | EXPORT_SYMBOL_GPL(ktime_get_ts); | 123 | EXPORT_SYMBOL_GPL(ktime_get_ts); |
124 | 124 | ||
125 | /* | 125 | /* |
126 | * Get the coarse grained time at the softirq based on xtime and | ||
127 | * wall_to_monotonic. | ||
128 | */ | ||
129 | static void hrtimer_get_softirq_time(struct hrtimer_base *base) | ||
130 | { | ||
131 | ktime_t xtim, tomono; | ||
132 | unsigned long seq; | ||
133 | |||
134 | do { | ||
135 | seq = read_seqbegin(&xtime_lock); | ||
136 | xtim = timespec_to_ktime(xtime); | ||
137 | tomono = timespec_to_ktime(wall_to_monotonic); | ||
138 | |||
139 | } while (read_seqretry(&xtime_lock, seq)); | ||
140 | |||
141 | base[CLOCK_REALTIME].softirq_time = xtim; | ||
142 | base[CLOCK_MONOTONIC].softirq_time = ktime_add(xtim, tomono); | ||
143 | } | ||
144 | |||
145 | /* | ||
126 | * Functions and macros which are different for UP/SMP systems are kept in a | 146 | * Functions and macros which are different for UP/SMP systems are kept in a |
127 | * single place | 147 | * single place |
128 | */ | 148 | */ |
@@ -246,7 +266,7 @@ ktime_t ktime_add_ns(const ktime_t kt, u64 nsec) | |||
246 | /* | 266 | /* |
247 | * Divide a ktime value by a nanosecond value | 267 | * Divide a ktime value by a nanosecond value |
248 | */ | 268 | */ |
249 | static unsigned long ktime_divns(const ktime_t kt, nsec_t div) | 269 | static unsigned long ktime_divns(const ktime_t kt, s64 div) |
250 | { | 270 | { |
251 | u64 dclc, inc, dns; | 271 | u64 dclc, inc, dns; |
252 | int sft = 0; | 272 | int sft = 0; |
@@ -281,18 +301,17 @@ void unlock_hrtimer_base(const struct hrtimer *timer, unsigned long *flags) | |||
281 | * hrtimer_forward - forward the timer expiry | 301 | * hrtimer_forward - forward the timer expiry |
282 | * | 302 | * |
283 | * @timer: hrtimer to forward | 303 | * @timer: hrtimer to forward |
304 | * @now: forward past this time | ||
284 | * @interval: the interval to forward | 305 | * @interval: the interval to forward |
285 | * | 306 | * |
286 | * Forward the timer expiry so it will expire in the future. | 307 | * Forward the timer expiry so it will expire in the future. |
287 | * Returns the number of overruns. | 308 | * Returns the number of overruns. |
288 | */ | 309 | */ |
289 | unsigned long | 310 | unsigned long |
290 | hrtimer_forward(struct hrtimer *timer, ktime_t interval) | 311 | hrtimer_forward(struct hrtimer *timer, ktime_t now, ktime_t interval) |
291 | { | 312 | { |
292 | unsigned long orun = 1; | 313 | unsigned long orun = 1; |
293 | ktime_t delta, now; | 314 | ktime_t delta; |
294 | |||
295 | now = timer->base->get_time(); | ||
296 | 315 | ||
297 | delta = ktime_sub(now, timer->expires); | 316 | delta = ktime_sub(now, timer->expires); |
298 | 317 | ||
@@ -303,7 +322,7 @@ hrtimer_forward(struct hrtimer *timer, ktime_t interval) | |||
303 | interval.tv64 = timer->base->resolution.tv64; | 322 | interval.tv64 = timer->base->resolution.tv64; |
304 | 323 | ||
305 | if (unlikely(delta.tv64 >= interval.tv64)) { | 324 | if (unlikely(delta.tv64 >= interval.tv64)) { |
306 | nsec_t incr = ktime_to_ns(interval); | 325 | s64 incr = ktime_to_ns(interval); |
307 | 326 | ||
308 | orun = ktime_divns(delta, incr); | 327 | orun = ktime_divns(delta, incr); |
309 | timer->expires = ktime_add_ns(timer->expires, incr * orun); | 328 | timer->expires = ktime_add_ns(timer->expires, incr * orun); |
@@ -355,8 +374,6 @@ static void enqueue_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) | |||
355 | rb_link_node(&timer->node, parent, link); | 374 | rb_link_node(&timer->node, parent, link); |
356 | rb_insert_color(&timer->node, &base->active); | 375 | rb_insert_color(&timer->node, &base->active); |
357 | 376 | ||
358 | timer->state = HRTIMER_PENDING; | ||
359 | |||
360 | if (!base->first || timer->expires.tv64 < | 377 | if (!base->first || timer->expires.tv64 < |
361 | rb_entry(base->first, struct hrtimer, node)->expires.tv64) | 378 | rb_entry(base->first, struct hrtimer, node)->expires.tv64) |
362 | base->first = &timer->node; | 379 | base->first = &timer->node; |
@@ -376,6 +393,7 @@ static void __remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) | |||
376 | if (base->first == &timer->node) | 393 | if (base->first == &timer->node) |
377 | base->first = rb_next(&timer->node); | 394 | base->first = rb_next(&timer->node); |
378 | rb_erase(&timer->node, &base->active); | 395 | rb_erase(&timer->node, &base->active); |
396 | timer->node.rb_parent = HRTIMER_INACTIVE; | ||
379 | } | 397 | } |
380 | 398 | ||
381 | /* | 399 | /* |
@@ -386,7 +404,6 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_base *base) | |||
386 | { | 404 | { |
387 | if (hrtimer_active(timer)) { | 405 | if (hrtimer_active(timer)) { |
388 | __remove_hrtimer(timer, base); | 406 | __remove_hrtimer(timer, base); |
389 | timer->state = HRTIMER_INACTIVE; | ||
390 | return 1; | 407 | return 1; |
391 | } | 408 | } |
392 | return 0; | 409 | return 0; |
@@ -560,6 +577,7 @@ void hrtimer_init(struct hrtimer *timer, clockid_t clock_id, | |||
560 | clock_id = CLOCK_MONOTONIC; | 577 | clock_id = CLOCK_MONOTONIC; |
561 | 578 | ||
562 | timer->base = &bases[clock_id]; | 579 | timer->base = &bases[clock_id]; |
580 | timer->node.rb_parent = HRTIMER_INACTIVE; | ||
563 | } | 581 | } |
564 | 582 | ||
565 | /** | 583 | /** |
@@ -586,48 +604,35 @@ int hrtimer_get_res(const clockid_t which_clock, struct timespec *tp) | |||
586 | */ | 604 | */ |
587 | static inline void run_hrtimer_queue(struct hrtimer_base *base) | 605 | static inline void run_hrtimer_queue(struct hrtimer_base *base) |
588 | { | 606 | { |
589 | ktime_t now = base->get_time(); | ||
590 | struct rb_node *node; | 607 | struct rb_node *node; |
591 | 608 | ||
609 | if (base->get_softirq_time) | ||
610 | base->softirq_time = base->get_softirq_time(); | ||
611 | |||
592 | spin_lock_irq(&base->lock); | 612 | spin_lock_irq(&base->lock); |
593 | 613 | ||
594 | while ((node = base->first)) { | 614 | while ((node = base->first)) { |
595 | struct hrtimer *timer; | 615 | struct hrtimer *timer; |
596 | int (*fn)(void *); | 616 | int (*fn)(struct hrtimer *); |
597 | int restart; | 617 | int restart; |
598 | void *data; | ||
599 | 618 | ||
600 | timer = rb_entry(node, struct hrtimer, node); | 619 | timer = rb_entry(node, struct hrtimer, node); |
601 | if (now.tv64 <= timer->expires.tv64) | 620 | if (base->softirq_time.tv64 <= timer->expires.tv64) |
602 | break; | 621 | break; |
603 | 622 | ||
604 | fn = timer->function; | 623 | fn = timer->function; |
605 | data = timer->data; | ||
606 | set_curr_timer(base, timer); | 624 | set_curr_timer(base, timer); |
607 | timer->state = HRTIMER_RUNNING; | ||
608 | __remove_hrtimer(timer, base); | 625 | __remove_hrtimer(timer, base); |
609 | spin_unlock_irq(&base->lock); | 626 | spin_unlock_irq(&base->lock); |
610 | 627 | ||
611 | /* | 628 | restart = fn(timer); |
612 | * fn == NULL is special case for the simplest timer | ||
613 | * variant - wake up process and do not restart: | ||
614 | */ | ||
615 | if (!fn) { | ||
616 | wake_up_process(data); | ||
617 | restart = HRTIMER_NORESTART; | ||
618 | } else | ||
619 | restart = fn(data); | ||
620 | 629 | ||
621 | spin_lock_irq(&base->lock); | 630 | spin_lock_irq(&base->lock); |
622 | 631 | ||
623 | /* Another CPU has added back the timer */ | 632 | if (restart != HRTIMER_NORESTART) { |
624 | if (timer->state != HRTIMER_RUNNING) | 633 | BUG_ON(hrtimer_active(timer)); |
625 | continue; | ||
626 | |||
627 | if (restart == HRTIMER_RESTART) | ||
628 | enqueue_hrtimer(timer, base); | 634 | enqueue_hrtimer(timer, base); |
629 | else | 635 | } |
630 | timer->state = HRTIMER_EXPIRED; | ||
631 | } | 636 | } |
632 | set_curr_timer(base, NULL); | 637 | set_curr_timer(base, NULL); |
633 | spin_unlock_irq(&base->lock); | 638 | spin_unlock_irq(&base->lock); |
@@ -641,6 +646,8 @@ void hrtimer_run_queues(void) | |||
641 | struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); | 646 | struct hrtimer_base *base = __get_cpu_var(hrtimer_bases); |
642 | int i; | 647 | int i; |
643 | 648 | ||
649 | hrtimer_get_softirq_time(base); | ||
650 | |||
644 | for (i = 0; i < MAX_HRTIMER_BASES; i++) | 651 | for (i = 0; i < MAX_HRTIMER_BASES; i++) |
645 | run_hrtimer_queue(&base[i]); | 652 | run_hrtimer_queue(&base[i]); |
646 | } | 653 | } |
@@ -649,79 +656,70 @@ void hrtimer_run_queues(void) | |||
649 | * Sleep related functions: | 656 | * Sleep related functions: |
650 | */ | 657 | */ |
651 | 658 | ||
652 | /** | 659 | struct sleep_hrtimer { |
653 | * schedule_hrtimer - sleep until timeout | 660 | struct hrtimer timer; |
654 | * | 661 | struct task_struct *task; |
655 | * @timer: hrtimer variable initialized with the correct clock base | 662 | int expired; |
656 | * @mode: timeout value is abs/rel | 663 | }; |
657 | * | ||
658 | * Make the current task sleep until @timeout is | ||
659 | * elapsed. | ||
660 | * | ||
661 | * You can set the task state as follows - | ||
662 | * | ||
663 | * %TASK_UNINTERRUPTIBLE - at least @timeout is guaranteed to | ||
664 | * pass before the routine returns. The routine will return 0 | ||
665 | * | ||
666 | * %TASK_INTERRUPTIBLE - the routine may return early if a signal is | ||
667 | * delivered to the current task. In this case the remaining time | ||
668 | * will be returned | ||
669 | * | ||
670 | * The current task state is guaranteed to be TASK_RUNNING when this | ||
671 | * routine returns. | ||
672 | */ | ||
673 | static ktime_t __sched | ||
674 | schedule_hrtimer(struct hrtimer *timer, const enum hrtimer_mode mode) | ||
675 | { | ||
676 | /* fn stays NULL, meaning single-shot wakeup: */ | ||
677 | timer->data = current; | ||
678 | 664 | ||
679 | hrtimer_start(timer, timer->expires, mode); | 665 | static int nanosleep_wakeup(struct hrtimer *timer) |
666 | { | ||
667 | struct sleep_hrtimer *t = | ||
668 | container_of(timer, struct sleep_hrtimer, timer); | ||
680 | 669 | ||
681 | schedule(); | 670 | t->expired = 1; |
682 | hrtimer_cancel(timer); | 671 | wake_up_process(t->task); |
683 | 672 | ||
684 | /* Return the remaining time: */ | 673 | return HRTIMER_NORESTART; |
685 | if (timer->state != HRTIMER_EXPIRED) | ||
686 | return ktime_sub(timer->expires, timer->base->get_time()); | ||
687 | else | ||
688 | return (ktime_t) {.tv64 = 0 }; | ||
689 | } | 674 | } |
690 | 675 | ||
691 | static inline ktime_t __sched | 676 | static int __sched do_nanosleep(struct sleep_hrtimer *t, enum hrtimer_mode mode) |
692 | schedule_hrtimer_interruptible(struct hrtimer *timer, | ||
693 | const enum hrtimer_mode mode) | ||
694 | { | 677 | { |
695 | set_current_state(TASK_INTERRUPTIBLE); | 678 | t->timer.function = nanosleep_wakeup; |
679 | t->task = current; | ||
680 | t->expired = 0; | ||
681 | |||
682 | do { | ||
683 | set_current_state(TASK_INTERRUPTIBLE); | ||
684 | hrtimer_start(&t->timer, t->timer.expires, mode); | ||
685 | |||
686 | schedule(); | ||
687 | |||
688 | if (unlikely(!t->expired)) { | ||
689 | hrtimer_cancel(&t->timer); | ||
690 | mode = HRTIMER_ABS; | ||
691 | } | ||
692 | } while (!t->expired && !signal_pending(current)); | ||
696 | 693 | ||
697 | return schedule_hrtimer(timer, mode); | 694 | return t->expired; |
698 | } | 695 | } |
699 | 696 | ||
700 | static long __sched nanosleep_restart(struct restart_block *restart) | 697 | static long __sched nanosleep_restart(struct restart_block *restart) |
701 | { | 698 | { |
699 | struct sleep_hrtimer t; | ||
702 | struct timespec __user *rmtp; | 700 | struct timespec __user *rmtp; |
703 | struct timespec tu; | 701 | struct timespec tu; |
704 | void *rfn_save = restart->fn; | 702 | ktime_t time; |
705 | struct hrtimer timer; | ||
706 | ktime_t rem; | ||
707 | 703 | ||
708 | restart->fn = do_no_restart_syscall; | 704 | restart->fn = do_no_restart_syscall; |
709 | 705 | ||
710 | hrtimer_init(&timer, (clockid_t) restart->arg3, HRTIMER_ABS); | 706 | hrtimer_init(&t.timer, restart->arg3, HRTIMER_ABS); |
711 | 707 | t.timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; | |
712 | timer.expires.tv64 = ((u64)restart->arg1 << 32) | (u64) restart->arg0; | ||
713 | |||
714 | rem = schedule_hrtimer_interruptible(&timer, HRTIMER_ABS); | ||
715 | 708 | ||
716 | if (rem.tv64 <= 0) | 709 | if (do_nanosleep(&t, HRTIMER_ABS)) |
717 | return 0; | 710 | return 0; |
718 | 711 | ||
719 | rmtp = (struct timespec __user *) restart->arg2; | 712 | rmtp = (struct timespec __user *) restart->arg2; |
720 | tu = ktime_to_timespec(rem); | 713 | if (rmtp) { |
721 | if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu))) | 714 | time = ktime_sub(t.timer.expires, t.timer.base->get_time()); |
722 | return -EFAULT; | 715 | if (time.tv64 <= 0) |
716 | return 0; | ||
717 | tu = ktime_to_timespec(time); | ||
718 | if (copy_to_user(rmtp, &tu, sizeof(tu))) | ||
719 | return -EFAULT; | ||
720 | } | ||
723 | 721 | ||
724 | restart->fn = rfn_save; | 722 | restart->fn = nanosleep_restart; |
725 | 723 | ||
726 | /* The other values in restart are already filled in */ | 724 | /* The other values in restart are already filled in */ |
727 | return -ERESTART_RESTARTBLOCK; | 725 | return -ERESTART_RESTARTBLOCK; |
@@ -731,33 +729,34 @@ long hrtimer_nanosleep(struct timespec *rqtp, struct timespec __user *rmtp, | |||
731 | const enum hrtimer_mode mode, const clockid_t clockid) | 729 | const enum hrtimer_mode mode, const clockid_t clockid) |
732 | { | 730 | { |
733 | struct restart_block *restart; | 731 | struct restart_block *restart; |
734 | struct hrtimer timer; | 732 | struct sleep_hrtimer t; |
735 | struct timespec tu; | 733 | struct timespec tu; |
736 | ktime_t rem; | 734 | ktime_t rem; |
737 | 735 | ||
738 | hrtimer_init(&timer, clockid, mode); | 736 | hrtimer_init(&t.timer, clockid, mode); |
739 | 737 | t.timer.expires = timespec_to_ktime(*rqtp); | |
740 | timer.expires = timespec_to_ktime(*rqtp); | 738 | if (do_nanosleep(&t, mode)) |
741 | |||
742 | rem = schedule_hrtimer_interruptible(&timer, mode); | ||
743 | if (rem.tv64 <= 0) | ||
744 | return 0; | 739 | return 0; |
745 | 740 | ||
746 | /* Absolute timers do not update the rmtp value and restart: */ | 741 | /* Absolute timers do not update the rmtp value and restart: */ |
747 | if (mode == HRTIMER_ABS) | 742 | if (mode == HRTIMER_ABS) |
748 | return -ERESTARTNOHAND; | 743 | return -ERESTARTNOHAND; |
749 | 744 | ||
750 | tu = ktime_to_timespec(rem); | 745 | if (rmtp) { |
751 | 746 | rem = ktime_sub(t.timer.expires, t.timer.base->get_time()); | |
752 | if (rmtp && copy_to_user(rmtp, &tu, sizeof(tu))) | 747 | if (rem.tv64 <= 0) |
753 | return -EFAULT; | 748 | return 0; |
749 | tu = ktime_to_timespec(rem); | ||
750 | if (copy_to_user(rmtp, &tu, sizeof(tu))) | ||
751 | return -EFAULT; | ||
752 | } | ||
754 | 753 | ||
755 | restart = ¤t_thread_info()->restart_block; | 754 | restart = ¤t_thread_info()->restart_block; |
756 | restart->fn = nanosleep_restart; | 755 | restart->fn = nanosleep_restart; |
757 | restart->arg0 = timer.expires.tv64 & 0xFFFFFFFF; | 756 | restart->arg0 = t.timer.expires.tv64 & 0xFFFFFFFF; |
758 | restart->arg1 = timer.expires.tv64 >> 32; | 757 | restart->arg1 = t.timer.expires.tv64 >> 32; |
759 | restart->arg2 = (unsigned long) rmtp; | 758 | restart->arg2 = (unsigned long) rmtp; |
760 | restart->arg3 = (unsigned long) timer.base->index; | 759 | restart->arg3 = (unsigned long) t.timer.base->index; |
761 | 760 | ||
762 | return -ERESTART_RESTARTBLOCK; | 761 | return -ERESTART_RESTARTBLOCK; |
763 | } | 762 | } |