Commit b12a03ce4880bd13786a98db6de494a3e0123129
1 parent
942c3c5c32
Exists in
master
and in
7 other branches
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>
Showing 3 changed files with 65 additions and 78 deletions Side-by-side Diff
include/linux/hrtimer.h
... | ... | @@ -148,9 +148,7 @@ |
148 | 148 | ktime_t resolution; |
149 | 149 | ktime_t (*get_time)(void); |
150 | 150 | ktime_t softirq_time; |
151 | -#ifdef CONFIG_HIGH_RES_TIMERS | |
152 | 151 | ktime_t offset; |
153 | -#endif | |
154 | 152 | }; |
155 | 153 | |
156 | 154 | enum hrtimer_base_type { |
... | ... | @@ -256,8 +254,6 @@ |
256 | 254 | #ifdef CONFIG_HIGH_RES_TIMERS |
257 | 255 | struct clock_event_device; |
258 | 256 | |
259 | -extern void clock_was_set(void); | |
260 | -extern void hres_timers_resume(void); | |
261 | 257 | extern void hrtimer_interrupt(struct clock_event_device *dev); |
262 | 258 | |
263 | 259 | /* |
264 | 260 | |
... | ... | @@ -291,16 +287,8 @@ |
291 | 287 | # define MONOTONIC_RES_NSEC LOW_RES_NSEC |
292 | 288 | # define KTIME_MONOTONIC_RES KTIME_LOW_RES |
293 | 289 | |
294 | -/* | |
295 | - * clock_was_set() is a NOP for non- high-resolution systems. The | |
296 | - * time-sorted order guarantees that a timer does not expire early and | |
297 | - * is expired in the next softirq when the clock was advanced. | |
298 | - */ | |
299 | -static inline void clock_was_set(void) { } | |
300 | 290 | static inline void hrtimer_peek_ahead_timers(void) { } |
301 | 291 | |
302 | -static inline void hres_timers_resume(void) { } | |
303 | - | |
304 | 292 | /* |
305 | 293 | * In non high resolution mode the time reference is taken from |
306 | 294 | * the base softirq time variable. |
307 | 295 | |
... | ... | @@ -316,10 +304,12 @@ |
316 | 304 | } |
317 | 305 | #endif |
318 | 306 | |
307 | +extern void clock_was_set(void); | |
308 | +extern void hrtimers_resume(void); | |
309 | + | |
319 | 310 | extern ktime_t ktime_get(void); |
320 | 311 | extern ktime_t ktime_get_real(void); |
321 | 312 | extern ktime_t ktime_get_boottime(void); |
322 | - | |
323 | 313 | |
324 | 314 | DECLARE_PER_CPU(struct tick_device, tick_cpu_device); |
325 | 315 |
kernel/hrtimer.c
... | ... | @@ -621,67 +621,7 @@ |
621 | 621 | return res; |
622 | 622 | } |
623 | 623 | |
624 | - | |
625 | 624 | /* |
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 | -/* | |
685 | 625 | * Initialize the high resolution related parts of cpu_base |
686 | 626 | */ |
687 | 627 | static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) |
688 | 628 | |
... | ... | @@ -714,12 +654,14 @@ |
714 | 654 | return 0; |
715 | 655 | } |
716 | 656 | |
657 | +static void retrigger_next_event(void *arg); | |
658 | + | |
717 | 659 | /* |
718 | 660 | * Switch to high resolution mode |
719 | 661 | */ |
720 | 662 | static int hrtimer_switch_to_hres(void) |
721 | 663 | { |
722 | - int cpu = smp_processor_id(); | |
664 | + int i, cpu = smp_processor_id(); | |
723 | 665 | struct hrtimer_cpu_base *base = &per_cpu(hrtimer_bases, cpu); |
724 | 666 | unsigned long flags; |
725 | 667 | |
... | ... | @@ -735,9 +677,8 @@ |
735 | 677 | return 0; |
736 | 678 | } |
737 | 679 | base->hres_active = 1; |
738 | - base->clock_base[HRTIMER_BASE_REALTIME].resolution = KTIME_HIGH_RES; | |
739 | - base->clock_base[HRTIMER_BASE_MONOTONIC].resolution = KTIME_HIGH_RES; | |
740 | - base->clock_base[HRTIMER_BASE_BOOTTIME].resolution = KTIME_HIGH_RES; | |
680 | + for (i = 0; i < HRTIMER_MAX_CLOCK_BASES; i++) | |
681 | + base->clock_base[i].resolution = KTIME_HIGH_RES; | |
741 | 682 | |
742 | 683 | tick_setup_sched_timer(); |
743 | 684 | |
... | ... | @@ -763,6 +704,62 @@ |
763 | 704 | static inline void hrtimer_init_hres(struct hrtimer_cpu_base *base) { } |
764 | 705 | |
765 | 706 | #endif /* CONFIG_HIGH_RES_TIMERS */ |
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 | +} | |
766 | 763 | |
767 | 764 | static inline void timer_stats_hrtimer_set_start_info(struct hrtimer *timer) |
768 | 765 | { |
kernel/time/timekeeping.c