blob: 2c9aa576fe968a706308a803b54102dde386743e [file] [log] [blame]
Tianyu Jiang99dacaa2018-11-27 18:47:00 -08001/*
2 * Copyright 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "BufferHubEventFdTest"
18
19#include <sys/epoll.h>
20#include <sys/eventfd.h>
21
Tianyu Jiang35b37c42018-12-05 13:15:24 -080022#include <array>
Tianyu Jiang99dacaa2018-11-27 18:47:00 -080023#include <condition_variable>
24#include <mutex>
25#include <thread>
26
27#include <gmock/gmock.h>
28#include <gtest/gtest.h>
Tianyu Jiang35b37c42018-12-05 13:15:24 -080029#include <log/log.h>
Tianyu Jiang99dacaa2018-11-27 18:47:00 -080030#include <ui/BufferHubEventFd.h>
31
32namespace android {
33
34namespace {
35
36const int kTimeout = 100;
37const std::chrono::milliseconds kTimeoutMs(kTimeout);
38
39using ::testing::Contains;
40using BufferHubEventFdTest = ::testing::Test;
41
42} // namespace
43
44TEST_F(BufferHubEventFdTest, EventFd_testSingleEpollFd) {
45 BufferHubEventFd eventFd;
46 ASSERT_TRUE(eventFd.isValid());
47
48 base::unique_fd epollFd(epoll_create(64));
49 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
50
51 ASSERT_GE(epollFd.get(), 0);
52 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
53
54 std::array<epoll_event, 1> events;
55 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
56
57 eventFd.signal();
58 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
59
60 // The epoll fd is edge triggered, so it only responds to the eventFd once.
61 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
62}
63
64TEST_F(BufferHubEventFdTest, EventFd_testClear) {
65 BufferHubEventFd eventFd;
66 ASSERT_TRUE(eventFd.isValid());
67
68 base::unique_fd epollFd(epoll_create(64));
69 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
70
71 ASSERT_GE(epollFd.get(), 0);
72 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
73
74 eventFd.signal();
75 eventFd.clear();
76
77 std::array<epoll_event, 1> events;
78 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
79}
80
81TEST_F(BufferHubEventFdTest, EventFd_testDupEventFd) {
82 BufferHubEventFd eventFd;
83 ASSERT_TRUE(eventFd.isValid());
84
85 base::unique_fd epollFd(epoll_create(64));
86 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
87
88 ASSERT_GE(epollFd.get(), 0);
89 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
90
91 // Technically, the dupliated eventFd and the original eventFd are pointing
92 // to the same kernel object. This test signals the duplicated eventFd but epolls the origianl
93 // eventFd.
Fan Xud5855a62019-01-14 15:52:42 -080094 BufferHubEventFd dupedEventFd(dup(eventFd.get()));
Tianyu Jiang99dacaa2018-11-27 18:47:00 -080095 ASSERT_GE(dupedEventFd.get(), 0);
96
97 std::array<epoll_event, 1> events;
98 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
99
Fan Xud5855a62019-01-14 15:52:42 -0800100 dupedEventFd.signal();
Tianyu Jiang99dacaa2018-11-27 18:47:00 -0800101 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
102
103 // The epoll fd is edge triggered, so it only responds to the eventFd once.
104 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
105
Fan Xud5855a62019-01-14 15:52:42 -0800106 dupedEventFd.signal();
Tianyu Jiang99dacaa2018-11-27 18:47:00 -0800107
Fan Xud5855a62019-01-14 15:52:42 -0800108 dupedEventFd.clear();
Tianyu Jiang99dacaa2018-11-27 18:47:00 -0800109 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
110}
111
112TEST_F(BufferHubEventFdTest, EventFd_testTwoEpollFds) {
113 BufferHubEventFd eventFd;
114 ASSERT_TRUE(eventFd.isValid());
115
116 base::unique_fd epollFd1(epoll_create(64));
117 base::unique_fd epollFd2(epoll_create(64));
118 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
119
120 ASSERT_GE(epollFd1.get(), 0);
121 ASSERT_GE(epollFd2.get(), 0);
122
123 // Register the same eventFd to two EpollFds.
124 ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
125 ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
126
127 std::array<epoll_event, 1> events;
128 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
129 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
130
131 eventFd.signal();
132 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
133 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 1);
134
135 // The epoll fd is edge triggered, so it only responds to the eventFd once.
136 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
137 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
138
139 eventFd.signal();
140 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
141
142 eventFd.clear();
143 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
144 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
145}
146
147TEST_F(BufferHubEventFdTest, EventFd_testTwoEventFds) {
148 BufferHubEventFd eventFd1;
149 BufferHubEventFd eventFd2;
150
151 ASSERT_TRUE(eventFd1.isValid());
152 ASSERT_TRUE(eventFd2.isValid());
153
154 base::unique_fd epollFd(epoll_create(64));
155 epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
156 epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
157
158 ASSERT_GE(epollFd.get(), 0);
159 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
160 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
161
162 std::array<epoll_event, 2> events;
163 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
164
165 // Signal one by one.
166 eventFd1.signal();
167 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
168 EXPECT_EQ(events[0].data.u32, e1.data.u32);
169
170 eventFd2.signal();
171 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
172 EXPECT_EQ(events[0].data.u32, e2.data.u32);
173
174 // Signal both.
175 eventFd1.signal();
176 eventFd2.signal();
177 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 2);
178
179 uint32_t u32s[] = {events[0].data.u32, events[1].data.u32};
180 EXPECT_THAT(u32s, Contains(e1.data.u32));
181 EXPECT_THAT(u32s, Contains(e2.data.u32));
182
183 // The epoll fd is edge triggered, so it only responds to the eventFd once.
184 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
185
186 eventFd1.signal();
187 eventFd2.signal();
188 eventFd2.clear();
189 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
190}
191
192TEST_F(BufferHubEventFdTest, EventFd_testPollingThreadWithTwoEventFds) {
193 BufferHubEventFd eventFd1;
194 BufferHubEventFd eventFd2;
195
196 ASSERT_TRUE(eventFd1.isValid());
197 ASSERT_TRUE(eventFd2.isValid());
198
199 base::unique_fd epollFd(epoll_create(64));
200 epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
201 epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
202
203 ASSERT_GE(epollFd.get(), 0);
204 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
205 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
206
207 int countEvent1 = 0;
208 int countEvent2 = 0;
209 std::atomic<bool> stop{false};
210 std::mutex mx;
211 std::condition_variable cv;
212
213 std::thread pollingThread([&] {
214 std::array<epoll_event, 2> events;
215 while (true) {
216 if (stop.load()) {
217 break;
218 }
219 int ret = epoll_wait(epollFd.get(), events.data(), events.size(), kTimeout);
220 ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
221
222 std::lock_guard<std::mutex> lock(mx);
223 for (int i = 0; i < ret; i++) {
224 if (events[i].data.u32 == e1.data.u32) {
225 countEvent1++;
226 cv.notify_one();
227 } else if (events[i].data.u32 == e2.data.u32) {
228 countEvent2++;
229 cv.notify_one();
230 }
231 }
232 }
233 });
234
235 {
236 std::unique_lock<std::mutex> lock(mx);
237
238 eventFd1.signal();
239 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 1; }));
240
241 eventFd1.signal();
242 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 2; }));
243
244 eventFd2.signal();
245 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 1; }));
246
247 eventFd1.clear();
248 eventFd2.clear();
249 EXPECT_EQ(countEvent1, 2);
250 EXPECT_EQ(countEvent2, 1);
251
252 eventFd1.signal();
253 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 3; }));
254
255 eventFd2.signal();
256 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 2; }));
257 }
258
259 stop.store(true);
260 pollingThread.join();
261}
262
263TEST_F(BufferHubEventFdTest, EventFd_testTwoPollingThreads) {
264 BufferHubEventFd eventFd;
265 ASSERT_TRUE(eventFd.isValid());
266
267 base::unique_fd epollFd1(epoll_create(64));
268 base::unique_fd epollFd2(epoll_create(64));
269 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
270
271 ASSERT_GE(epollFd1.get(), 0);
272 ASSERT_GE(epollFd2.get(), 0);
273
274 // Register the same eventFd to two EpollFds.
275 ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
276 ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
277
278 int countEpoll1 = 0;
279 int countEpoll2 = 0;
280 std::atomic<bool> stop{false};
281 std::mutex mx;
282 std::condition_variable cv;
283
284 std::thread pollingThread1([&] {
285 std::array<epoll_event, 1> events;
286 while (!stop.load()) {
287 int ret = epoll_wait(epollFd1.get(), events.data(), events.size(), kTimeout);
288 ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
289
290 if (ret > 0) {
291 std::lock_guard<std::mutex> lock(mx);
292 countEpoll1++;
293 cv.notify_one();
294 }
295 }
296 });
297
298 std::thread pollingThread2([&] {
299 std::array<epoll_event, 1> events;
300 while (!stop.load()) {
301 int ret = epoll_wait(epollFd2.get(), events.data(), events.size(), kTimeout);
302 ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
303
304 if (ret > 0) {
305 std::lock_guard<std::mutex> lock(mx);
306 countEpoll2++;
307 cv.notify_one();
308 }
309 }
310 });
311
312 {
313 std::unique_lock<std::mutex> lock(mx);
314
315 eventFd.signal();
316 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 1; }));
317 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 1; }));
318
319 eventFd.signal();
320 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 2; }));
321 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 2; }));
322
323 eventFd.clear();
324 EXPECT_EQ(countEpoll1, 2);
325 EXPECT_EQ(countEpoll2, 2);
326
327 eventFd.signal();
328 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 3; }));
329 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 3; }));
330 }
331
332 stop.store(true);
333 pollingThread1.join();
334 pollingThread2.join();
335}
336
337} // namespace android