Add missing zstd.h to coregrind Makefile.am noinst_HEADERS
[valgrind.git] / memcheck / tests / linux / timerfd-syscall.c
blob61d75b55456bf7f34afd2ee0dd0a11447956e483
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, see <http://www.gnu.org/licenses/>.
23 * See also http://www.xmailserver.org/timerfd-test2.c
26 #define _GNU_SOURCE
28 #include "../../../config.h"
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <poll.h>
32 #include <signal.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37 #include <unistd.h>
38 #include <signal.h>
39 #if defined(HAVE_SYS_SYSCALL_H)
40 #include <sys/syscall.h>
41 #endif
42 #if defined(HAVE_SYS_TIME_H)
43 #include <sys/time.h>
44 #endif
45 #if defined(HAVE_SYS_TYPES_H)
46 #include <sys/types.h>
47 #endif
51 * timerfd_* system call numbers introduced in 2.6.23. These constants are
52 * not yet in the glibc 2.7 headers, that is why they are defined here.
54 #ifndef __NR_timerfd_create
55 #if defined(__x86_64__)
56 #define __NR_timerfd_create 283
57 #elif defined(__i386__)
58 #define __NR_timerfd_create 322
59 #elif defined(__powerpc__)
60 #define __NR_timerfd_create 306
61 #elif defined(__s390x__)
62 #define __NR_timerfd_create 319
63 #else
64 #error Cannot detect your architecture!
65 #endif
66 #endif
68 #ifndef __NR_timerfd_settime
69 #if defined(__x86_64__)
70 #define __NR_timerfd_settime 286
71 #define __NR_timerfd_gettime 287
72 #elif defined(__i386__)
73 #define __NR_timerfd_settime 325
74 #define __NR_timerfd_gettime 326
75 #elif defined(__powerpc__)
76 #define __NR_timerfd_settime 311
77 #define __NR_timerfd_gettime 312
78 #elif defined(__s390x__)
79 #define __NR_timerfd_settime 320
80 #define __NR_timerfd_gettime 321
81 #else
82 #error Cannot detect your architecture!
83 #endif
84 #endif
88 /* Definitions from include/linux/timerfd.h */
89 #define TFD_TIMER_ABSTIME (1 << 0)
93 struct tmr_type
95 int id;
96 char const *name;
100 #if defined(HAVE_CLOCK_GETTIME)
101 unsigned long long getustime(int clockid)
103 struct timespec tp;
105 if (clock_gettime((clockid_t) clockid, &tp))
107 perror("clock_gettime");
108 return 0;
111 return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
113 #else
114 unsigned long long getustime(int clockid)
116 fprintf(stderr, "error: clock_gettime\n");
117 return 0;
119 #endif
121 void set_timespec(struct timespec *tmr, unsigned long long ustime)
123 tmr->tv_sec = (time_t) (ustime / 1000000ULL);
124 tmr->tv_nsec = (long) (1000ULL * (ustime % 1000000ULL));
127 int timerfd_create(int clockid, int flags)
129 return syscall(__NR_timerfd_create, clockid, flags);
132 int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr,
133 struct itimerspec *otmr)
135 return syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);
138 int timerfd_gettime(int ufc, struct itimerspec *otmr)
140 return syscall(__NR_timerfd_gettime, ufc, otmr);
143 long waittmr(int tfd, int timeo)
145 u_int64_t ticks;
146 struct pollfd pfd;
148 pfd.fd = tfd;
149 pfd.events = POLLIN;
150 pfd.revents = 0;
151 if (poll(&pfd, 1, timeo) < 0)
153 perror("poll");
154 return -1;
156 if ((pfd.revents & POLLIN) == 0)
158 fprintf(stderr, "no ticks happened\n");
159 return -1;
161 if (read(tfd, &ticks, sizeof(ticks)) != sizeof(ticks))
163 perror("timerfd read");
164 return -1;
167 return ticks;
170 int main(int ac, char **av)
172 int i, tfd;
173 long ticks;
174 unsigned long long tnow, ttmr;
175 u_int64_t uticks;
176 struct itimerspec tmr;
177 struct tmr_type clks[] =
179 #if defined(HAVE_CLOCK_MONOTONIC)
180 { CLOCK_MONOTONIC, "CLOCK MONOTONIC" },
181 #endif
182 { CLOCK_REALTIME, "CLOCK REALTIME" },
185 for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++)
187 fprintf(stderr, "\n\n---------------------------------------\n");
188 fprintf(stderr, "| testing %s\n", clks[i].name);
189 fprintf(stderr, "---------------------------------------\n\n");
191 fprintf(stderr, "relative timer test (at 500 ms) ...\n");
192 set_timespec(&tmr.it_value, 500 * 1000);
193 set_timespec(&tmr.it_interval, 0);
194 tnow = getustime(clks[i].id);
195 if ((tfd = timerfd_create(clks[i].id, 0)) == -1)
197 perror("timerfd_create");
198 return 1;
201 if (timerfd_settime(tfd, 0, &tmr, NULL))
203 perror("timerfd_settime");
204 return 1;
207 fprintf(stderr, "waiting timer ...\n");
208 ticks = waittmr(tfd, -1);
209 ttmr = getustime(clks[i].id);
210 if (ticks <= 0)
211 fprintf(stderr, "whooops! no timer showed up!\n");
212 else
213 fprintf(stderr, "got timer ticks (%ld) after %.1f s\n",
214 ticks, (ttmr - tnow) * 1e-6);
217 fprintf(stderr, "absolute timer test (at 500 ms) ...\n");
218 tnow = getustime(clks[i].id);
219 set_timespec(&tmr.it_value, tnow + 500 * 1000);
220 set_timespec(&tmr.it_interval, 0);
221 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL))
223 perror("timerfd_settime");
224 return 1;
227 fprintf(stderr, "waiting timer ...\n");
228 ticks = waittmr(tfd, -1);
229 ttmr = getustime(clks[i].id);
230 if (ticks <= 0)
231 fprintf(stderr, "whooops! no timer showed up!\n");
232 else
233 fprintf(stderr, "got timer ticks (%ld) after %.1f s\n",
234 ticks, (ttmr - tnow) * 1e-6);
236 fprintf(stderr, "sequential timer test (100 ms clock) ...\n");
237 tnow = getustime(clks[i].id);
238 set_timespec(&tmr.it_value, tnow + 100 * 1000);
239 set_timespec(&tmr.it_interval, 100 * 1000);
240 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL))
242 perror("timerfd_settime");
243 return 1;
246 fprintf(stderr, "sleeping one second ...\n");
247 sleep(1);
248 if (timerfd_gettime(tfd, &tmr))
250 perror("timerfd_gettime");
251 return 1;
253 fprintf(stderr, "timerfd_gettime returned:\n"
254 "\tit_value = %.1f it_interval = %.1f\n",
255 tmr.it_value.tv_sec + 1e-9 * tmr.it_value.tv_nsec,
256 tmr.it_interval.tv_sec + 1e-9 * tmr.it_interval.tv_nsec);
257 fprintf(stderr, "sleeping 1 second ...\n");
258 sleep(1);
260 fprintf(stderr, "waiting timer ...\n");
261 ticks = waittmr(tfd, -1);
262 ttmr = getustime(clks[i].id);
263 if (ticks <= 0)
264 fprintf(stderr, "whooops! no timer showed up!\n");
265 else
267 const double delta = (ttmr - tnow) * 1e-6;
268 if (19 <= ticks && ticks <= 55 && 1.9 < delta && delta < 5.5)
269 fprintf(stderr, "got about 20 timer ticks after about 2s\n");
270 else
271 fprintf(stderr, "got timer ticks (%ld) after %.2f s\n", ticks, delta);
275 fprintf(stderr, "O_NONBLOCK test ...\n");
276 tnow = getustime(clks[i].id);
277 set_timespec(&tmr.it_value, 100 * 1000);
278 set_timespec(&tmr.it_interval, 0);
279 if (timerfd_settime(tfd, 0, &tmr, NULL))
281 perror("timerfd_settime");
282 return 1;
284 #if 0
285 fprintf(stderr, "timerfd = %d\n", tfd);
286 #endif
288 fprintf(stderr, "waiting timer (flush the single tick) ...\n");
289 ticks = waittmr(tfd, -1);
290 ttmr = getustime(clks[i].id);
291 if (ticks <= 0)
292 fprintf(stderr, "whooops! no timer showed up!\n");
293 else
294 fprintf(stderr, "got timer ticks (%ld) after %.1f s\n",
295 ticks, (ttmr - tnow) * 1e-6);
297 fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
299 if (read(tfd, &uticks, sizeof(uticks)) > 0)
300 fprintf(stderr, "whooops! timer ticks not zero when should have been\n");
301 else if (errno != EAGAIN)
302 fprintf(stderr, "whooops! bad errno value (%d = '%s')!\n",
303 errno, strerror(errno));
304 else
305 fprintf(stderr, "success\n");
307 fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
309 close(tfd);
312 return 0;