Timekeeping queue for 4.14
Subsystems (3)
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
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
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.
--- tools/testing/selftests/timers/freq-step.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/testing/selftests/timers/freq-step.c +4 -0
@@ -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
PATCH 2/6 kselftests: timers: freq-step: Fix build warning
In reply to John StultzFixes 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.
--- tools/testing/selftests/timers/freq-step.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
tools/testing/selftests/timers/freq-step.c +2 -2
@@ -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
PATCH 3/6 kselftests: timers: set-timer-lat: Tweak reporting when timer fires early
In reply to John StultzFrom: 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.
--- 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
@@ -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
PATCH 4/6 kselftests: timers: set-timer-lat: Add one-shot timer test cases
In reply to John StultzFrom: 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.
--- 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
@@ -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
PATCH 5/6 timekeeping: Use proper timekeeper for debug code
In reply to John StultzFrom: 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().
--- kernel/time/timekeeping.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/timekeeping.c +1 -1
@@ -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
PATCH 6/6 alarmtimer: Fix unavailable wake-up source in sysfs
In reply to John StultzFrom: 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.
--- kernel/time/alarmtimer.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
kernel/time/alarmtimer.c +9 -2
@@ -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