diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2017-05-30 17:15:50 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2017-06-04 09:40:27 -0400 |
commit | 91d57bae08689199c8acc77a8b3b41150cafab1c (patch) | |
tree | 31db8b4a4554fcc51fbdb947a9ad30ce18071818 | |
parent | 63841b2a6969501de183efafc14d20175e402804 (diff) |
posix-timers: Make use of forward/remaining callbacks
Replace the hrtimer calls by calls to the new forward/remaining kclock
callbacks and move the hrtimer specific implementation into the
corresponding callback functions.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: John Stultz <john.stultz@linaro.org>
Link: http://lkml.kernel.org/r/20170530211657.121437232@linutronix.de
-rw-r--r-- | kernel/time/posix-timers.c | 64 |
1 files changed, 49 insertions, 15 deletions
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c index 795215bba73d..48f6c37ae5df 100644 --- a/kernel/time/posix-timers.c +++ b/kernel/time/posix-timers.c | |||
@@ -607,6 +607,20 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) | |||
607 | return NULL; | 607 | return NULL; |
608 | } | 608 | } |
609 | 609 | ||
610 | static ktime_t common_hrtimer_remaining(struct k_itimer *timr, ktime_t now) | ||
611 | { | ||
612 | struct hrtimer *timer = &timr->it.real.timer; | ||
613 | |||
614 | return __hrtimer_expires_remaining_adjusted(timer, now); | ||
615 | } | ||
616 | |||
617 | static int common_hrtimer_forward(struct k_itimer *timr, ktime_t now) | ||
618 | { | ||
619 | struct hrtimer *timer = &timr->it.real.timer; | ||
620 | |||
621 | return (int)hrtimer_forward(timer, now, timr->it_interval); | ||
622 | } | ||
623 | |||
610 | /* | 624 | /* |
611 | * Get the time remaining on a POSIX.1b interval timer. This function | 625 | * Get the time remaining on a POSIX.1b interval timer. This function |
612 | * is ALWAYS called with spin_lock_irq on the timer, thus it must not | 626 | * is ALWAYS called with spin_lock_irq on the timer, thus it must not |
@@ -626,42 +640,54 @@ static struct k_itimer *__lock_timer(timer_t timer_id, unsigned long *flags) | |||
626 | static void | 640 | static void |
627 | common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) | 641 | common_timer_get(struct k_itimer *timr, struct itimerspec64 *cur_setting) |
628 | { | 642 | { |
643 | const struct k_clock *kc = timr->kclock; | ||
629 | ktime_t now, remaining, iv; | 644 | ktime_t now, remaining, iv; |
630 | struct hrtimer *timer = &timr->it.real.timer; | 645 | struct timespec64 ts64; |
646 | bool sig_none; | ||
631 | 647 | ||
632 | memset(cur_setting, 0, sizeof(*cur_setting)); | 648 | memset(cur_setting, 0, sizeof(*cur_setting)); |
633 | 649 | ||
650 | sig_none = (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE; | ||
634 | iv = timr->it_interval; | 651 | iv = timr->it_interval; |
635 | 652 | ||
636 | /* interval timer ? */ | 653 | /* interval timer ? */ |
637 | if (iv) | 654 | if (iv) { |
638 | cur_setting->it_interval = ktime_to_timespec64(iv); | 655 | cur_setting->it_interval = ktime_to_timespec64(iv); |
639 | else if (!hrtimer_active(timer) && | 656 | } else if (!timr->it_active) { |
640 | (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) | 657 | /* |
641 | return; | 658 | * SIGEV_NONE oneshot timers are never queued. Check them |
659 | * below. | ||
660 | */ | ||
661 | if (!sig_none) | ||
662 | return; | ||
663 | } | ||
642 | 664 | ||
643 | now = timer->base->get_time(); | 665 | /* |
666 | * The timespec64 based conversion is suboptimal, but it's not | ||
667 | * worth to implement yet another callback. | ||
668 | */ | ||
669 | kc->clock_get(timr->it_clock, &ts64); | ||
670 | now = timespec64_to_ktime(ts64); | ||
644 | 671 | ||
645 | /* | 672 | /* |
646 | * When a requeue is pending or this is a SIGEV_NONE | 673 | * When a requeue is pending or this is a SIGEV_NONE timer move the |
647 | * timer move the expiry time forward by intervals, so | 674 | * expiry time forward by intervals, so expiry is > now. |
648 | * expiry is > now. | ||
649 | */ | 675 | */ |
650 | if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || | 676 | if (iv && (timr->it_requeue_pending & REQUEUE_PENDING || sig_none)) |
651 | (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) | 677 | timr->it_overrun += kc->timer_forward(timr, now); |
652 | timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv); | ||
653 | 678 | ||
654 | remaining = __hrtimer_expires_remaining_adjusted(timer, now); | 679 | remaining = kc->timer_remaining(timr, now); |
655 | /* Return 0 only, when the timer is expired and not pending */ | 680 | /* Return 0 only, when the timer is expired and not pending */ |
656 | if (remaining <= 0) { | 681 | if (remaining <= 0) { |
657 | /* | 682 | /* |
658 | * A single shot SIGEV_NONE timer must return 0, when | 683 | * A single shot SIGEV_NONE timer must return 0, when |
659 | * it is expired ! | 684 | * it is expired ! |
660 | */ | 685 | */ |
661 | if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) | 686 | if (!sig_none) |
662 | cur_setting->it_value.tv_nsec = 1; | 687 | cur_setting->it_value.tv_nsec = 1; |
663 | } else | 688 | } else { |
664 | cur_setting->it_value = ktime_to_timespec64(remaining); | 689 | cur_setting->it_value = ktime_to_timespec64(remaining); |
690 | } | ||
665 | } | 691 | } |
666 | 692 | ||
667 | /* Get the time remaining on a POSIX.1b interval timer. */ | 693 | /* Get the time remaining on a POSIX.1b interval timer. */ |
@@ -1049,6 +1075,8 @@ static const struct k_clock clock_realtime = { | |||
1049 | .timer_get = common_timer_get, | 1075 | .timer_get = common_timer_get, |
1050 | .timer_del = common_timer_del, | 1076 | .timer_del = common_timer_del, |
1051 | .timer_rearm = common_hrtimer_rearm, | 1077 | .timer_rearm = common_hrtimer_rearm, |
1078 | .timer_forward = common_hrtimer_forward, | ||
1079 | .timer_remaining= common_hrtimer_remaining, | ||
1052 | }; | 1080 | }; |
1053 | 1081 | ||
1054 | static const struct k_clock clock_monotonic = { | 1082 | static const struct k_clock clock_monotonic = { |
@@ -1061,6 +1089,8 @@ static const struct k_clock clock_monotonic = { | |||
1061 | .timer_get = common_timer_get, | 1089 | .timer_get = common_timer_get, |
1062 | .timer_del = common_timer_del, | 1090 | .timer_del = common_timer_del, |
1063 | .timer_rearm = common_hrtimer_rearm, | 1091 | .timer_rearm = common_hrtimer_rearm, |
1092 | .timer_forward = common_hrtimer_forward, | ||
1093 | .timer_remaining= common_hrtimer_remaining, | ||
1064 | }; | 1094 | }; |
1065 | 1095 | ||
1066 | static const struct k_clock clock_monotonic_raw = { | 1096 | static const struct k_clock clock_monotonic_raw = { |
@@ -1088,6 +1118,8 @@ static const struct k_clock clock_tai = { | |||
1088 | .timer_get = common_timer_get, | 1118 | .timer_get = common_timer_get, |
1089 | .timer_del = common_timer_del, | 1119 | .timer_del = common_timer_del, |
1090 | .timer_rearm = common_hrtimer_rearm, | 1120 | .timer_rearm = common_hrtimer_rearm, |
1121 | .timer_forward = common_hrtimer_forward, | ||
1122 | .timer_remaining= common_hrtimer_remaining, | ||
1091 | }; | 1123 | }; |
1092 | 1124 | ||
1093 | static const struct k_clock clock_boottime = { | 1125 | static const struct k_clock clock_boottime = { |
@@ -1100,6 +1132,8 @@ static const struct k_clock clock_boottime = { | |||
1100 | .timer_get = common_timer_get, | 1132 | .timer_get = common_timer_get, |
1101 | .timer_del = common_timer_del, | 1133 | .timer_del = common_timer_del, |
1102 | .timer_rearm = common_hrtimer_rearm, | 1134 | .timer_rearm = common_hrtimer_rearm, |
1135 | .timer_forward = common_hrtimer_forward, | ||
1136 | .timer_remaining= common_hrtimer_remaining, | ||
1103 | }; | 1137 | }; |
1104 | 1138 | ||
1105 | static const struct k_clock * const posix_clocks[] = { | 1139 | static const struct k_clock * const posix_clocks[] = { |