0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #include <errno.h>
0024 #include <stdio.h>
0025 #include <unistd.h>
0026 #include <time.h>
0027 #include <string.h>
0028 #include <signal.h>
0029 #include <stdlib.h>
0030 #include <pthread.h>
0031 #include "../kselftest.h"
0032
0033 #define CLOCK_REALTIME 0
0034 #define CLOCK_MONOTONIC 1
0035 #define CLOCK_PROCESS_CPUTIME_ID 2
0036 #define CLOCK_THREAD_CPUTIME_ID 3
0037 #define CLOCK_MONOTONIC_RAW 4
0038 #define CLOCK_REALTIME_COARSE 5
0039 #define CLOCK_MONOTONIC_COARSE 6
0040 #define CLOCK_BOOTTIME 7
0041 #define CLOCK_REALTIME_ALARM 8
0042 #define CLOCK_BOOTTIME_ALARM 9
0043 #define CLOCK_HWSPECIFIC 10
0044 #define CLOCK_TAI 11
0045 #define NR_CLOCKIDS 12
0046
0047
0048 #define NSEC_PER_SEC 1000000000ULL
0049 #define UNRESONABLE_LATENCY 40000000
0050
0051 #define TIMER_SECS 1
0052 int alarmcount;
0053 int clock_id;
0054 struct timespec start_time;
0055 long long max_latency_ns;
0056 int timer_fired_early;
0057
0058 char *clockstring(int clockid)
0059 {
0060 switch (clockid) {
0061 case CLOCK_REALTIME:
0062 return "CLOCK_REALTIME";
0063 case CLOCK_MONOTONIC:
0064 return "CLOCK_MONOTONIC";
0065 case CLOCK_PROCESS_CPUTIME_ID:
0066 return "CLOCK_PROCESS_CPUTIME_ID";
0067 case CLOCK_THREAD_CPUTIME_ID:
0068 return "CLOCK_THREAD_CPUTIME_ID";
0069 case CLOCK_MONOTONIC_RAW:
0070 return "CLOCK_MONOTONIC_RAW";
0071 case CLOCK_REALTIME_COARSE:
0072 return "CLOCK_REALTIME_COARSE";
0073 case CLOCK_MONOTONIC_COARSE:
0074 return "CLOCK_MONOTONIC_COARSE";
0075 case CLOCK_BOOTTIME:
0076 return "CLOCK_BOOTTIME";
0077 case CLOCK_REALTIME_ALARM:
0078 return "CLOCK_REALTIME_ALARM";
0079 case CLOCK_BOOTTIME_ALARM:
0080 return "CLOCK_BOOTTIME_ALARM";
0081 case CLOCK_TAI:
0082 return "CLOCK_TAI";
0083 };
0084 return "UNKNOWN_CLOCKID";
0085 }
0086
0087
0088 long long timespec_sub(struct timespec a, struct timespec b)
0089 {
0090 long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
0091
0092 ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
0093 return ret;
0094 }
0095
0096
0097 void sigalarm(int signo)
0098 {
0099 long long delta_ns;
0100 struct timespec ts;
0101
0102 clock_gettime(clock_id, &ts);
0103 alarmcount++;
0104
0105 delta_ns = timespec_sub(start_time, ts);
0106 delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount;
0107
0108 if (delta_ns < 0)
0109 timer_fired_early = 1;
0110
0111 if (delta_ns > max_latency_ns)
0112 max_latency_ns = delta_ns;
0113 }
0114
0115 void describe_timer(int flags, int interval)
0116 {
0117 printf("%-22s %s %s ",
0118 clockstring(clock_id),
0119 flags ? "ABSTIME":"RELTIME",
0120 interval ? "PERIODIC":"ONE-SHOT");
0121 }
0122
0123 int setup_timer(int clock_id, int flags, int interval, timer_t *tm1)
0124 {
0125 struct sigevent se;
0126 struct itimerspec its1, its2;
0127 int err;
0128
0129
0130 memset(&se, 0, sizeof(se));
0131 se.sigev_notify = SIGEV_SIGNAL;
0132 se.sigev_signo = SIGRTMAX;
0133 se.sigev_value.sival_int = 0;
0134
0135 max_latency_ns = 0;
0136 alarmcount = 0;
0137 timer_fired_early = 0;
0138
0139 err = timer_create(clock_id, &se, tm1);
0140 if (err) {
0141 if ((clock_id == CLOCK_REALTIME_ALARM) ||
0142 (clock_id == CLOCK_BOOTTIME_ALARM)) {
0143 printf("%-22s %s missing CAP_WAKE_ALARM? : [UNSUPPORTED]\n",
0144 clockstring(clock_id),
0145 flags ? "ABSTIME":"RELTIME");
0146
0147 return 1;
0148 }
0149 printf("%s - timer_create() failed\n", clockstring(clock_id));
0150 return -1;
0151 }
0152
0153 clock_gettime(clock_id, &start_time);
0154 if (flags) {
0155 its1.it_value = start_time;
0156 its1.it_value.tv_sec += TIMER_SECS;
0157 } else {
0158 its1.it_value.tv_sec = TIMER_SECS;
0159 its1.it_value.tv_nsec = 0;
0160 }
0161 its1.it_interval.tv_sec = interval;
0162 its1.it_interval.tv_nsec = 0;
0163
0164 err = timer_settime(*tm1, flags, &its1, &its2);
0165 if (err) {
0166 printf("%s - timer_settime() failed\n", clockstring(clock_id));
0167 return -1;
0168 }
0169
0170 return 0;
0171 }
0172
0173 int check_timer_latency(int flags, int interval)
0174 {
0175 int err = 0;
0176
0177 describe_timer(flags, interval);
0178 printf("timer fired early: %7d : ", timer_fired_early);
0179 if (!timer_fired_early) {
0180 printf("[OK]\n");
0181 } else {
0182 printf("[FAILED]\n");
0183 err = -1;
0184 }
0185
0186 describe_timer(flags, interval);
0187 printf("max latency: %10lld ns : ", max_latency_ns);
0188
0189 if (max_latency_ns < UNRESONABLE_LATENCY) {
0190 printf("[OK]\n");
0191 } else {
0192 printf("[FAILED]\n");
0193 err = -1;
0194 }
0195 return err;
0196 }
0197
0198 int check_alarmcount(int flags, int interval)
0199 {
0200 describe_timer(flags, interval);
0201 printf("count: %19d : ", alarmcount);
0202 if (alarmcount == 1) {
0203 printf("[OK]\n");
0204 return 0;
0205 }
0206 printf("[FAILED]\n");
0207 return -1;
0208 }
0209
0210 int do_timer(int clock_id, int flags)
0211 {
0212 timer_t tm1;
0213 const int interval = TIMER_SECS;
0214 int err;
0215
0216 err = setup_timer(clock_id, flags, interval, &tm1);
0217
0218 if (err)
0219 return err == 1 ? 0 : err;
0220
0221 while (alarmcount < 5)
0222 sleep(1);
0223
0224 timer_delete(tm1);
0225 return check_timer_latency(flags, interval);
0226 }
0227
0228 int do_timer_oneshot(int clock_id, int flags)
0229 {
0230 timer_t tm1;
0231 const int interval = 0;
0232 struct timeval timeout;
0233 int err;
0234
0235 err = setup_timer(clock_id, flags, interval, &tm1);
0236
0237 if (err)
0238 return err == 1 ? 0 : err;
0239
0240 memset(&timeout, 0, sizeof(timeout));
0241 timeout.tv_sec = 5;
0242 do {
0243 err = select(0, NULL, NULL, NULL, &timeout);
0244 } while (err == -1 && errno == EINTR);
0245
0246 timer_delete(tm1);
0247 err = check_timer_latency(flags, interval);
0248 err |= check_alarmcount(flags, interval);
0249 return err;
0250 }
0251
0252 int main(void)
0253 {
0254 struct sigaction act;
0255 int signum = SIGRTMAX;
0256 int ret = 0;
0257
0258
0259 sigfillset(&act.sa_mask);
0260 act.sa_flags = 0;
0261 act.sa_handler = sigalarm;
0262 sigaction(signum, &act, NULL);
0263
0264 printf("Setting timers for every %i seconds\n", TIMER_SECS);
0265 for (clock_id = 0; clock_id < NR_CLOCKIDS; clock_id++) {
0266
0267 if ((clock_id == CLOCK_PROCESS_CPUTIME_ID) ||
0268 (clock_id == CLOCK_THREAD_CPUTIME_ID) ||
0269 (clock_id == CLOCK_MONOTONIC_RAW) ||
0270 (clock_id == CLOCK_REALTIME_COARSE) ||
0271 (clock_id == CLOCK_MONOTONIC_COARSE) ||
0272 (clock_id == CLOCK_HWSPECIFIC))
0273 continue;
0274
0275 ret |= do_timer(clock_id, TIMER_ABSTIME);
0276 ret |= do_timer(clock_id, 0);
0277 ret |= do_timer_oneshot(clock_id, TIMER_ABSTIME);
0278 ret |= do_timer_oneshot(clock_id, 0);
0279 }
0280 if (ret)
0281 return ksft_exit_fail();
0282 return ksft_exit_pass();
0283 }