• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2016 Fujitsu Ltd.
4  * Author: Xiao Yang <yangx.jy@cn.fujitsu.com>
5  */
6 
7 /*\
8  * [Description]
9  *
10  * Check the basic functionality of the epoll_ctl:
11  *
12  * - When epoll_ctl succeeds to register fd on the epoll instance and associates
13  * event with fd, epoll_wait will get registered fd and event correctly.
14  * - When epoll_ctl succeeds to change event which is related to fd, epoll_wait
15  * will get changed event correctly.
16  * - When epoll_ctl succeeds to deregister fd from the epoll instance epoll_wait
17  * won't get deregistered fd and event.
18  */
19 
20 #include <poll.h>
21 #include <sys/epoll.h>
22 
23 #include "tst_test.h"
24 
25 static int epfd;
26 static int fd[2];
27 
28 static struct epoll_event events[3] = {
29 	{.events = EPOLLIN},
30 	{.events = EPOLLOUT},
31 	{.events = EPOLLIN}
32 };
33 
setup(void)34 static void setup(void)
35 {
36 	epfd = epoll_create(2);
37 	if (epfd == -1)
38 		tst_brk(TBROK | TERRNO, "fail to create epoll instance");
39 
40 	SAFE_PIPE(fd);
41 
42 	events[0].data.fd = fd[0];
43 	events[1].data.fd = fd[1];
44 	events[2].data.fd = fd[1];
45 }
46 
cleanup(void)47 static void cleanup(void)
48 {
49 	if (epfd > 0)
50 		SAFE_CLOSE(epfd);
51 
52 	if (fd[0] > 0)
53 		SAFE_CLOSE(fd[0]);
54 
55 	if (fd[1] > 0)
56 		SAFE_CLOSE(fd[1]);
57 }
58 
has_event(struct epoll_event * epvs,int len,int fd,unsigned int events)59 static int has_event(struct epoll_event *epvs, int len,
60 	int fd, unsigned int events)
61 {
62 	int i;
63 
64 	for (i = 0; i < len; i++) {
65 		if ((epvs[i].data.fd == fd) && (epvs[i].events == events))
66 			return 1;
67 	}
68 
69 	return 0;
70 }
71 
check_epoll_ctl(int opt,int exp_num)72 static void check_epoll_ctl(int opt, int exp_num)
73 {
74 	int res;
75 	unsigned int events;
76 	char write_buf[] = "test";
77 	char read_buf[sizeof(write_buf)];
78 	struct epoll_event res_evs[2];
79 
80 	events = EPOLLIN;
81 	if (exp_num == 2)
82 		events |= EPOLLOUT;
83 
84 	SAFE_WRITE(SAFE_WRITE_ALL, fd[1], write_buf, sizeof(write_buf));
85 
86 	while (events) {
87 		int events_matched = 0;
88 
89 		memset(res_evs, 0, sizeof(res_evs));
90 		res = epoll_wait(epfd, res_evs, 2, -1);
91 
92 		if (res <= 0) {
93 			tst_res(TFAIL | TERRNO, "epoll_wait() returned %i",
94 				res);
95 			goto end;
96 		}
97 
98 		if ((events & EPOLLIN) &&
99 		    has_event(res_evs, 2, fd[0], EPOLLIN)) {
100 			events_matched++;
101 			events &= ~EPOLLIN;
102 		}
103 
104 		if ((events & EPOLLOUT) &&
105 		    has_event(res_evs, 2, fd[1], EPOLLOUT)) {
106 			events_matched++;
107 			events &= ~EPOLLOUT;
108 		}
109 
110 		if (res != events_matched) {
111 			tst_res(TFAIL,
112 				"epoll_wait() returned unexpected events");
113 			goto end;
114 		}
115 	}
116 
117 	tst_res(TPASS, "epoll_ctl() succeeds with op %i", opt);
118 
119 end:
120 	SAFE_READ(1, fd[0], read_buf, sizeof(write_buf));
121 }
122 
opera_epoll_ctl(int opt,int fd,struct epoll_event * epvs)123 static void opera_epoll_ctl(int opt, int fd, struct epoll_event *epvs)
124 {
125 	TEST(epoll_ctl(epfd, opt, fd, epvs));
126 	if (TST_RET == -1)
127 		tst_brk(TBROK | TTERRNO, "epoll_ctl() fails with op %i", opt);
128 }
129 
verify_epoll_ctl(void)130 static void verify_epoll_ctl(void)
131 {
132 	opera_epoll_ctl(EPOLL_CTL_ADD, fd[0], &events[0]);
133 	opera_epoll_ctl(EPOLL_CTL_ADD, fd[1], &events[2]);
134 	check_epoll_ctl(EPOLL_CTL_ADD, 1);
135 	opera_epoll_ctl(EPOLL_CTL_MOD, fd[1], &events[1]);
136 	check_epoll_ctl(EPOLL_CTL_MOD, 2);
137 	opera_epoll_ctl(EPOLL_CTL_DEL, fd[1], &events[1]);
138 	check_epoll_ctl(EPOLL_CTL_DEL, 1);
139 	opera_epoll_ctl(EPOLL_CTL_DEL, fd[0], &events[0]);
140 }
141 
142 static struct tst_test test = {
143 	.setup = setup,
144 	.cleanup = cleanup,
145 	.test_all = verify_epoll_ctl,
146 };
147