Commit b12a03ce4880bd13786a98db6de494a3e0123129

Authored by Thomas Gleixner
1 parent 942c3c5c32

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  
... ... @@ -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
... ... @@ -680,7 +680,7 @@
680 680 clockevents_notify(CLOCK_EVT_NOTIFY_RESUME, NULL);
681 681  
682 682 /* Resume hrtimers */
683   - hres_timers_resume();
  683 + hrtimers_resume();
684 684 }
685 685  
686 686 static int timekeeping_suspend(void)