• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "linux_syscall_numbers.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 i, tfd;
136 	long ticks;
137 	unsigned long long tnow, ttmr;
138 	u_int64_t uticks;
139 	struct itimerspec tmr;
140 	struct tmr_type clks[] = {
141 		{CLOCK_MONOTONIC, "CLOCK MONOTONIC"},
142 		{CLOCK_REALTIME, "CLOCK REALTIME"},
143 	};
144 
145 	if ((tst_kvercmp(2, 6, 25)) < 0) {
146 		tst_resm(TCONF, "This test can only run on kernels that are ");
147 		tst_resm(TCONF, "2.6.25 and higher");
148 		exit(0);
149 	}
150 
151 	for (i = 0; i < sizeof(clks) / sizeof(clks[0]); i++) {
152 		fprintf(stdout,
153 			"\n\n---------------------------------------\n");
154 		fprintf(stdout, "| testing %s\n", clks[i].name);
155 		fprintf(stdout, "---------------------------------------\n\n");
156 
157 		fprintf(stdout, "relative timer test (at 500 ms) ...\n");
158 		set_timespec(&tmr.it_value, 500 * 1000);
159 		set_timespec(&tmr.it_interval, 0);
160 		tnow = getustime(clks[i].id);
161 		if ((tfd = timerfd_create(clks[i].id, 0)) == -1) {
162 			perror("timerfd");
163 			return 1;
164 		}
165 		fprintf(stdout, "timerfd = %d\n", tfd);
166 
167 		if (timerfd_settime(tfd, 0, &tmr, NULL)) {
168 			perror("timerfd_settime");
169 			return 1;
170 		}
171 
172 		fprintf(stdout, "wating timer ...\n");
173 		ticks = waittmr(tfd, -1);
174 		ttmr = getustime(clks[i].id);
175 		if (ticks <= 0)
176 			fprintf(stdout, "whooops! no timer showed up!\n");
177 		else
178 			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
179 				ticks, (ttmr - tnow) / 1000);
180 
181 		fprintf(stdout, "absolute timer test (at 500 ms) ...\n");
182 		tnow = getustime(clks[i].id);
183 		set_timespec(&tmr.it_value, tnow + 500 * 1000);
184 		set_timespec(&tmr.it_interval, 0);
185 		if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
186 			perror("timerfd_settime");
187 			return 1;
188 		}
189 
190 		fprintf(stdout, "wating timer ...\n");
191 		ticks = waittmr(tfd, -1);
192 		ttmr = getustime(clks[i].id);
193 		if (ticks <= 0)
194 			fprintf(stdout, "whooops! no timer showed up!\n");
195 		else
196 			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
197 				ticks, (ttmr - tnow) / 1000);
198 
199 		fprintf(stdout, "sequential timer test (100 ms clock) ...\n");
200 		tnow = getustime(clks[i].id);
201 		set_timespec(&tmr.it_value, tnow + 100 * 1000);
202 		set_timespec(&tmr.it_interval, 100 * 1000);
203 		if (timerfd_settime(tfd, TFD_TIMER_ABSTIME, &tmr, NULL)) {
204 			perror("timerfd_settime");
205 			return 1;
206 		}
207 
208 		fprintf(stdout, "sleeping 1 second ...\n");
209 		sleep(1);
210 		if (timerfd_gettime(tfd, &tmr)) {
211 			perror("timerfd_gettime");
212 			return 1;
213 		}
214 		fprintf(stdout, "timerfd_gettime returned:\n"
215 			"\tit_value = { %ld, %ld } it_interval = { %ld, %ld }\n",
216 			(long)tmr.it_value.tv_sec, (long)tmr.it_value.tv_nsec,
217 			(long)tmr.it_interval.tv_sec,
218 			(long)tmr.it_interval.tv_nsec);
219 		fprintf(stdout, "sleeping 1 second ...\n");
220 		sleep(1);
221 
222 		fprintf(stdout, "wating timer ...\n");
223 		ticks = waittmr(tfd, -1);
224 		ttmr = getustime(clks[i].id);
225 		if (ticks <= 0)
226 			fprintf(stdout, "whooops! no timer showed up!\n");
227 		else
228 			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
229 				ticks, (ttmr - tnow) / 1000);
230 
231 		fprintf(stdout, "O_NONBLOCK test ...\n");
232 		tnow = getustime(clks[i].id);
233 		set_timespec(&tmr.it_value, 100 * 1000);
234 		set_timespec(&tmr.it_interval, 0);
235 		if (timerfd_settime(tfd, 0, &tmr, NULL)) {
236 			perror("timerfd_settime");
237 			return 1;
238 		}
239 		fprintf(stdout, "timerfd = %d\n", tfd);
240 
241 		fprintf(stdout, "wating timer (flush the single tick) ...\n");
242 		ticks = waittmr(tfd, -1);
243 		ttmr = getustime(clks[i].id);
244 		if (ticks <= 0)
245 			fprintf(stdout, "whooops! no timer showed up!\n");
246 		else
247 			fprintf(stdout, "got timer ticks (%ld) after %llu ms\n",
248 				ticks, (ttmr - tnow) / 1000);
249 
250 		fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) | O_NONBLOCK);
251 
252 		if (read(tfd, &uticks, sizeof(uticks)) > 0)
253 			fprintf(stdout,
254 				"whooops! timer ticks not zero when should have been\n");
255 		else if (errno != EAGAIN)
256 			fprintf(stdout,
257 				"whooops! bad errno value (%d = '%s')!\n",
258 				errno, strerror(errno));
259 		else
260 			fprintf(stdout, "success\n");
261 
262 		fcntl(tfd, F_SETFL, fcntl(tfd, F_GETFL, 0) & ~O_NONBLOCK);
263 
264 		close(tfd);
265 	}
266 
267 	tst_exit();
268 }
269 
270 #else
271 int TST_TOTAL = 0;
272 
main(void)273 int main(void)
274 {
275 
276 	tst_brkm(TCONF, NULL,
277 		 "This test needs a kernel that has timerfd syscall.");
278 }
279 #endif
280