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