@@ -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
};
/**
@@ -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;
}
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 <mingo@kernel.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Richard Cochran <richardcochran@gmail.com> Signed-off-by: John Stultz <john.stultz@linaro.org> --- include/linux/timekeeper_internal.h | 18 +++++++++++++++++- kernel/time/timekeeping.c | 33 ++++++++++----------------------- 2 files changed, 27 insertions(+), 24 deletions(-)