sched: x86, track TSC-unstable events
[deliverable/linux.git] / arch / i386 / kernel / tsc.c
index 6cb8f53367324c46fc5efcdc070afb5f02c01add..ea63a30ca3e88daa1bca2975f3c9f98812d7dffc 100644 (file)
@@ -4,6 +4,7 @@
  * See comments there for proper credits.
  */
 
+#include <linux/sched.h>
 #include <linux/clocksource.h>
 #include <linux/workqueue.h>
 #include <linux/cpufreq.h>
@@ -106,8 +107,13 @@ unsigned long long sched_clock(void)
 
        /*
         * Fall back to jiffies if there's no TSC available:
+        * ( But note that we still use it if the TSC is marked
+        *   unstable. We do this because unlike Time Of Day,
+        *   the scheduler clock tolerates small errors and it's
+        *   very important for it to be as fast as the platform
+        *   can achive it. )
         */
-       if (unlikely(!tsc_enabled))
+       if (unlikely(!tsc_enabled && !tsc_unstable))
                /* No locking but a rare wrong value is not a big deal: */
                return (jiffies_64 - INITIAL_JIFFIES) * (1000000000 / HZ);
 
@@ -200,13 +206,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
        struct cpufreq_freqs *freq = data;
 
-       if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
-               write_seqlock_irq(&xtime_lock);
-
        if (!ref_freq) {
                if (!freq->old){
                        ref_freq = freq->new;
-                       goto end;
+                       return 0;
                }
                ref_freq = freq->old;
                loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
@@ -233,13 +236,10 @@ time_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
                                 * TSC based sched_clock turns
                                 * to junk w/ cpufreq
                                 */
-                               mark_tsc_unstable();
+                               mark_tsc_unstable("cpufreq changes");
                        }
                }
        }
-end:
-       if (val != CPUFREQ_RESUMECHANGE && val != CPUFREQ_SUSPENDCHANGE)
-               write_sequnlock_irq(&xtime_lock);
 
        return 0;
 }
@@ -281,11 +281,13 @@ static struct clocksource clocksource_tsc = {
                                  CLOCK_SOURCE_MUST_VERIFY,
 };
 
-void mark_tsc_unstable(void)
+void mark_tsc_unstable(char *reason)
 {
+       sched_clock_unstable_event();
        if (!tsc_unstable) {
                tsc_unstable = 1;
                tsc_enabled = 0;
+               printk("Marking TSC unstable due to: %s.\n", reason);
                /* Can be called before registration */
                if (clocksource_tsc.mult)
                        clocksource_change_rating(&clocksource_tsc, 0);
This page took 0.025042 seconds and 5 git commands to generate.