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