1 /*
2 * timerfd() test by Davide Libenzi (test app for timerfd)
3 * Copyright (C) 2007 Davide Libenzi
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 * Davide Libenzi <davidel@xmailserver.org>
20 *
21 *
22 * $ gcc -o timerfd-test2 timerfd-test2.c -lrt
23 *
24 * NAME
25 * timerfd01.c
26 * HISTORY
27 * 28/05/2008 Initial contribution by Davide Libenzi <davidel@xmailserver.org>
28 * 28/05/2008 Integrated to LTP by Subrata Modak <subrata@linux.vnet.ibm.com>
29 */
30
31 #define _GNU_SOURCE
32 #include <sys/syscall.h>
33 #include <sys/types.h>
34 #include <sys/signal.h>
35 #include <sys/time.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <unistd.h>
40 #include <signal.h>
41 #include <poll.h>
42 #include <fcntl.h>
43 #include <time.h>
44 #include <errno.h>
45 #include "test.h"
46 #include "lapi/syscalls.h"
47
48 #define cleanup tst_exit
49
50 char *TCID = "timerfd01";
51
52 /*
53 * This were good at the time of 2.6.23-rc7 ...
54 *
55 * #ifdef __NR_timerfd
56 *
57 * ... but is not now with 2.6.25
58 */
59 #ifdef __NR_timerfd_create
60
61 /* Definitions from include/linux/timerfd.h */
62 #define TFD_TIMER_ABSTIME (1 << 0)
63
64 struct tmr_type {
65 int id;
66 char const *name;
67 };
68
getustime(int clockid)69 unsigned long long getustime(int clockid)
70 {
71 struct timespec tp;
72
73 if (clock_gettime((clockid_t) clockid, &tp)) {
74 perror("clock_gettime");
75 return 0;
76 }
77
78 return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
79 }
80
set_timespec(struct timespec * tmr,unsigned long long ustime)81 void set_timespec(struct timespec *tmr, unsigned long long ustime)
82 {
83
84 tmr->tv_sec = (time_t) (ustime / 1000000ULL);
85 tmr->tv_nsec = (long)(1000ULL * (ustime % 1000000ULL));
86 }
87
timerfd_create(int clockid,int flags)88 int timerfd_create(int clockid, int flags)
89 {
90
91 return ltp_syscall(__NR_timerfd_create, clockid, flags);
92 }
93
timerfd_settime(int ufc,int flags,const struct itimerspec * utmr,struct itimerspec * otmr)94 int timerfd_settime(int ufc, int flags, const struct itimerspec *utmr,
95 struct itimerspec *otmr)
96 {
97
98 return ltp_syscall(__NR_timerfd_settime, ufc, flags, utmr, otmr);
99 }
100
timerfd_gettime(int ufc,struct itimerspec * otmr)101 int timerfd_gettime(int ufc, struct itimerspec *otmr)
102 {
103
104 return ltp_syscall(__NR_timerfd_gettime, ufc, otmr);
105 }
106
waittmr(int tfd,int timeo)107 long waittmr(int tfd, int timeo)
108 {
109 u_int64_t ticks;
110 struct pollfd pfd;
111
112 pfd.fd = tfd;
113 pfd.events = POLLIN;
114 pfd.revents = 0;
115 if (poll(&pfd, 1, timeo) < 0) {
116 perror("poll");
117 return -1;
118 }
119 if ((pfd.revents & POLLIN) == 0) {
120 fprintf(stdout, "no ticks happened\n");
121 return -1;
122 }
123 if (read(tfd, &ticks, sizeof(ticks)) != sizeof(ticks)) {
124 perror("timerfd read");
125 return -1;
126 }
127
128 return ticks;
129 }
130
131 int TST_TOTAL = 3;
132
main(int ac,char ** av)133 int main(int ac, char **av)
134 {
135 int tfd;
136 unsigned int i;
137 long ticks;
138 unsigned long long tnow, ttmr;
139 u_int64_t uticks;
140 struct itimerspec tmr;
141 struct tmr_type clks[] = {
142 {CLOCK_MONOTONIC, "CLOCK MONOTONIC"},
143 {CLOCK_REALTIME, "CLOCK REALTIME"},
144 };
145
146 tst_parse_opts(ac, av, NULL, NULL);
147
148 if ((tst_kvercmp(2, 6, 25)) < 0) {
149 tst_resm(TCONF, "This test can only run on kernels that are ");
150 tst_resm(TCONF, "2.6.25 and higher");
151 exit(0);
152 }
153
154 for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++) {
155 fprintf(stdout,
156 "\n\n---------------------------------------\n");
157 fprintf(stdout, "| testing %s\n", clks[i].name);
158 fprintf(stdout, "---------------------------------------\n\n");
159
160 fprintf(stdout, "relative timer test (at 500 ms) ...\n");
161 set_timespec(&tmr.it_value, 500 * 1000);
162 set_timespec(&tmr.it_interval, 0);
163 tnow = getustime(clks[i].id);
164 if ((tfd = timerfd_create(clks[i].id, 0)) == -1) {
165 perror("timerfd");
166 return 1;
167 }
168 fprintf(stdout, "timerfd = %d\n", tfd);
169
170 if (timerfd_settime(tfd, 0, &tmr, NULL)) {
171 perror("timerfd_settime");
172 return 1;
173 }
174
175 fprintf(stdout, "wating timer ...\n");
176 ticks = waittmr(tfd, -1);
177 ttmr = getustime(clks[i].id);
178 if (ticks <= 0)
179 fprintf(stdout, "whooops! no timer showed up!\n");
180 else
181 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
182 ticks, (ttmr - tnow) / 1000);
183
184 fprintf(stdout, "absolute timer test (at 500 ms) ...\n");
185 tnow = getustime(clks[i].id);
186 set_timespec(&tmr.it_value, tnow + 500 * 1000);
187 set_timespec(&tmr.it_interval, 0);
188 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
189 perror("timerfd_settime");
190 return 1;
191 }
192
193 fprintf(stdout, "wating timer ...\n");
194 ticks = waittmr(tfd, -1);
195 ttmr = getustime(clks[i].id);
196 if (ticks <= 0)
197 fprintf(stdout, "whooops! no timer showed up!\n");
198 else
199 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
200 ticks, (ttmr - tnow) / 1000);
201
202 fprintf(stdout, "sequential timer test (100 ms clock) ...\n");
203 tnow = getustime(clks[i].id);
204 set_timespec(&tmr.it_value, tnow + 100 * 1000);
205 set_timespec(&tmr.it_interval, 100 * 1000);
206 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
207 perror("timerfd_settime");
208 return 1;
209 }
210
211 fprintf(stdout, "sleeping 1 second ...\n");
212 sleep(1);
213 if (timerfd_gettime(tfd, &tmr)) {
214 perror("timerfd_gettime");
215 return 1;
216 }
217 fprintf(stdout, "timerfd_gettime returned:\n"
218 "\tit_value = { %ld, %ld } it_interval = { %ld, %ld }\n",
219 (long)tmr.it_value.tv_sec, (long)tmr.it_value.tv_nsec,
220 (long)tmr.it_interval.tv_sec,
221 (long)tmr.it_interval.tv_nsec);
222 fprintf(stdout, "sleeping 1 second ...\n");
223 sleep(1);
224
225 fprintf(stdout, "wating timer ...\n");
226 ticks = waittmr(tfd, -1);
227 ttmr = getustime(clks[i].id);
228 if (ticks <= 0)
229 fprintf(stdout, "whooops! no timer showed up!\n");
230 else
231 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
232 ticks, (ttmr - tnow) / 1000);
233
234 fprintf(stdout, "O_NONBLOCK test ...\n");
235 tnow = getustime(clks[i].id);
236 set_timespec(&tmr.it_value, 100 * 1000);
237 set_timespec(&tmr.it_interval, 0);
238 if (timerfd_settime(tfd, 0, &tmr, NULL)) {
239 perror("timerfd_settime");
240 return 1;
241 }
242 fprintf(stdout, "timerfd = %d\n", tfd);
243
244 fprintf(stdout, "wating timer (flush the single tick) ...\n");
245 ticks = waittmr(tfd, -1);
246 ttmr = getustime(clks[i].id);
247 if (ticks <= 0)
248 fprintf(stdout, "whooops! no timer showed up!\n");
249 else
250 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
251 ticks, (ttmr - tnow) / 1000);
252
253 fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
254
255 if (read(tfd, &uticks, sizeof(uticks)) > 0)
256 fprintf(stdout,
257 "whooops! timer ticks not zero when should have been\n");
258 else if (errno != EAGAIN)
259 fprintf(stdout,
260 "whooops! bad errno value (%d = '%s')!\n",
261 errno, strerror(errno));
262 else
263 fprintf(stdout, "success\n");
264
265 fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
266
267 close(tfd);
268 }
269
270 tst_exit();
271 }
272
273 #else
274 int TST_TOTAL = 0;
275
main(void)276 int main(void)
277 {
278
279 tst_brkm(TCONF, NULL,
280 "This test needs a kernel that has timerfd syscall.");
281 }
282 #endif
283