Ingo suggested that the timekeeping debugging variables
recently added should not be global, and should be tied
to the timekeeper's read_base.

Thus this patch implements that suggestion.

I'm a little hesitant here, since the tkr structure
has been carefully designed to fit in a cacheline.
However, these additions are all at the end of the
structure and are conditionally compiled.

Cc: Ingo Molnar <mi...@kernel.org>
Cc: Thomas Gleixner <t...@linutronix.de>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Prarit Bhargava <pra...@redhat.com>
Cc: Richard Cochran <richardcoch...@gmail.com>
Signed-off-by: John Stultz <john.stu...@linaro.org>
---
 include/linux/timekeeper_internal.h | 18 +++++++++++++++++-
 kernel/time/timekeeping.c           | 33 ++++++++++-----------------------
 2 files changed, 27 insertions(+), 24 deletions(-)

diff --git a/include/linux/timekeeper_internal.h 
b/include/linux/timekeeper_internal.h
index fb86963..9b33027 100644
--- a/include/linux/timekeeper_internal.h
+++ b/include/linux/timekeeper_internal.h
@@ -20,9 +20,13 @@
  * @shift:     Shift value for scaled math conversion
  * @xtime_nsec: Shifted (fractional) nano seconds offset for readout
  * @base:      ktime_t (nanoseconds) base time for readout
+ * @last_warning:   Warning ratelimiter (DEBUG_TIMEKEEPING)
+ * @underflow_seen: Underflow warning flag (DEBUG_TIMEKEEPING)
+ * @overflow_seen:  Overflow warning flag (DEBUG_TIMEKEEPING)
  *
  * This struct has size 56 byte on 64 bit. Together with a seqcount it
- * occupies a single 64byte cache line.
+ * occupies a single 64byte cache line (when DEBUG_TIMEKEEPING is not
+ * enabled).
  *
  * The struct is separate from struct timekeeper as it is also used
  * for a fast NMI safe accessors.
@@ -36,6 +40,18 @@ struct tk_read_base {
        u32                     shift;
        u64                     xtime_nsec;
        ktime_t                 base;
+#ifdef CONFIG_DEBUG_TIMEKEEPING
+       long                    last_warning;
+       /*
+        * These simple flag variables are managed
+        * without locks, which is racy, but ok since
+        * we don't really care about being super
+        * precise about how many events were seen,
+        * just that a problem was observed.
+        */
+       int                     underflow_seen;
+       int                     overflow_seen;
+#endif
 };
 
 /**
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 676896e..ad7a80f 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -118,19 +118,6 @@ static inline void tk_update_sleep_time(struct timekeeper 
*tk, ktime_t delta)
 
 #ifdef CONFIG_DEBUG_TIMEKEEPING
 #define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */
-/*
- * These simple flag variables are managed
- * without locks, which is racy, but ok since
- * we don't really care about being super
- * precise about how many events were seen,
- * just that a problem was observed.
- */
-static int timekeeping_underflow_seen;
-static int timekeeping_overflow_seen;
-
-/* last_warning is only modified under the timekeeping lock */
-static long timekeeping_last_warning;
-
 static void timekeeping_check_update(struct tk_read_base *tkr, cycle_t offset)
 {
 
@@ -149,24 +136,24 @@ static void timekeeping_check_update(struct tk_read_base 
*tkr, cycle_t offset)
                }
        }
 
-       if (timekeeping_underflow_seen) {
-               if (jiffies - timekeeping_last_warning > WARNING_FREQ) {
+       if (tkr->underflow_seen) {
+               if (jiffies - tkr->last_warning > WARNING_FREQ) {
                        printk_deferred("WARNING: Underflow in clocksource '%s' 
observed, time update ignored.\n", name);
                        printk_deferred("         Please report this, consider 
using a different clocksource, if possible.\n");
                        printk_deferred("         Your kernel is probably still 
fine.\n");
-                       timekeeping_last_warning = jiffies;
+                       tkr->last_warning = jiffies;
                }
-               timekeeping_underflow_seen = 0;
+               tkr->underflow_seen = 0;
        }
 
-       if (timekeeping_overflow_seen) {
-               if (jiffies - timekeeping_last_warning > WARNING_FREQ) {
+       if (tkr->overflow_seen) {
+               if (jiffies - tkr->last_warning > WARNING_FREQ) {
                        printk_deferred("WARNING: Overflow in clocksource '%s' 
observed, time update capped.\n", name);
                        printk_deferred("         Please report this, consider 
using a different clocksource, if possible.\n");
                        printk_deferred("         Your kernel is probably still 
fine.\n");
-                       timekeeping_last_warning = jiffies;
+                       tkr->last_warning = jiffies;
                }
-               timekeeping_overflow_seen = 0;
+               tkr->overflow_seen = 0;
        }
 }
 
@@ -197,13 +184,13 @@ static inline cycle_t timekeeping_get_delta(struct 
tk_read_base *tkr)
         * mask-relative negative values.
         */
        if (unlikely((~delta & mask) < (mask >> 3))) {
-               timekeeping_underflow_seen = 1;
+               tkr->underflow_seen = 1;
                delta = 0;
        }
 
        /* Cap delta value to the max_cycles values to avoid mult overflows */
        if (unlikely(delta > max)) {
-               timekeeping_overflow_seen = 1;
+               tkr->overflow_seen = 1;
                delta = tkr->clock->max_cycles;
        }
 
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to