Skip to contentSkip to conversation

Timekeeping queue for 4.14

GIT PULL New John Stultz 1 participant 7 messages Aug 18, 2017

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

Thomas, Ingo,
Just wanted to send along my current time queue for 4.14.

Most of it is actually ksefltest related, so if you'd prefer I can send those through Shuah.

Let me know if you have any feedback or objections.

thanks
-john

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
Cc Shuah Khan <[email protected]>

The following changes since commit 5771a8c08880cdca3bfb4a3fc6d309d6bba20877:

Linux v4.13-rc1 (2017-07-15 15:22:10 -0700)

are available in the git repository at:

https://git.linaro.org/people/john.stultz/linux.git fortglx/4.14/time

for you to fetch changes up to 47b4a457e4cc816b3fdd2ee55c65fda8ea6de051:

alarmtimer: Fix unavailable wake-up source in sysfs (2017-08-17 12:15:10 -0700)

----------------------------------------------------------------

Geert Uytterhoeven (1):
alarmtimer: Fix unavailable wake-up source in sysfs

Greg Hackmann (2):
kselftests: timers: set-timer-lat: Tweak reporting when timer fires
early
kselftests: timers: set-timer-lat: Add one-shot timer test cases

John Stultz (2):
kselftests: timers: freq-step: Define ADJ_SETOFFSET if device has
older kernel headers
kselftests: timers: freq-step: Fix build warning

Stafford Horne (1):
timekeeping: Use proper timekeeper for debug code

 kernel/time/alarmtimer.c                       |  11 ++-
 kernel/time/timekeeping.c                      |   2 +-
 tools/testing/selftests/timers/freq-step.c     |   8 +-
 tools/testing/selftests/timers/set-timer-lat.c | 103 +++++++++++++++++++++----
 4 files changed, 106 insertions(+), 18 deletions(-)
Signature · 1 line
2.7.4
#1 lore raw

PATCH 1/6 kselftests: timers: freq-step: Define ADJ_SETOFFSET if device has older kernel headers

On some systems, the kernel headers haven't been updated to include ADJ_SETOFFSET, so define it in the test if needed.

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
Cc Shuah Khan <[email protected]>
---
 tools/testing/selftests/timers/freq-step.c | 4 ++++
 1 file changed, 4 insertions(+)
tools/testing/selftests/timers/freq-step.c +4 -0
index e8c6183..934a308 100644
@@ -33,6 +33,10 @@
 #define MAX_FREQ_ERROR 10e-6
 #define MAX_STDDEV 1000e-9
 
+#ifndef ADJ_SETOFFSET
+  #define ADJ_SETOFFSET 0x0100
+#endif
+
 struct sample {
 	double offset;
 	double time;
Signature · 1 line
2.7.4
#2 lore raw

PATCH 2/6 kselftests: timers: freq-step: Fix build warning

In reply to John Stultz

Fixes the following build warning:
freq-step.c: In function ‘main’:
freq-step.c:271:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^

By returning the return values from ksft_success/fail.

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
Cc Shuah Khan <[email protected]>
---
 tools/testing/selftests/timers/freq-step.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/timers/freq-step.c +2 -2
index 934a308..926828e 100644
@@ -266,7 +266,7 @@ int main(int argc, char **argv)
 	set_frequency(0.0);
 
 	if (fails)
-		ksft_exit_fail();
+		return ksft_exit_fail();
 
-	ksft_exit_pass();
+	return ksft_exit_pass();
 }
Signature · 1 line
2.7.4
#3 lore raw

PATCH 3/6 kselftests: timers: set-timer-lat: Tweak reporting when timer fires early

In reply to John Stultz

From: Greg Hackmann <[email protected]>

Rather than printing an error inside the alarm signal handler, set a flag that we check later. This keeps the test from spamming the console every time the alarm fires early. It also fixes the test exiting with error code 0 if this was the only test failure.

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
Cc Shuah Khan <[email protected]>
---
 tools/testing/selftests/timers/set-timer-lat.c | 33 +++++++++++++++++++-------
 1 file changed, 25 insertions(+), 8 deletions(-)
tools/testing/selftests/timers/set-timer-lat.c +25 -8
index 4fc98c5..10c2e18 100644
@@ -63,6 +63,7 @@ int alarmcount;
 int clock_id;
 struct timespec start_time;
 long long max_latency_ns;
+int timer_fired_early;
 
 char *clockstring(int clockid)
 {
@@ -115,12 +116,19 @@ void sigalarm(int signo)
 	delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount;
 
 	if (delta_ns < 0)
-		printf("%s timer fired early: FAIL\n", clockstring(clock_id));
+		timer_fired_early = 1;
 
 	if (delta_ns > max_latency_ns)
 		max_latency_ns = delta_ns;
 }
 
+void describe_timer(int flags)
+{
+	printf("%-22s %s ",
+			clockstring(clock_id),
+			flags ? "ABSTIME":"RELTIME");
+}
+
 int do_timer(int clock_id, int flags)
 {
 	struct sigevent se;
@@ -136,6 +144,7 @@ int do_timer(int clock_id, int flags)
 
 	max_latency_ns = 0;
 	alarmcount = 0;
+	timer_fired_early = 0;
 
 	err = timer_create(clock_id, &se, &tm1);
 	if (err) {
@@ -170,18 +179,26 @@ int do_timer(int clock_id, int flags)
 	while (alarmcount < 5)
 		sleep(1);
 
-	printf("%-22s %s max latency: %10lld ns : ",
-			clockstring(clock_id),
-			flags ? "ABSTIME":"RELTIME",
-			max_latency_ns);
+	describe_timer(flags);
+	printf("timer fired early: %7d : ", timer_fired_early);
+	if (!timer_fired_early) {
+		printf("[OK]\n");
+	} else {
+		printf("[FAILED]\n");
+		err = -1;
+	}
+
+	describe_timer(flags);
+	printf("max latency: %10lld ns : ", max_latency_ns);
 
 	timer_delete(tm1);
 	if (max_latency_ns < UNRESONABLE_LATENCY) {
 		printf("[OK]\n");
-		return 0;
+	} else {
+		printf("[FAILED]\n");
+		err = -1;
 	}
-	printf("[FAILED]\n");
-	return -1;
+	return err;
 }
 
 int main(void)
Signature · 1 line
2.7.4
#4 lore raw

PATCH 4/6 kselftests: timers: set-timer-lat: Add one-shot timer test cases

In reply to John Stultz

From: Greg Hackmann <[email protected]>

These testcases are motivated by a recent alarmtimer regression, which caused one-shot CLOCK_{BOOTTIME,REALTIME}_ALARM timers to become periodic timers.

The new testcases are very similar to the existing testcases for repeating timers. But rather than waiting for 5 alarms, they wait for 5 seconds and verify that the alarm fired exactly once.

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
Cc Shuah Khan <[email protected]>
---
 tools/testing/selftests/timers/set-timer-lat.c | 86 ++++++++++++++++++++++----
 1 file changed, 73 insertions(+), 13 deletions(-)
tools/testing/selftests/timers/set-timer-lat.c +73 -13
index 10c2e18..15434da 100644
@@ -20,6 +20,7 @@
  */
 
 
+#include <errno.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <time.h>
@@ -122,17 +123,17 @@ void sigalarm(int signo)
 		max_latency_ns = delta_ns;
 }
 
-void describe_timer(int flags)
+void describe_timer(int flags, int interval)
 {
-	printf("%-22s %s ",
+	printf("%-22s %s %s ",
 			clockstring(clock_id),
-			flags ? "ABSTIME":"RELTIME");
+			flags ? "ABSTIME":"RELTIME",
+			interval ? "PERIODIC":"ONE-SHOT");
 }
 
-int do_timer(int clock_id, int flags)
+int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
 {
 	struct sigevent se;
-	timer_t tm1;
 	struct itimerspec its1, its2;
 	int err;
 
@@ -146,7 +147,7 @@ int do_timer(int clock_id, int flags)
 	alarmcount = 0;
 	timer_fired_early = 0;
 
-	err = timer_create(clock_id, &se, &tm1);
+	err = timer_create(clock_id, &se, tm1);
 	if (err) {
 		if ((clock_id == CLOCK_REALTIME_ALARM) ||
 		    (clock_id == CLOCK_BOOTTIME_ALARM)) {
@@ -167,19 +168,23 @@ int do_timer(int clock_id, int flags)
 		its1.it_value.tv_sec = TIMER_SECS;
 		its1.it_value.tv_nsec = 0;
 	}
-	its1.it_interval.tv_sec = TIMER_SECS;
+	its1.it_interval.tv_sec = interval;
 	its1.it_interval.tv_nsec = 0;
 
-	err = timer_settime(tm1, flags, &its1, &its2);
+	err = timer_settime(*tm1, flags, &its1, &its2);
 	if (err) {
 		printf("%s - timer_settime() failed\n", clockstring(clock_id));
 		return -1;
 	}
 
-	while (alarmcount < 5)
-		sleep(1);
+	return 0;
+}
 
-	describe_timer(flags);
+int check_timer_latency(int flags, int interval)
+{
+	int err = 0;
+
+	describe_timer(flags, interval);
 	printf("timer fired early: %7d : ", timer_fired_early);
 	if (!timer_fired_early) {
 		printf("[OK]\n");
@@ -188,10 +193,9 @@ int do_timer(int clock_id, int flags)
 		err = -1;
 	}
 
-	describe_timer(flags);
+	describe_timer(flags, interval);
 	printf("max latency: %10lld ns : ", max_latency_ns);
 
-	timer_delete(tm1);
 	if (max_latency_ns < UNRESONABLE_LATENCY) {
 		printf("[OK]\n");
 	} else {
@@ -201,6 +205,60 @@ int do_timer(int clock_id, int flags)
 	return err;
 }
 
+int check_alarmcount(int flags, int interval)
+{
+	describe_timer(flags, interval);
+	printf("count: %19d : ", alarmcount);
+	if (alarmcount == 1) {
+		printf("[OK]\n");
+		return 0;
+	}
+	printf("[FAILED]\n");
+	return -1;
+}
+
+int do_timer(int clock_id, int flags)
+{
+	timer_t tm1;
+	const int interval = TIMER_SECS;
+	int err;
+
+	err = setup_timer(clock_id, flags, interval, &tm1);
+	if (err)
+		return err;
+
+	while (alarmcount < 5)
+		sleep(1);
+
+	timer_delete(tm1);
+	return check_timer_latency(flags, interval);
+}
+
+int do_timer_oneshot(int clock_id, int flags)
+{
+	timer_t tm1;
+	const int interval = 0;
+	struct timeval timeout;
+	fd_set fds;
+	int err;
+
+	err = setup_timer(clock_id, flags, interval, &tm1);
+	if (err)
+		return err;
+
+	memset(&timeout, 0, sizeof(timeout));
+	timeout.tv_sec = 5;
+	FD_ZERO(&fds);
+	do {
+		err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout);
+	} while (err == -1 && errno == EINTR);
+
+	timer_delete(tm1);
+	err = check_timer_latency(flags, interval);
+	err |= check_alarmcount(flags, interval);
+	return err;
+}
+
 int main(void)
 {
 	struct sigaction act;
@@ -226,6 +284,8 @@ int main(void)
 
 		ret |= do_timer(clock_id, TIMER_ABSTIME);
 		ret |= do_timer(clock_id, 0);
+		ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME);
+		ret |= do_timer_oneshot(clock_id, 0);
 	}
 	if (ret)
 		return ksft_exit_fail();
Signature · 1 line
2.7.4
#5 lore raw

PATCH 5/6 timekeeping: Use proper timekeeper for debug code

In reply to John Stultz

From: Stafford Horne <[email protected]>

When CONFIG_DEBUG_TIMEKEEPING is enabled the timekeeping_check_update() function will update status like last_warning and underflow_seen on the timekeeper.

If there are issues found this state is used to rate limit the warnings that get printed.

This rate limiting doesn't really really work if stored in real_tk as the shadow timekeeper is overwritten onto real_tk at the end of every update_wall_time() call, resetting last_warning and other statuses.

Fix rate limiting by using the shadow_timekeeper for timekeeping_check_update().

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
Fixes commit 57d05a93ada7 ("time: Rework debugging variables so they aren't global")
---
 kernel/time/timekeeping.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/timekeeping.c +1 -1
index cedafa0..8f58669 100644
@@ -2066,7 +2066,7 @@ void update_wall_time(void)
 		goto out;
 
 	/* Do some additional sanity checking */
-	timekeeping_check_update(real_tk, offset);
+	timekeeping_check_update(tk, offset);
 
 	/*
 	 * With NO_HZ we may have to accumulate many cycle_intervals
Signature · 1 line
2.7.4
#6 lore raw

PATCH 6/6 alarmtimer: Fix unavailable wake-up source in sysfs

In reply to John Stultz

From: Geert Uytterhoeven <[email protected]>

Currently the alarmtimer registers a wake-up source unconditionally, regardless of the system having a (wake-up capable) RTC or not. Hence the alarmtimer will always show up in /sys/kernel/debug/wakeup_sources, even if it is not available, and thus cannot be a wake-up source.

To fix this, postpone registration until a wake-up capable RTC device is added.

Cc Thomas Gleixner <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Miroslav Lichvar <[email protected]>
Cc Richard Cochran <[email protected]>
Cc Prarit Bhargava <[email protected]>
Cc Stephen Boyd <[email protected]>
---
 kernel/time/alarmtimer.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)
kernel/time/alarmtimer.c +9 -2
index 0b8ff7d..73a2b47 100644
@@ -56,9 +56,9 @@ static ktime_t freezer_delta;
 static DEFINE_SPINLOCK(freezer_delta_lock);
 #endif
 
+#ifdef CONFIG_RTC_CLASS
 static struct wakeup_source *ws;
 
-#ifdef CONFIG_RTC_CLASS
 /* rtc timer and device for setting alarm wakeups at suspend */
 static struct rtc_timer		rtctimer;
 static struct rtc_device	*rtcdev;
@@ -89,6 +89,7 @@ static int alarmtimer_rtc_add_device(struct device *dev,
 {
 	unsigned long flags;
 	struct rtc_device *rtc = to_rtc_device(dev);
+	struct wakeup_source *__ws;
 
 	if (rtcdev)
 		return -EBUSY;
@@ -98,13 +99,20 @@ static int alarmtimer_rtc_add_device(struct device *dev,
 	if (!device_may_wakeup(rtc->dev.parent))
 		return -1;
 
+	__ws = wakeup_source_register("alarmtimer");
+
 	spin_lock_irqsave(&rtcdev_lock, flags);
 	if (!rtcdev) {
 		rtcdev = rtc;
 		/* hold a reference so it doesn't go away */
 		get_device(dev);
+		ws = __ws;
+		__ws = NULL;
 	}
 	spin_unlock_irqrestore(&rtcdev_lock, flags);
+
+	wakeup_source_unregister(__ws);
+
 	return 0;
 }
 
@@ -860,7 +868,6 @@ static int __init alarmtimer_init(void)
 		error = PTR_ERR(pdev);
 		goto out_drv;
 	}
-	ws = wakeup_source_register("alarmtimer");
 	return 0;
 
 out_drv:
Signature · 1 line
2.7.4