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