aboutsummaryrefslogtreecommitdiffstats
path: root/tools/testing/selftests/timers
diff options
context:
space:
mode:
authorJohn Stultz <john.stultz@linaro.org>2015-03-11 20:40:03 -0400
committerShuah Khan <shuahkh@osg.samsung.com>2015-03-12 15:22:14 -0400
commit4e40d0a22e728102bfea9543d827ee72206eecbb (patch)
tree3b03d586fb7b3a969dd7de3177de13922aa562b2 /tools/testing/selftests/timers
parent51f91cbdf5450b773eb221a2dfd141a92413370e (diff)
selftests/timers: Add set-timer-lat test from timetest suite
Add my set-timer-lat test from the timetest suite. This test checks the latency from set_timer and reports if any are unreasonable (>40ms). Cc: Shuah Khan <shuahkh@osg.samsung.com> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Richard Cochran <richardcochran@gmail.com> Signed-off-by: John Stultz <john.stultz@linaro.org> Tested-by: Prarit Bhargava <prarit@redhat.com> Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com>
Diffstat (limited to 'tools/testing/selftests/timers')
-rw-r--r--tools/testing/selftests/timers/Makefile5
-rw-r--r--tools/testing/selftests/timers/set-timer-lat.c209
2 files changed, 213 insertions, 1 deletions
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index 088a791a44cb..f69bdce0b8f3 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -2,7 +2,8 @@ CC = $(CROSS_COMPILE)gcc
2BUILD_FLAGS = -DKTEST 2BUILD_FLAGS = -DKTEST
3CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS) 3CFLAGS += -O3 -Wl,-no-as-needed -Wall $(BUILD_FLAGS)
4LDFLAGS += -lrt -lpthread 4LDFLAGS += -lrt -lpthread
5bins = posix_timers nanosleep inconsistency-check nsleep-lat raw_skew 5bins = posix_timers nanosleep inconsistency-check nsleep-lat raw_skew \
6 set-timer-lat
6 7
7all: ${bins} 8all: ${bins}
8 9
@@ -10,7 +11,9 @@ run_tests: all
10 ./posix_timers 11 ./posix_timers
11 ./nanosleep 12 ./nanosleep
12 ./nsleep-lat 13 ./nsleep-lat
14 ./set-timer-lat
13 ./inconsistency-check 15 ./inconsistency-check
14 ./raw_skew 16 ./raw_skew
17
15clean: 18clean:
16 rm -f ${bins} 19 rm -f ${bins}
diff --git a/tools/testing/selftests/timers/set-timer-lat.c b/tools/testing/selftests/timers/set-timer-lat.c
new file mode 100644
index 000000000000..3ea2effbcc22
--- /dev/null
+++ b/tools/testing/selftests/timers/set-timer-lat.c
@@ -0,0 +1,209 @@
1/* set_timer latency test
2 * John Stultz (john.stultz@linaro.org)
3 * (C) Copyright Linaro 2014
4 * Licensed under the GPLv2
5 *
6 * This test makes sure the set_timer api is correct
7 *
8 * To build:
9 * $ gcc set-timer-lat.c -o set-timer-lat -lrt
10 *
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.
15 *
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.
20 */
21
22
23#include <stdio.h>
24#include <unistd.h>
25#include <time.h>
26#include <string.h>
27#include <signal.h>
28#include <stdlib.h>
29#include <pthread.h>
30#ifdef KTEST
31#include "../kselftest.h"
32#else
33static inline int ksft_exit_pass(void)
34{
35 exit(0);
36}
37static inline int ksft_exit_fail(void)
38{
39 exit(1);
40}
41#endif
42
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
54#define CLOCK_TAI 11
55#define NR_CLOCKIDS 12
56
57
58#define NSEC_PER_SEC 1000000000ULL
59#define UNRESONABLE_LATENCY 40000000 /* 40ms in nanosecs */
60
61#define TIMER_SECS 3
62int alarmcount;
63int clock_id;
64struct timespec start_time;
65long long max_latency_ns;
66
67char *clockstring(int clockid)
68{
69 switch (clockid) {
70 case CLOCK_REALTIME:
71 return "CLOCK_REALTIME";
72 case CLOCK_MONOTONIC:
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";
84 case CLOCK_BOOTTIME:
85 return "CLOCK_BOOTTIME";
86 case CLOCK_REALTIME_ALARM:
87 return "CLOCK_REALTIME_ALARM";
88 case CLOCK_BOOTTIME_ALARM:
89 return "CLOCK_BOOTTIME_ALARM";
90 case CLOCK_TAI:
91 return "CLOCK_TAI";
92 };
93 return "UNKNOWN_CLOCKID";
94}
95
96
97long long timespec_sub(struct timespec a, struct timespec b)
98{
99 long long ret = NSEC_PER_SEC * b.tv_sec + b.tv_nsec;
100
101 ret -= NSEC_PER_SEC * a.tv_sec + a.tv_nsec;
102 return ret;
103}
104
105
106void sigalarm(int signo)
107{
108 long long delta_ns;
109 struct timespec ts;
110
111 clock_gettime(clock_id, &ts);
112 alarmcount++;
113
114 delta_ns = timespec_sub(start_time, ts);
115 delta_ns -= NSEC_PER_SEC * TIMER_SECS * alarmcount;
116
117 if (delta_ns < 0)
118 printf("%s timer fired early: FAIL\n", clockstring(clock_id));
119
120 if (delta_ns > max_latency_ns)
121 max_latency_ns = delta_ns;
122}
123
124int do_timer(int clock_id, int flags)
125{
126 struct sigevent se;
127 timer_t tm1;
128 struct itimerspec its1, its2;
129 int err;
130
131 /* Set up timer: */
132 memset(&se, 0, sizeof(se));
133 se.sigev_notify = SIGEV_SIGNAL;
134 se.sigev_signo = SIGRTMAX;
135 se.sigev_value.sival_int = 0;
136
137 max_latency_ns = 0;
138 alarmcount = 0;
139
140 err = timer_create(clock_id, &se, &tm1);
141 if (err) {
142 printf("%s - timer_create() failed\n", clockstring(clock_id));
143 return -1;
144 }
145
146 clock_gettime(clock_id, &start_time);
147 if (flags) {
148 its1.it_value = start_time;
149 its1.it_value.tv_sec += TIMER_SECS;
150 } else {
151 its1.it_value.tv_sec = TIMER_SECS;
152 its1.it_value.tv_nsec = 0;
153 }
154 its1.it_interval.tv_sec = TIMER_SECS;
155 its1.it_interval.tv_nsec = 0;
156
157 err = timer_settime(tm1, flags, &its1, &its2);
158 if (err) {
159 printf("%s - timer_settime() failed\n", clockstring(clock_id));
160 return -1;
161 }
162
163 while (alarmcount < 5)
164 sleep(1);
165
166 printf("%-22s %s max latency: %10lld ns : ",
167 clockstring(clock_id),
168 flags ? "ABSTIME":"RELTIME",
169 max_latency_ns);
170
171 timer_delete(tm1);
172 if (max_latency_ns < UNRESONABLE_LATENCY) {
173 printf("[OK]\n");
174 return 0;
175 }
176 printf("[FAILED]\n");
177 return -1;
178}
179
180int main(void)
181{
182 struct sigaction act;
183 int signum = SIGRTMAX;
184 int ret = 0;
185
186 /* Set up signal handler: */
187 sigfillset(&act.sa_mask);
188 act.sa_flags = 0;
189 act.sa_handler = sigalarm;
190 sigaction(signum, &act, NULL);
191
192 printf("Setting timers for every %i seconds\n", TIMER_SECS);
193 for (clock_id = 0; clock_id < NR_CLOCKIDS; clock_id++) {
194
195 if ((clock_id == CLOCK_PROCESS_CPUTIME_ID) ||
196 (clock_id == CLOCK_THREAD_CPUTIME_ID) ||
197 (clock_id == CLOCK_MONOTONIC_RAW) ||
198 (clock_id == CLOCK_REALTIME_COARSE) ||
199 (clock_id == CLOCK_MONOTONIC_COARSE) ||
200 (clock_id == CLOCK_HWSPECIFIC))
201 continue;
202
203 ret |= do_timer(clock_id, TIMER_ABSTIME);
204 ret |= do_timer(clock_id, 0);
205 }
206 if (ret)
207 return ksft_exit_fail();
208 return ksft_exit_pass();
209}