1 /* set_timer latency test
2 * John Stultz (john.stultz@linaro.org)
3 * (C) Copyright Linaro 2014
4 * Licensed under the GPLv2
6 * This test makes sure the set_timer api is correct
9 * $ gcc set-timer-lat.c -o set-timer-lat -lrt
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation, either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
31 #include "../kselftest.h"
33 static inline int ksft_exit_pass(void)
37 static inline int ksft_exit_fail(void)
43 #define CLOCK_REALTIME 0
44 #define CLOCK_MONOTONIC 1
45 #define CLOCK_PROCESS_CPUTIME_ID 2
46 #define CLOCK_THREAD_CPUTIME_ID 3
47 #define CLOCK_MONOTONIC_RAW 4
48 #define CLOCK_REALTIME_COARSE 5
49 #define CLOCK_MONOTONIC_COARSE 6
50 #define CLOCK_BOOTTIME 7
51 #define CLOCK_REALTIME_ALARM 8
52 #define CLOCK_BOOTTIME_ALARM 9
53 #define CLOCK_HWSPECIFIC 10
55 #define NR_CLOCKIDS 12
58 #define NSEC_PER_SEC 1000000000ULL
59 #define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
64 struct timespec start_time
;
65 long long max_latency_ns
;
67 char *clockstring(int clockid
)
71 return "CLOCK_REALTIME";
73 return "CLOCK_MONOTONIC";
74 case CLOCK_PROCESS_CPUTIME_ID
:
75 return "CLOCK_PROCESS_CPUTIME_ID";
76 case CLOCK_THREAD_CPUTIME_ID
:
77 return "CLOCK_THREAD_CPUTIME_ID";
78 case CLOCK_MONOTONIC_RAW
:
79 return "CLOCK_MONOTONIC_RAW";
80 case CLOCK_REALTIME_COARSE
:
81 return "CLOCK_REALTIME_COARSE";
82 case CLOCK_MONOTONIC_COARSE
:
83 return "CLOCK_MONOTONIC_COARSE";
85 return "CLOCK_BOOTTIME";
86 case CLOCK_REALTIME_ALARM
:
87 return "CLOCK_REALTIME_ALARM";
88 case CLOCK_BOOTTIME_ALARM
:
89 return "CLOCK_BOOTTIME_ALARM";
93 return "UNKNOWN_CLOCKID";
97 long long timespec_sub(struct timespec a
, struct timespec b
)
99 long long ret
= NSEC_PER_SEC
* b
.tv_sec
+ b
.tv_nsec
;
101 ret
-= NSEC_PER_SEC
* a
.tv_sec
+ a
.tv_nsec
;
106 void sigalarm(int signo
)
111 clock_gettime(clock_id
, &ts
);
114 delta_ns
= timespec_sub(start_time
, ts
);
115 delta_ns
-= NSEC_PER_SEC
* TIMER_SECS
* alarmcount
;
118 printf("%s timer fired early: FAIL\n", clockstring(clock_id
));
120 if (delta_ns
> max_latency_ns
)
121 max_latency_ns
= delta_ns
;
124 int do_timer(int clock_id
, int flags
)
128 struct itimerspec its1
, its2
;
132 memset(&se
, 0, sizeof(se
));
133 se
.sigev_notify
= SIGEV_SIGNAL
;
134 se
.sigev_signo
= SIGRTMAX
;
135 se
.sigev_value
.sival_int
= 0;
140 err
= timer_create(clock_id
, &se
, &tm1
);
142 if ((clock_id
== CLOCK_REALTIME_ALARM
) ||
143 (clock_id
== CLOCK_BOOTTIME_ALARM
)) {
144 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n",
145 clockstring(clock_id
),
146 flags
? "ABSTIME":"RELTIME");
149 printf("%s - timer_create() failed\n", clockstring(clock_id
));
153 clock_gettime(clock_id
, &start_time
);
155 its1
.it_value
= start_time
;
156 its1
.it_value
.tv_sec
+= TIMER_SECS
;
158 its1
.it_value
.tv_sec
= TIMER_SECS
;
159 its1
.it_value
.tv_nsec
= 0;
161 its1
.it_interval
.tv_sec
= TIMER_SECS
;
162 its1
.it_interval
.tv_nsec
= 0;
164 err
= timer_settime(tm1
, flags
, &its1
, &its2
);
166 printf("%s - timer_settime() failed\n", clockstring(clock_id
));
170 while (alarmcount
< 5)
173 printf("%-22s %s max latency: %10lld ns : ",
174 clockstring(clock_id
),
175 flags
? "ABSTIME":"RELTIME",
179 if (max_latency_ns
< UNRESONABLE_LATENCY
) {
183 printf("[FAILED]\n");
189 struct sigaction act
;
190 int signum
= SIGRTMAX
;
193 /* Set up signal handler: */
194 sigfillset(&act
.sa_mask
);
196 act
.sa_handler
= sigalarm
;
197 sigaction(signum
, &act
, NULL
);
199 printf("Setting timers for every %i seconds\n", TIMER_SECS
);
200 for (clock_id
= 0; clock_id
< NR_CLOCKIDS
; clock_id
++) {
202 if ((clock_id
== CLOCK_PROCESS_CPUTIME_ID
) ||
203 (clock_id
== CLOCK_THREAD_CPUTIME_ID
) ||
204 (clock_id
== CLOCK_MONOTONIC_RAW
) ||
205 (clock_id
== CLOCK_REALTIME_COARSE
) ||
206 (clock_id
== CLOCK_MONOTONIC_COARSE
) ||
207 (clock_id
== CLOCK_HWSPECIFIC
))
210 ret
|= do_timer(clock_id
, TIMER_ABSTIME
);
211 ret
|= do_timer(clock_id
, 0);
214 return ksft_exit_fail();
215 return ksft_exit_pass();