Home | History | Annotate | Download | only in timerfd
      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 (at) 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 (at) xmailserver.org>
     28  *      28/05/2008 Integrated to LTP by Subrata Modak <subrata (at) 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 
     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 
     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 
     88 int timerfd_create(int clockid, int flags)
     89 {
     90 
     91 	return ltp_syscall(__NR_timerfd_create, clockid, flags);
     92 }
     93 
     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 
    101 int timerfd_gettime(int ufc, struct itimerspec *otmr)
    102 {
    103 
    104 	return ltp_syscall(__NR_timerfd_gettime, ufc, otmr);
    105 }
    106 
    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 
    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 
    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