1 /** Test Valgrind's interception of the Linux syscalls timerfd_create(),
2 * timerfd_gettime() and timerfd_settime().
4 * This is a modified version of
5 * timerfd-test2 by Davide Libenzi (test app for timerfd)
6 * Copyright (C) 2007 Davide Libenzi <davidel@xmailserver.org>
7 * Modified for inclusion in Valgrind.
8 * Copyright (C) 2008 Bart Van Assche <bvanassche@acm.org>
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * See also http://www.xmailserver.org/timerfd-test2.c
29 #include "../../../config.h"
39 #if defined(HAVE_SYS_SIGNAL_H)
40 #include <sys/signal.h>
42 #if defined(HAVE_SYS_SYSCALL_H)
43 #include <sys/syscall.h>
45 #if defined(HAVE_SYS_TIME_H)
48 #if defined(HAVE_SYS_TYPES_H)
49 #include <sys/types.h>
54 * timerfd_* system call numbers introduced in 2.6.23. These constants are
55 * not yet in the glibc 2.7 headers, that is why they are defined here.
57 #ifndef __NR_timerfd_create
58 #if defined(__x86_64__)
59 #define __NR_timerfd_create 283
60 #elif defined(__i386__)
61 #define __NR_timerfd_create 322
62 #elif defined(__powerpc__)
63 #define __NR_timerfd_create 306
64 #elif defined(__s390x__)
65 #define __NR_timerfd_create 319
67 #error Cannot detect your architecture!
71 #ifndef __NR_timerfd_settime
72 #if defined(__x86_64__)
73 #define __NR_timerfd_settime 286
74 #define __NR_timerfd_gettime 287
75 #elif defined(__i386__)
76 #define __NR_timerfd_settime 325
77 #define __NR_timerfd_gettime 326
78 #elif defined(__powerpc__)
79 #define __NR_timerfd_settime 311
80 #define __NR_timerfd_gettime 312
81 #elif defined(__s390x__)
82 #define __NR_timerfd_settime 320
83 #define __NR_timerfd_gettime 321
85 #error Cannot detect your architecture!
91 /* Definitions from include/linux/timerfd.h */
92 #define TFD_TIMER_ABSTIME (1 << 0)
103 #if defined(HAVE_CLOCK_GETTIME)
104 unsigned long long getustime(int clockid
)
108 if (clock_gettime((clockid_t
) clockid
, &tp
))
110 perror("clock_gettime");
114 return 1000000ULL * tp
.tv_sec
+ tp
.tv_nsec
/ 1000;
117 unsigned long long getustime(int clockid
)
119 fprintf(stderr
, "error: clock_gettime\n");
124 void set_timespec(struct timespec
*tmr
, unsigned long long ustime
)
126 tmr
->tv_sec
= (time_t) (ustime
/ 1000000ULL);
127 tmr
->tv_nsec
= (long) (1000ULL * (ustime
% 1000000ULL));
130 int timerfd_create(int clockid
, int flags
)
132 return syscall(__NR_timerfd_create
, clockid
, flags
);
135 int timerfd_settime(int ufc
, int flags
, const struct itimerspec
*utmr
,
136 struct itimerspec
*otmr
)
138 return syscall(__NR_timerfd_settime
, ufc
, flags
, utmr
, otmr
);
141 int timerfd_gettime(int ufc
, struct itimerspec
*otmr
)
143 return syscall(__NR_timerfd_gettime
, ufc
, otmr
);
146 long waittmr(int tfd
, int timeo
)
154 if (poll(&pfd
, 1, timeo
) < 0)
159 if ((pfd
.revents
& POLLIN
) == 0)
161 fprintf(stderr
, "no ticks happened\n");
164 if (read(tfd
, &ticks
, sizeof(ticks
)) != sizeof(ticks
))
166 perror("timerfd read");
173 int main(int ac
, char **av
)
177 unsigned long long tnow
, ttmr
;
179 struct itimerspec tmr
;
180 struct tmr_type clks
[] =
182 #if defined(HAVE_CLOCK_MONOTONIC)
183 { CLOCK_MONOTONIC
, "CLOCK MONOTONIC" },
185 { CLOCK_REALTIME
, "CLOCK REALTIME" },
188 for (i
= 0; i
< sizeof(clks
) / sizeof(clks
[0]); i
++)
190 fprintf(stderr
, "\n\n---------------------------------------\n");
191 fprintf(stderr
, "| testing %s\n", clks
[i
].name
);
192 fprintf(stderr
, "---------------------------------------\n\n");
194 fprintf(stderr
, "relative timer test (at 500 ms) ...\n");
195 set_timespec(&tmr
.it_value
, 500 * 1000);
196 set_timespec(&tmr
.it_interval
, 0);
197 tnow
= getustime(clks
[i
].id
);
198 if ((tfd
= timerfd_create(clks
[i
].id
, 0)) == -1)
200 perror("timerfd_create");
204 if (timerfd_settime(tfd
, 0, &tmr
, NULL
))
206 perror("timerfd_settime");
210 fprintf(stderr
, "waiting timer ...\n");
211 ticks
= waittmr(tfd
, -1);
212 ttmr
= getustime(clks
[i
].id
);
214 fprintf(stderr
, "whooops! no timer showed up!\n");
216 fprintf(stderr
, "got timer ticks (%ld) after %.1f s\n",
217 ticks
, (ttmr
- tnow
) * 1e-6);
220 fprintf(stderr
, "absolute timer test (at 500 ms) ...\n");
221 tnow
= getustime(clks
[i
].id
);
222 set_timespec(&tmr
.it_value
, tnow
+ 500 * 1000);
223 set_timespec(&tmr
.it_interval
, 0);
224 if (timerfd_settime(tfd
, TFD_TIMER_ABSTIME
, &tmr
, NULL
))
226 perror("timerfd_settime");
230 fprintf(stderr
, "waiting timer ...\n");
231 ticks
= waittmr(tfd
, -1);
232 ttmr
= getustime(clks
[i
].id
);
234 fprintf(stderr
, "whooops! no timer showed up!\n");
236 fprintf(stderr
, "got timer ticks (%ld) after %.1f s\n",
237 ticks
, (ttmr
- tnow
) * 1e-6);
239 fprintf(stderr
, "sequential timer test (100 ms clock) ...\n");
240 tnow
= getustime(clks
[i
].id
);
241 set_timespec(&tmr
.it_value
, tnow
+ 100 * 1000);
242 set_timespec(&tmr
.it_interval
, 100 * 1000);
243 if (timerfd_settime(tfd
, TFD_TIMER_ABSTIME
, &tmr
, NULL
))
245 perror("timerfd_settime");
249 fprintf(stderr
, "sleeping one second ...\n");
251 if (timerfd_gettime(tfd
, &tmr
))
253 perror("timerfd_gettime");
256 fprintf(stderr
, "timerfd_gettime returned:\n"
257 "\tit_value = %.1f it_interval = %.1f\n",
258 tmr
.it_value
.tv_sec
+ 1e-9 * tmr
.it_value
.tv_nsec
,
259 tmr
.it_interval
.tv_sec
+ 1e-9 * tmr
.it_interval
.tv_nsec
);
260 fprintf(stderr
, "sleeping 1 second ...\n");
263 fprintf(stderr
, "waiting timer ...\n");
264 ticks
= waittmr(tfd
, -1);
265 ttmr
= getustime(clks
[i
].id
);
267 fprintf(stderr
, "whooops! no timer showed up!\n");
270 const double delta
= (ttmr
- tnow
) * 1e-6;
271 if (19 <= ticks
&& ticks
<= 55 && 1.9 < delta
&& delta
< 5.5)
272 fprintf(stderr
, "got about 20 timer ticks after about 2s\n");
274 fprintf(stderr
, "got timer ticks (%ld) after %.2f s\n", ticks
, delta
);
278 fprintf(stderr
, "O_NONBLOCK test ...\n");
279 tnow
= getustime(clks
[i
].id
);
280 set_timespec(&tmr
.it_value
, 100 * 1000);
281 set_timespec(&tmr
.it_interval
, 0);
282 if (timerfd_settime(tfd
, 0, &tmr
, NULL
))
284 perror("timerfd_settime");
288 fprintf(stderr
, "timerfd = %d\n", tfd
);
291 fprintf(stderr
, "waiting timer (flush the single tick) ...\n");
292 ticks
= waittmr(tfd
, -1);
293 ttmr
= getustime(clks
[i
].id
);
295 fprintf(stderr
, "whooops! no timer showed up!\n");
297 fprintf(stderr
, "got timer ticks (%ld) after %.1f s\n",
298 ticks
, (ttmr
- tnow
) * 1e-6);
300 fcntl(tfd
, F_SETFL
, fcntl(tfd
, F_GETFL
, 0) | O_NONBLOCK
);
302 if (read(tfd
, &uticks
, sizeof(uticks
)) > 0)
303 fprintf(stderr
, "whooops! timer ticks not zero when should have been\n");
304 else if (errno
!= EAGAIN
)
305 fprintf(stderr
, "whooops! bad errno value (%d = '%s')!\n",
306 errno
, strerror(errno
));
308 fprintf(stderr
, "success\n");
310 fcntl(tfd
, F_SETFL
, fcntl(tfd
, F_GETFL
, 0) & ~O_NONBLOCK
);