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