]> Pileus Git - ~andy/linux/commitdiff
Merge branch 'timers-for-linus-clocksource' of git://git.kernel.org/pub/scm/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 15 Jun 2009 16:58:33 +0000 (09:58 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 15 Jun 2009 16:58:33 +0000 (09:58 -0700)
* 'timers-for-linus-clocksource' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  clocksource: prevent selection of low resolution clocksourse also for nohz=on
  clocksource: sanity check sysfs clocksource changes

include/linux/tick.h
kernel/time/clocksource.c
kernel/time/tick-oneshot.c

index 469b82d88b3b133b5bbadf5b72304f5657f2b961..0482229c07db348636a9089722b69168a8b4dcc9 100644 (file)
@@ -97,10 +97,12 @@ extern void tick_clock_notify(void);
 extern int tick_check_oneshot_change(int allow_nohz);
 extern struct tick_sched *tick_get_tick_sched(int cpu);
 extern void tick_check_idle(int cpu);
+extern int tick_oneshot_mode_active(void);
 # else
 static inline void tick_clock_notify(void) { }
 static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 static inline void tick_check_idle(int cpu) { }
+static inline int tick_oneshot_mode_active(void) { return 0; }
 # endif
 
 #else /* CONFIG_GENERIC_CLOCKEVENTS */
@@ -109,6 +111,7 @@ static inline void tick_cancel_sched_timer(int cpu) { }
 static inline void tick_clock_notify(void) { }
 static inline int tick_check_oneshot_change(int allow_nohz) { return 0; }
 static inline void tick_check_idle(int cpu) { }
+static inline int tick_oneshot_mode_active(void) { return 0; }
 #endif /* !CONFIG_GENERIC_CLOCKEVENTS */
 
 # ifdef CONFIG_NO_HZ
index 80189f6f1c5a1f7a326c9490e18f571fc8f49ea7..592bf584d1d2b5fa86a7fb605e4f5cf2901eda11 100644 (file)
@@ -509,6 +509,18 @@ static ssize_t sysfs_override_clocksource(struct sys_device *dev,
                }
        }
 
+       /*
+        * Check to make sure we don't switch to a non-highres capable
+        * clocksource if the tick code is in oneshot mode (highres or nohz)
+        */
+       if (tick_oneshot_mode_active() &&
+           !(ovr->flags & CLOCK_SOURCE_VALID_FOR_HRES)) {
+               printk(KERN_WARNING "%s clocksource is not HRT compatible. "
+                       "Cannot switch while in HRT/NOHZ mode\n", ovr->name);
+               ovr = NULL;
+               override_name[0] = 0;
+       }
+
        /* Reselect, when the override name has changed */
        if (ovr != clocksource_override) {
                clocksource_override = ovr;
@@ -537,7 +549,13 @@ sysfs_show_available_clocksources(struct sys_device *dev,
 
        spin_lock_irq(&clocksource_lock);
        list_for_each_entry(src, &clocksource_list, list) {
-               count += snprintf(buf + count,
+               /*
+                * Don't show non-HRES clocksource if the tick code is
+                * in one shot mode (highres=on or nohz=on)
+                */
+               if (!tick_oneshot_mode_active() ||
+                   (src->flags & CLOCK_SOURCE_VALID_FOR_HRES))
+                       count += snprintf(buf + count,
                                  max((ssize_t)PAGE_SIZE - count, (ssize_t)0),
                                  "%s ", src->name);
        }
index 2e8de678e767a76d444c822307b7bd34baff67c5..a96c0e2b89cf82b574de560971256dc7f2bf0931 100644 (file)
@@ -128,6 +128,23 @@ int tick_switch_to_oneshot(void (*handler)(struct clock_event_device *))
        return 0;
 }
 
+/**
+ * tick_check_oneshot_mode - check whether the system is in oneshot mode
+ *
+ * returns 1 when either nohz or highres are enabled. otherwise 0.
+ */
+int tick_oneshot_mode_active(void)
+{
+       unsigned long flags;
+       int ret;
+
+       local_irq_save(flags);
+       ret = __get_cpu_var(tick_cpu_device).mode == TICKDEV_MODE_ONESHOT;
+       local_irq_restore(flags);
+
+       return ret;
+}
+
 #ifdef CONFIG_HIGH_RES_TIMERS
 /**
  * tick_init_highres - switch to high resolution mode