• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2016 Fujitsu Ltd.
3  * Author: Guangwen Feng <fenggw-fnst@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 
main(int ac,char ** av)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 
setup(void)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 
cleanup(void)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 
help(void)142 static void help(void)
143 {
144 	printf("  -s      epoll_wait() timeout length in ms\n");
145 }
146