aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Hackmann <ghackmann@google.com>2017-07-25 17:36:26 -0400
committerJohn Stultz <john.stultz@linaro.org>2017-08-17 15:14:58 -0400
commit28be3f8f48cfb3cf024860f042d424cd4824f5f7 (patch)
tree47d9c085f9218d2cce26962ed724a10445cdca0e
parenta524b1184b8e86141d689fa78ad150fbf2db9b4c (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.c86
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
125void describe_timer(int flags) 126void 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
132int do_timer(int clock_id, int flags) 134int 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); 183int 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
208int 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
220int 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
237int 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
204int main(void) 262int 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();