diff options
author | Greg Hackmann <ghackmann@google.com> | 2017-07-25 17:36:26 -0400 |
---|---|---|
committer | John Stultz <john.stultz@linaro.org> | 2017-08-17 15:14:58 -0400 |
commit | 28be3f8f48cfb3cf024860f042d424cd4824f5f7 (patch) | |
tree | 47d9c085f9218d2cce26962ed724a10445cdca0e | |
parent | a524b1184b8e86141d689fa78ad150fbf2db9b4c (diff) |
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 <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Miroslav Lichvar <mlichvar@redhat.com>
Cc: Richard Cochran <richardcochran@gmail.com>
Cc: Prarit Bhargava <prarit@redhat.com>
Cc: Stephen Boyd <stephen.boyd@linaro.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Signed-off-by: Greg Hackmann <ghackmann@google.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
-rw-r--r-- | tools/testing/selftests/timers/set-timer-lat.c | 86 |
1 files 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 @@ | |||
20 | */ | 20 | */ |
21 | 21 | ||
22 | 22 | ||
23 | #include <errno.h> | ||
23 | #include <stdio.h> | 24 | #include <stdio.h> |
24 | #include <unistd.h> | 25 | #include <unistd.h> |
25 | #include <time.h> | 26 | #include <time.h> |
@@ -122,17 +123,17 @@ void sigalarm(int signo) | |||
122 | max_latency_ns = delta_ns; | 123 | max_latency_ns = delta_ns; |
123 | } | 124 | } |
124 | 125 | ||
125 | void describe_timer(int flags) | 126 | void describe_timer(int flags, int interval) |
126 | { | 127 | { |
127 | printf("%-22s %s ", | 128 | printf("%-22s %s %s ", |
128 | clockstring(clock_id), | 129 | clockstring(clock_id), |
129 | flags ? "ABSTIME":"RELTIME"); | 130 | flags ? "ABSTIME":"RELTIME", |
131 | interval ? "PERIODIC":"ONE-SHOT"); | ||
130 | } | 132 | } |
131 | 133 | ||
132 | int do_timer(int clock_id, int flags) | 134 | int setup_timer(int clock_id, int flags, int interval, timer_t *tm1) |
133 | { | 135 | { |
134 | struct sigevent se; | 136 | struct sigevent se; |
135 | timer_t tm1; | ||
136 | struct itimerspec its1, its2; | 137 | struct itimerspec its1, its2; |
137 | int err; | 138 | int err; |
138 | 139 | ||
@@ -146,7 +147,7 @@ int do_timer(int clock_id, int flags) | |||
146 | alarmcount = 0; | 147 | alarmcount = 0; |
147 | timer_fired_early = 0; | 148 | timer_fired_early = 0; |
148 | 149 | ||
149 | err = timer_create(clock_id, &se, &tm1); | 150 | err = timer_create(clock_id, &se, tm1); |
150 | if (err) { | 151 | if (err) { |
151 | if ((clock_id == CLOCK_REALTIME_ALARM) || | 152 | if ((clock_id == CLOCK_REALTIME_ALARM) || |
152 | (clock_id == CLOCK_BOOTTIME_ALARM)) { | 153 | (clock_id == CLOCK_BOOTTIME_ALARM)) { |
@@ -167,19 +168,23 @@ int do_timer(int clock_id, int flags) | |||
167 | its1.it_value.tv_sec = TIMER_SECS; | 168 | its1.it_value.tv_sec = TIMER_SECS; |
168 | its1.it_value.tv_nsec = 0; | 169 | its1.it_value.tv_nsec = 0; |
169 | } | 170 | } |
170 | its1.it_interval.tv_sec = TIMER_SECS; | 171 | its1.it_interval.tv_sec = interval; |
171 | its1.it_interval.tv_nsec = 0; | 172 | its1.it_interval.tv_nsec = 0; |
172 | 173 | ||
173 | err = timer_settime(tm1, flags, &its1, &its2); | 174 | err = timer_settime(*tm1, flags, &its1, &its2); |
174 | if (err) { | 175 | if (err) { |
175 | printf("%s - timer_settime() failed\n", clockstring(clock_id)); | 176 | printf("%s - timer_settime() failed\n", clockstring(clock_id)); |
176 | return -1; | 177 | return -1; |
177 | } | 178 | } |
178 | 179 | ||
179 | while (alarmcount < 5) | 180 | return 0; |
180 | sleep(1); | 181 | } |
181 | 182 | ||
182 | describe_timer(flags); | 183 | int check_timer_latency(int flags, int interval) |
184 | { | ||
185 | int err = 0; | ||
186 | |||
187 | describe_timer(flags, interval); | ||
183 | printf("timer fired early: %7d : ", timer_fired_early); | 188 | printf("timer fired early: %7d : ", timer_fired_early); |
184 | if (!timer_fired_early) { | 189 | if (!timer_fired_early) { |
185 | printf("[OK]\n"); | 190 | printf("[OK]\n"); |
@@ -188,10 +193,9 @@ int do_timer(int clock_id, int flags) | |||
188 | err = -1; | 193 | err = -1; |
189 | } | 194 | } |
190 | 195 | ||
191 | describe_timer(flags); | 196 | describe_timer(flags, interval); |
192 | printf("max latency: %10lld ns : ", max_latency_ns); | 197 | printf("max latency: %10lld ns : ", max_latency_ns); |
193 | 198 | ||
194 | timer_delete(tm1); | ||
195 | if (max_latency_ns < UNRESONABLE_LATENCY) { | 199 | if (max_latency_ns < UNRESONABLE_LATENCY) { |
196 | printf("[OK]\n"); | 200 | printf("[OK]\n"); |
197 | } else { | 201 | } else { |
@@ -201,6 +205,60 @@ int do_timer(int clock_id, int flags) | |||
201 | return err; | 205 | return err; |
202 | } | 206 | } |
203 | 207 | ||
208 | int check_alarmcount(int flags, int interval) | ||
209 | { | ||
210 | describe_timer(flags, interval); | ||
211 | printf("count: %19d : ", alarmcount); | ||
212 | if (alarmcount == 1) { | ||
213 | printf("[OK]\n"); | ||
214 | return 0; | ||
215 | } | ||
216 | printf("[FAILED]\n"); | ||
217 | return -1; | ||
218 | } | ||
219 | |||
220 | int do_timer(int clock_id, int flags) | ||
221 | { | ||
222 | timer_t tm1; | ||
223 | const int interval = TIMER_SECS; | ||
224 | int err; | ||
225 | |||
226 | err = setup_timer(clock_id, flags, interval, &tm1); | ||
227 | if (err) | ||
228 | return err; | ||
229 | |||
230 | while (alarmcount < 5) | ||
231 | sleep(1); | ||
232 | |||
233 | timer_delete(tm1); | ||
234 | return check_timer_latency(flags, interval); | ||
235 | } | ||
236 | |||
237 | int do_timer_oneshot(int clock_id, int flags) | ||
238 | { | ||
239 | timer_t tm1; | ||
240 | const int interval = 0; | ||
241 | struct timeval timeout; | ||
242 | fd_set fds; | ||
243 | int err; | ||
244 | |||
245 | err = setup_timer(clock_id, flags, interval, &tm1); | ||
246 | if (err) | ||
247 | return err; | ||
248 | |||
249 | memset(&timeout, 0, sizeof(timeout)); | ||
250 | timeout.tv_sec = 5; | ||
251 | FD_ZERO(&fds); | ||
252 | do { | ||
253 | err = select(FD_SETSIZE, &fds, NULL, NULL, &timeout); | ||
254 | } while (err == -1 && errno == EINTR); | ||
255 | |||
256 | timer_delete(tm1); | ||
257 | err = check_timer_latency(flags, interval); | ||
258 | err |= check_alarmcount(flags, interval); | ||
259 | return err; | ||
260 | } | ||
261 | |||
204 | int main(void) | 262 | int main(void) |
205 | { | 263 | { |
206 | struct sigaction act; | 264 | struct sigaction act; |
@@ -226,6 +284,8 @@ int main(void) | |||
226 | 284 | ||
227 | ret |= do_timer(clock_id, TIMER_ABSTIME); | 285 | ret |= do_timer(clock_id, TIMER_ABSTIME); |
228 | ret |= do_timer(clock_id, 0); | 286 | ret |= do_timer(clock_id, 0); |
287 | ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME); | ||
288 | ret |= do_timer_oneshot(clock_id, 0); | ||
229 | } | 289 | } |
230 | if (ret) | 290 | if (ret) |
231 | return ksft_exit_fail(); | 291 | return ksft_exit_fail(); |