diff options
author | Thomas Gleixner <tglx@linutronix.de> | 2011-05-02 10:48:57 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2011-05-02 15:37:58 -0400 |
commit | b12a03ce4880bd13786a98db6de494a3e0123129 (patch) | |
tree | 2a8f2cf0d1d6749b4a33cc07c9b7839a4a139e9a /kernel | |
parent | 942c3c5c329274fa6de5998cb911cf3d0a42d0b1 (diff) |
hrtimers: Prepare for cancel on clock was set timers
Make clock_was_set() unconditional and rename hres_timers_resume to
hrtimers_resume. This is a preparatory patch for hrtimers which are
cancelled when clock realtime was set.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/hrtimer.c | 125 | ||||
-rw-r--r-- | kernel/time/timekeeping.c | 2 |
2 files changed, 62 insertions, 65 deletions
diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index dbbbf7d43080..c145ed643bca 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c | |||
@@ -621,66 +621,6 @@ static int hrtimer_reprogram(struct hrtimer *timer, | |||
621 | return res; | 621 | return res; |
622 | } | 622 | } |
623 | 623 | ||
624 | |||
625 | /* | ||
626 | * Retrigger next event is called after clock was set | ||
627 | * | ||
628 | * Called with interrupts disabled via on_each_cpu() | ||
629 | */ | ||
630 | static void retrigger_next_event(void *arg) | ||
631 | { | ||
632 | struct hrtimer_cpu_base *base; | ||
633 | struct timespec realtime_offset, wtm, sleep; | ||
634 | |||
635 | if (!hrtimer_hres_active()) | ||
636 | return; | ||
637 | |||
638 | get_xtime_and_monotonic_and_sleep_offset(&realtime_offset, &wtm, | ||
639 | &sleep); | ||
640 | set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); | ||
641 | |||
642 | base = &__get_cpu_var(hrtimer_bases); | ||
643 | |||
644 | /* Adjust CLOCK_REALTIME offset */ | ||
645 | raw_spin_lock(&base->lock); | ||
646 | base->clock_base[HRTIMER_BASE_REALTIME].offset = | ||
647 | timespec_to_ktime(realtime_offset); | ||
648 | base->clock_base[HRTIMER_BASE_BOOTTIME].offset = | ||
649 | timespec_to_ktime(sleep); | ||
650 | |||
651 | hrtimer_force_reprogram(base, 0); | ||
652 | raw_spin_unlock(&base->lock); | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * Clock realtime was set | ||
657 | * | ||
658 | * Change the offset of the realtime clock vs. the monotonic | ||
659 | * clock. | ||
660 | * | ||
661 | * We might have to reprogram the high resolution timer interrupt. On | ||
662 | * SMP we call the architecture specific code to retrigger _all_ high | ||
663 | * resolution timer interrupts. On UP we just disable interrupts and | ||
664 | * call the high resolution interrupt code. | ||
665 | */ | ||
666 | void clock_was_set(void) | ||
667 | { | ||
668 | /* Retrigger the CPU local events everywhere */ | ||
669 | on_each_cpu(retrigger_next_event, NULL, 1); | ||
670 | } | ||
671 | |||
672 | /* | ||
673 | * During resume we might have to reprogram the high resolution timer | ||
674 | * interrupt (on the local CPU): | ||
675 | */ | ||
676 | void hres_timers_resume(void) | ||
677 | { | ||
678 | WARN_ONCE(!irqs_disabled(), | ||
679 | KERN_INFO "hres_timers_resume() called with IRQs enabled!"); | ||
680 | |||
681 | retrigger_next_event(NULL); | ||
682 | } | ||
683 | |||
684 | /* | 624 | /* |
685 | * Initialize the high resolution related parts of cpu_base | 625 | * Initialize the high resolution related parts of cpu_base |
686 | */ | 626 | */ |
@@ -714,12 +654,14 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, | |||
714 | return 0; | 654 | return 0; |
715 | } | 655 | } |
716 | 656 | ||
657 | static void retrigger_next_event(void *arg); | ||
658 | |||
717 | /* | 659 | /* |
718 | * Switch to high resolution mode | 660 | * Switch to high resolution mode |
719 | */ | 661 | */ |
720 | static int hrtimer_switch_to_hres(void) | 662 | static int hrtimer_switch_to_hres(void) |
721 | { | 663 | { |
722 | int cpu = smp_processor_id(); | 664 | int i, cpu = smp_processor_id(); |
723 | struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu); | 665 | struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu); |
724 | unsigned long flags; | 666 | unsigned long flags; |
725 | 667 | ||
@@ -735,9 +677,8 @@ static int hrtimer_switch_to_hres(void) | |||
735 | return 0; | 677 | return 0; |
736 | } | 678 | } |
737 | base->hres_active = 1; | 679 | base->hres_active = 1; |
738 | base->clock_base[HRTIMER_BASE_REALTIME].resolution = KTIME_HIGH_RES; | 680 | for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) |
739 | base->clock_base[HRTIMER_BASE_MONOTONIC].resolution = KTIME_HIGH_RES; | 681 | base->clock_base[i].resolution = KTIME_HIGH_RES; |
740 | base->clock_base[HRTIMER_BASE_BOOTTIME].resolution = KTIME_HIGH_RES; | ||
741 | 682 | ||
742 | tick_setup_sched_timer(); | 683 | tick_setup_sched_timer(); |
743 | 684 | ||
@@ -764,6 +705,62 @@ static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { } | |||
764 | 705 | ||
765 | #endif /* CONFIG_HIGH_RES_TIMERS */ | 706 | #endif /* CONFIG_HIGH_RES_TIMERS */ |
766 | 707 | ||
708 | /* | ||
709 | * Retrigger next event is called after clock was set | ||
710 | * | ||
711 | * Called with interrupts disabled via on_each_cpu() | ||
712 | */ | ||
713 | static void retrigger_next_event(void *arg) | ||
714 | { | ||
715 | struct hrtimer_cpu_base *base = &__get_cpu_var(hrtimer_bases); | ||
716 | struct timespec realtime_offset, xtim, wtm, sleep; | ||
717 | |||
718 | if (!hrtimer_hres_active()) | ||
719 | return; | ||
720 | |||
721 | get_xtime_and_monotonic_and_sleep_offset(&xtim, &wtm, &sleep); | ||
722 | set_normalized_timespec(&realtime_offset, -wtm.tv_sec, -wtm.tv_nsec); | ||
723 | |||
724 | /* Adjust CLOCK_REALTIME offset */ | ||
725 | raw_spin_lock(&base->lock); | ||
726 | base->clock_base[HRTIMER_BASE_REALTIME].offset = | ||
727 | timespec_to_ktime(realtime_offset); | ||
728 | base->clock_base[HRTIMER_BASE_BOOTTIME].offset = | ||
729 | timespec_to_ktime(sleep); | ||
730 | |||
731 | hrtimer_force_reprogram(base, 0); | ||
732 | raw_spin_unlock(&base->lock); | ||
733 | } | ||
734 | |||
735 | /* | ||
736 | * Clock realtime was set | ||
737 | * | ||
738 | * Change the offset of the realtime clock vs. the monotonic | ||
739 | * clock. | ||
740 | * | ||
741 | * We might have to reprogram the high resolution timer interrupt. On | ||
742 | * SMP we call the architecture specific code to retrigger _all_ high | ||
743 | * resolution timer interrupts. On UP we just disable interrupts and | ||
744 | * call the high resolution interrupt code. | ||
745 | */ | ||
746 | void clock_was_set(void) | ||
747 | { | ||
748 | /* Retrigger the CPU local events everywhere */ | ||
749 | on_each_cpu(retrigger_next_event, NULL, 1); | ||
750 | } | ||
751 | |||
752 | /* | ||
753 | * During resume we might have to reprogram the high resolution timer | ||
754 | * interrupt (on the local CPU): | ||
755 | */ | ||
756 | void hrtimers_resume(void) | ||
757 | { | ||
758 | WARN_ONCE(!irqs_disabled(), | ||
759 | KERN_INFO "hrtimers_resume() called with IRQs enabled!"); | ||
760 | |||
761 | retrigger_next_event(NULL); | ||
762 | } | ||
763 | |||
767 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) | 764 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) |
768 | { | 765 | { |
769 | #ifdef CONFIG_TIMER_STATS | 766 | #ifdef CONFIG_TIMER_STATS |
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c index 8e6a05a5915a..a61b8fa2d39a 100644 --- a/kernel/time/timekeeping.c +++ b/kernel/time/timekeeping.c | |||
@@ -680,7 +680,7 @@ static void timekeeping_resume(void) | |||
680 | clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL); | 680 | clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL); |
681 | 681 | ||
682 | /* Resume hrtimers */ | 682 | /* Resume hrtimers */ |
683 | hres_timers_resume(); | 683 | hrtimers_resume(); |
684 | } | 684 | } |
685 | 685 | ||
686 | static int timekeeping_suspend(void) | 686 | static int timekeeping_suspend(void) |