Home | History | Annotate | Download | only in epoll_wait
      1 /*
      2  * Copyright (c) 2016 Fujitsu Ltd.
      3  * Author: Guangwen Feng <fenggw-fnst (at) cn.fujitsu.com>
      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
     13  * the 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.
     17  */
     18 
     19 /*
     20  * Description:
     21  *  Check that epoll_wait(2) timeouts correctly.
     22  */
     23 
     24 #include <sys/epoll.h>
     25 #include <unistd.h>
     26 #include <errno.h>
     27 
     28 #include "test.h"
     29 #include "safe_macros.h"
     30 
     31 char *TCID = "epoll_wait02";
     32 int TST_TOTAL = 1;
     33 
     34 static int epfd, fds[2];
     35 static char *opt_sleep_ms;
     36 static struct epoll_event epevs[1] = {
     37 	{.events = EPOLLIN}
     38 };
     39 
     40 static option_t opts[] = {
     41 	{"s:", NULL, &opt_sleep_ms},
     42 	{NULL, NULL, NULL}
     43 };
     44 
     45 static void setup(void);
     46 static void cleanup(void);
     47 static void help(void);
     48 
     49 int main(int ac, char **av)
     50 {
     51 	int lc, threshold;
     52 	long long elapsed_ms, sleep_ms = 100;
     53 
     54 	tst_parse_opts(ac, av, opts, help);
     55 
     56 	if (opt_sleep_ms) {
     57 		sleep_ms = atoll(opt_sleep_ms);
     58 
     59 		if (sleep_ms == 0) {
     60 			tst_brkm(TBROK, NULL,
     61 				 "Invalid timeout '%s'", opt_sleep_ms);
     62 		}
     63 	}
     64 
     65 	threshold = sleep_ms / 100 + 10;
     66 
     67 	setup();
     68 
     69 	for (lc = 0; TEST_LOOPING(lc); lc++) {
     70 		tst_count = 0;
     71 
     72 		tst_timer_start(CLOCK_MONOTONIC);
     73 		TEST(epoll_wait(epfd, epevs, 1, sleep_ms));
     74 		tst_timer_stop();
     75 
     76 		if (TEST_RETURN == -1) {
     77 			tst_resm(TFAIL | TTERRNO, "epoll_wait() failed");
     78 			continue;
     79 		}
     80 
     81 		if (TEST_RETURN != 0) {
     82 			tst_resm(TFAIL, "epoll_wait() returned %li, expected 0",
     83 				 TEST_RETURN);
     84 			continue;
     85 		}
     86 
     87 		elapsed_ms = tst_timer_elapsed_ms();
     88 
     89 		if (elapsed_ms < sleep_ms) {
     90 			tst_resm(TFAIL, "epoll_wait() woken up too early %llims, "
     91 				 "expected %llims", elapsed_ms, sleep_ms);
     92 			continue;
     93 		}
     94 
     95 		if (elapsed_ms - sleep_ms > threshold) {
     96 			tst_resm(TFAIL, "epoll_wait() slept too long %llims, "
     97 				 "expected %llims, threshold %i",
     98 				 elapsed_ms, sleep_ms, threshold);
     99 			continue;
    100 		}
    101 
    102 		tst_resm(TPASS, "epoll_wait() slept %llims, expected %llims, "
    103 			 "threshold %i", elapsed_ms, sleep_ms, threshold);
    104 	}
    105 
    106 	cleanup();
    107 	tst_exit();
    108 }
    109 
    110 static void setup(void)
    111 {
    112 	tst_timer_check(CLOCK_MONOTONIC);
    113 
    114 	SAFE_PIPE(NULL, fds);
    115 
    116 	epfd = epoll_create(1);
    117 	if (epfd == -1) {
    118 		tst_brkm(TBROK | TERRNO, cleanup,
    119 			 "failed to create epoll instance");
    120 	}
    121 
    122 	epevs[0].data.fd = fds[0];
    123 
    124 	if (epoll_ctl(epfd, EPOLL_CTL_ADD, fds[0], &epevs[0])) {
    125 		tst_brkm(TBROK | TERRNO, cleanup,
    126 			 "failed to register epoll target");
    127 	}
    128 }
    129 
    130 static void cleanup(void)
    131 {
    132 	if (epfd > 0 && close(epfd))
    133 		tst_resm(TWARN | TERRNO, "failed to close epfd");
    134 
    135 	if (close(fds[0]))
    136 		tst_resm(TWARN | TERRNO, "close(fds[0]) failed");
    137 
    138 	if (close(fds[1]))
    139 		tst_resm(TWARN | TERRNO, "close(fds[1]) failed");
    140 }
    141 
    142 static void help(void)
    143 {
    144 	printf("  -s      epoll_wait() timeout length in ms\n");
    145 }
    146