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