2 * timerfd() test by Davide Libenzi (test app for timerfd)
3 * Copyright (C) 2007 Davide Libenzi
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.
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.
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
19 * Davide Libenzi <davidel@xmailserver.org>
22 * $ gcc -o timerfd-test2 timerfd-test2.c -lrt
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 * 2016-04-08 Deintegrated from LTP by Barret Rhoden <brho@cs.berkeley.edu>
30 * Ported to Akaros. Added a few more tests.
34 #include <sys/syscall.h>
35 #include <sys/types.h>
36 #include <sys/signal.h>
48 #include <sys/timerfd.h>
49 #include <sys/select.h>
50 #include <benchutil/alarm.h>
51 #include <parlib/uthread.h>
58 unsigned long long getustime(int clockid)
62 if (clock_gettime((clockid_t) clockid, &tp)) {
63 perror("clock_gettime");
67 return 1000000ULL * tp.tv_sec + tp.tv_nsec / 1000;
70 void set_timespec(struct timespec *tmr, unsigned long long ustime)
73 tmr->tv_sec = (time_t) (ustime / 1000000ULL);
74 tmr->tv_nsec = (long)(1000ULL * (ustime % 1000000ULL));
78 long waittmr(int tfd, int timeo)
82 struct timeval tv, *timeout = 0;
88 tv.tv_sec = timeo / 1000;
89 tv.tv_usec = (timeo % 1000) * 1000;
92 ret = select(tfd + 1, &rfds, 0, 0, timeout);
98 fprintf(stdout, "no ticks happened\n");
101 if (read(tfd, &ticks, sizeof(ticks)) != sizeof(ticks)) {
102 perror("timerfd read");
108 int main(int ac, char **av)
112 unsigned long long tnow, ttmr;
114 struct itimerspec tmr;
115 struct tmr_type clks[] = {
116 {CLOCK_MONOTONIC, "CLOCK MONOTONIC"},
117 {CLOCK_REALTIME, "CLOCK REALTIME"},
120 for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++) {
122 "\n\n---------------------------------------\n");
123 fprintf(stdout, "| testing %s\n", clks[i].name);
124 fprintf(stdout, "---------------------------------------\n\n");
126 fprintf(stdout, "relative timer test (at 500 ms) ...\n");
127 set_timespec(&tmr.it_value, 500 * 1000);
128 set_timespec(&tmr.it_interval, 0);
129 tnow = getustime(clks[i].id);
130 if ((tfd = timerfd_create(clks[i].id, 0)) == -1) {
134 fprintf(stdout, "timerfd = %d\n", tfd);
136 if (timerfd_settime(tfd, 0, &tmr, NULL)) {
137 perror("timerfd_settime");
141 fprintf(stdout, "waiting timer ...\n");
142 ticks = waittmr(tfd, -1);
143 ttmr = getustime(clks[i].id);
145 fprintf(stdout, "whooops! no timer showed up!\n");
147 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
148 ticks, (ttmr - tnow) / 1000);
150 fprintf(stdout, "absolute timer test (at 500 ms) ...\n");
151 tnow = getustime(clks[i].id);
152 set_timespec(&tmr.it_value, tnow + 500 * 1000);
153 set_timespec(&tmr.it_interval, 0);
154 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
155 perror("timerfd_settime");
159 fprintf(stdout, "waiting timer ...\n");
160 ticks = waittmr(tfd, -1);
161 ttmr = getustime(clks[i].id);
163 fprintf(stdout, "whooops! no timer showed up!\n");
165 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
166 ticks, (ttmr - tnow) / 1000);
168 fprintf(stdout, "sequential timer test (100 ms clock) ...\n");
169 tnow = getustime(clks[i].id);
170 set_timespec(&tmr.it_value, tnow + 100 * 1000);
171 set_timespec(&tmr.it_interval, 100 * 1000);
172 if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
173 perror("timerfd_settime");
177 fprintf(stdout, "sleeping 1 second ...\n");
179 if (timerfd_gettime(tfd, &tmr)) {
180 perror("timerfd_gettime");
183 fprintf(stdout, "timerfd_gettime returned:\n"
184 "\tit_value = { %ld, %ld } it_interval = { %ld, %ld }\n",
185 (long)tmr.it_value.tv_sec, (long)tmr.it_value.tv_nsec,
186 (long)tmr.it_interval.tv_sec,
187 (long)tmr.it_interval.tv_nsec);
188 fprintf(stdout, "sleeping 1 second ...\n");
191 fprintf(stdout, "waiting timer ...\n");
192 ticks = waittmr(tfd, -1);
193 ttmr = getustime(clks[i].id);
195 fprintf(stdout, "whooops! no timer showed up!\n");
197 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
198 ticks, (ttmr - tnow) / 1000);
200 fprintf(stdout, "O_NONBLOCK test ...\n");
201 tnow = getustime(clks[i].id);
202 set_timespec(&tmr.it_value, 100 * 1000);
203 set_timespec(&tmr.it_interval, 0);
204 if (timerfd_settime(tfd, 0, &tmr, NULL)) {
205 perror("timerfd_settime");
208 fprintf(stdout, "timerfd = %d\n", tfd);
210 fprintf(stdout, "waiting timer (flush the single tick) ...\n");
211 ticks = waittmr(tfd, -1);
212 ttmr = getustime(clks[i].id);
214 fprintf(stdout, "whooops! no timer showed up!\n");
216 fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
217 ticks, (ttmr - tnow) / 1000);
219 fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
221 if (read(tfd, &uticks, sizeof(uticks)) > 0)
223 "whooops! timer ticks not zero when should have been\n");
224 else if (errno != EAGAIN)
226 "whooops! bad errno value (%d = '%s')!\n",
227 errno, strerror(errno));
229 fprintf(stdout, "success\n");
231 /* try a select loop with O_NONBLOCK */
233 bool has_selected = FALSE;
238 set_timespec(&tmr.it_value, 1000000);
239 set_timespec(&tmr.it_interval, 0);
240 if (timerfd_settime(tfd, 0, &tmr, NULL)) {
241 perror("timerfd_settime");
245 ret = read(tfd, &uticks, sizeof(uticks));
247 if (errno != EAGAIN) {
248 perror("select read");
252 if (ret != sizeof(uticks)) {
253 fprintf(stdout, "short read! (bad)\n");
259 if (select(tfd + 1, &rfds, 0, 0, 0) < 0) {
266 fprintf(stdout, "Failed to try to select!\n");
269 fprintf(stdout, "more success\n");
270 fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
272 /* let's make sure it actually blocks too. */
273 struct alarm_waiter waiter;
275 init_awaiter(&waiter, alarm_abort_sysc);
276 waiter.data = current_uthread;
277 set_awaiter_rel(&waiter, 1000000);
279 set_timespec(&tmr.it_value, 10000000);
280 set_timespec(&tmr.it_interval, 0);
281 if (timerfd_settime(tfd, 0, &tmr, NULL)) {
282 perror("timerfd_settime");
286 ret = read(tfd, &uticks, sizeof(uticks));
287 unset_alarm(&waiter);
289 fprintf(stdout, "Failed to block when we should have!\n");
292 fprintf(stdout, "done (still success)\n");