Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 57d05a93 authored by John Stultz's avatar John Stultz
Browse files

time: Rework debugging variables so they aren't global



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.

This version is different from the earlier versions
as it keeps the variables in the timekeeper structure
rather then in the tkr.

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: default avatarJohn Stultz <john.stultz@linaro.org>
parent 6374f912
Loading
Loading
Loading
Loading
+15 −0
Original line number Original line Diff line number Diff line
@@ -61,6 +61,9 @@ struct tk_read_base {
 *			shifted nano seconds.
 *			shifted nano seconds.
 * @ntp_error_shift:	Shift conversion between clock shifted nano seconds and
 * @ntp_error_shift:	Shift conversion between clock shifted nano seconds and
 *			ntp shifted nano seconds.
 *			ntp shifted nano seconds.
 * @last_warning:	Warning ratelimiter (DEBUG_TIMEKEEPING)
 * @underflow_seen:	Underflow warning flag (DEBUG_TIMEKEEPING)
 * @overflow_seen:	Overflow warning flag (DEBUG_TIMEKEEPING)
 *
 *
 * Note: For timespec(64) based interfaces wall_to_monotonic is what
 * Note: For timespec(64) based interfaces wall_to_monotonic is what
 * we need to add to xtime (or xtime corrected for sub jiffie times)
 * we need to add to xtime (or xtime corrected for sub jiffie times)
@@ -106,6 +109,18 @@ struct timekeeper {
	s64			ntp_error;
	s64			ntp_error;
	u32			ntp_error_shift;
	u32			ntp_error_shift;
	u32			ntp_err_mult;
	u32			ntp_err_mult;
#ifdef CONFIG_DEBUG_TIMEKEEPING
	long			last_warning;
	/*
	 * These simple flag variables are managed
	 * without locks, which is racy, but they are
	 * 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
};
};


#ifdef CONFIG_GENERIC_TIME_VSYSCALL
#ifdef CONFIG_GENERIC_TIME_VSYSCALL
+11 −22
Original line number Original line Diff line number Diff line
@@ -118,18 +118,6 @@ static inline void tk_update_sleep_time(struct timekeeper *tk, ktime_t delta)


#ifdef CONFIG_DEBUG_TIMEKEEPING
#ifdef CONFIG_DEBUG_TIMEKEEPING
#define WARNING_FREQ (HZ*300) /* 5 minute rate-limiting */
#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 timekeeper *tk, cycle_t offset)
static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset)
{
{
@@ -149,29 +137,30 @@ static void timekeeping_check_update(struct timekeeper *tk, cycle_t offset)
		}
		}
	}
	}


	if (timekeeping_underflow_seen) {
	if (tk->underflow_seen) {
		if (jiffies - timekeeping_last_warning > WARNING_FREQ) {
		if (jiffies - tk->last_warning > WARNING_FREQ) {
			printk_deferred("WARNING: Underflow in clocksource '%s' observed, time update ignored.\n", name);
			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("         Please report this, consider using a different clocksource, if possible.\n");
			printk_deferred("         Your kernel is probably still fine.\n");
			printk_deferred("         Your kernel is probably still fine.\n");
			timekeeping_last_warning = jiffies;
			tk->last_warning = jiffies;
		}
		}
		timekeeping_underflow_seen = 0;
		tk->underflow_seen = 0;
	}
	}


	if (timekeeping_overflow_seen) {
	if (tk->overflow_seen) {
		if (jiffies - timekeeping_last_warning > WARNING_FREQ) {
		if (jiffies - tk->last_warning > WARNING_FREQ) {
			printk_deferred("WARNING: Overflow in clocksource '%s' observed, time update capped.\n", name);
			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("         Please report this, consider using a different clocksource, if possible.\n");
			printk_deferred("         Your kernel is probably still fine.\n");
			printk_deferred("         Your kernel is probably still fine.\n");
			timekeeping_last_warning = jiffies;
			tk->last_warning = jiffies;
		}
		}
		timekeeping_overflow_seen = 0;
		tk->overflow_seen = 0;
	}
	}
}
}


static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr)
static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr)
{
{
	struct timekeeper *tk = &tk_core.timekeeper;
	cycle_t now, last, mask, max, delta;
	cycle_t now, last, mask, max, delta;
	unsigned int seq;
	unsigned int seq;


@@ -197,13 +186,13 @@ static inline cycle_t timekeeping_get_delta(struct tk_read_base *tkr)
	 * mask-relative negative values.
	 * mask-relative negative values.
	 */
	 */
	if (unlikely((~delta & mask) < (mask >> 3))) {
	if (unlikely((~delta & mask) < (mask >> 3))) {
		timekeeping_underflow_seen = 1;
		tk->underflow_seen = 1;
		delta = 0;
		delta = 0;
	}
	}


	/* Cap delta value to the max_cycles values to avoid mult overflows */
	/* Cap delta value to the max_cycles values to avoid mult overflows */
	if (unlikely(delta > max)) {
	if (unlikely(delta > max)) {
		timekeeping_overflow_seen = 1;
		tk->overflow_seen = 1;
		delta = tkr->clock->max_cycles;
		delta = tkr->clock->max_cycles;
	}
	}