From 28be3f8f48cfb3cf024860f042d424cd4824f5f7 Mon Sep 17 00:00:00 2001 From: Greg Hackmann Date: Tue, 25 Jul 2017 14:36:26 -0700 Subject: [PATCH] kselftests: timers: set-timer-lat: Add one-shot timer test cases 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 Cc: Ingo Molnar Cc: Miroslav Lichvar Cc: Richard Cochran Cc: Prarit Bhargava Cc: Stephen Boyd Cc: Shuah Khan Cc: linux-kselftest@vger.kernel.org Signed-off-by: Greg Hackmann Signed-off-by: John Stultz --- .../testing/selftests/timers/set-timer-lat.c | 86 ++++++++++++++++--- 1 file changed, 73 insertions(+), 13 deletions(-) diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c index 10c2e18737c0..15434da23b04 100644 --- a/tools/testing/selftests/timers/set-timer-lat.c +++ b/tools/testing/selftests/timers/set-timer-lat.c @@ -20,6 +20,7 @@ */ +#include #include #include #include @@ -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(); -- 2.20.1