blob: 92fb33ff48902ae4c990e5da9406b7e92213ccc6 [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.
94 base::unique_fd dupedEventFd(dup(eventFd.get()));
95 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
100 eventfd_write(dupedEventFd.get(), 1);
101 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
106 eventfd_write(dupedEventFd.get(), 1);
107
108 eventfd_t value;
109 eventfd_read(dupedEventFd.get(), &value);
110 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
111}
112
113TEST_F(BufferHubEventFdTest, EventFd_testTwoEpollFds) {
114 BufferHubEventFd eventFd;
115 ASSERT_TRUE(eventFd.isValid());
116
117 base::unique_fd epollFd1(epoll_create(64));
118 base::unique_fd epollFd2(epoll_create(64));
119 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
120
121 ASSERT_GE(epollFd1.get(), 0);
122 ASSERT_GE(epollFd2.get(), 0);
123
124 // Register the same eventFd to two EpollFds.
125 ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
126 ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
127
128 std::array<epoll_event, 1> events;
129 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
130 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
131
132 eventFd.signal();
133 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
134 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 1);
135
136 // The epoll fd is edge triggered, so it only responds to the eventFd once.
137 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
138 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
139
140 eventFd.signal();
141 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 1);
142
143 eventFd.clear();
144 EXPECT_EQ(epoll_wait(epollFd1.get(), events.data(), events.size(), 0), 0);
145 EXPECT_EQ(epoll_wait(epollFd2.get(), events.data(), events.size(), 0), 0);
146}
147
148TEST_F(BufferHubEventFdTest, EventFd_testTwoEventFds) {
149 BufferHubEventFd eventFd1;
150 BufferHubEventFd eventFd2;
151
152 ASSERT_TRUE(eventFd1.isValid());
153 ASSERT_TRUE(eventFd2.isValid());
154
155 base::unique_fd epollFd(epoll_create(64));
156 epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
157 epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
158
159 ASSERT_GE(epollFd.get(), 0);
160 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
161 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
162
163 std::array<epoll_event, 2> events;
164 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
165
166 // Signal one by one.
167 eventFd1.signal();
168 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
169 EXPECT_EQ(events[0].data.u32, e1.data.u32);
170
171 eventFd2.signal();
172 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
173 EXPECT_EQ(events[0].data.u32, e2.data.u32);
174
175 // Signal both.
176 eventFd1.signal();
177 eventFd2.signal();
178 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 2);
179
180 uint32_t u32s[] = {events[0].data.u32, events[1].data.u32};
181 EXPECT_THAT(u32s, Contains(e1.data.u32));
182 EXPECT_THAT(u32s, Contains(e2.data.u32));
183
184 // The epoll fd is edge triggered, so it only responds to the eventFd once.
185 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 0);
186
187 eventFd1.signal();
188 eventFd2.signal();
189 eventFd2.clear();
190 EXPECT_EQ(epoll_wait(epollFd.get(), events.data(), events.size(), 0), 1);
191}
192
193TEST_F(BufferHubEventFdTest, EventFd_testPollingThreadWithTwoEventFds) {
194 BufferHubEventFd eventFd1;
195 BufferHubEventFd eventFd2;
196
197 ASSERT_TRUE(eventFd1.isValid());
198 ASSERT_TRUE(eventFd2.isValid());
199
200 base::unique_fd epollFd(epoll_create(64));
201 epoll_event e1 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 1}};
202 epoll_event e2 = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 2}};
203
204 ASSERT_GE(epollFd.get(), 0);
205 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd1.get(), &e1), 0);
206 ASSERT_EQ(epoll_ctl(epollFd.get(), EPOLL_CTL_ADD, eventFd2.get(), &e2), 0);
207
208 int countEvent1 = 0;
209 int countEvent2 = 0;
210 std::atomic<bool> stop{false};
211 std::mutex mx;
212 std::condition_variable cv;
213
214 std::thread pollingThread([&] {
215 std::array<epoll_event, 2> events;
216 while (true) {
217 if (stop.load()) {
218 break;
219 }
220 int ret = epoll_wait(epollFd.get(), events.data(), events.size(), kTimeout);
221 ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
222
223 std::lock_guard<std::mutex> lock(mx);
224 for (int i = 0; i < ret; i++) {
225 if (events[i].data.u32 == e1.data.u32) {
226 countEvent1++;
227 cv.notify_one();
228 } else if (events[i].data.u32 == e2.data.u32) {
229 countEvent2++;
230 cv.notify_one();
231 }
232 }
233 }
234 });
235
236 {
237 std::unique_lock<std::mutex> lock(mx);
238
239 eventFd1.signal();
240 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 1; }));
241
242 eventFd1.signal();
243 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 2; }));
244
245 eventFd2.signal();
246 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 1; }));
247
248 eventFd1.clear();
249 eventFd2.clear();
250 EXPECT_EQ(countEvent1, 2);
251 EXPECT_EQ(countEvent2, 1);
252
253 eventFd1.signal();
254 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent1 == 3; }));
255
256 eventFd2.signal();
257 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEvent2 == 2; }));
258 }
259
260 stop.store(true);
261 pollingThread.join();
262}
263
264TEST_F(BufferHubEventFdTest, EventFd_testTwoPollingThreads) {
265 BufferHubEventFd eventFd;
266 ASSERT_TRUE(eventFd.isValid());
267
268 base::unique_fd epollFd1(epoll_create(64));
269 base::unique_fd epollFd2(epoll_create(64));
270 epoll_event e = {.events = EPOLLIN | EPOLLET, .data = {.u32 = 0}};
271
272 ASSERT_GE(epollFd1.get(), 0);
273 ASSERT_GE(epollFd2.get(), 0);
274
275 // Register the same eventFd to two EpollFds.
276 ASSERT_EQ(epoll_ctl(epollFd1.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
277 ASSERT_EQ(epoll_ctl(epollFd2.get(), EPOLL_CTL_ADD, eventFd.get(), &e), 0);
278
279 int countEpoll1 = 0;
280 int countEpoll2 = 0;
281 std::atomic<bool> stop{false};
282 std::mutex mx;
283 std::condition_variable cv;
284
285 std::thread pollingThread1([&] {
286 std::array<epoll_event, 1> events;
287 while (!stop.load()) {
288 int ret = epoll_wait(epollFd1.get(), events.data(), events.size(), kTimeout);
289 ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
290
291 if (ret > 0) {
292 std::lock_guard<std::mutex> lock(mx);
293 countEpoll1++;
294 cv.notify_one();
295 }
296 }
297 });
298
299 std::thread pollingThread2([&] {
300 std::array<epoll_event, 1> events;
301 while (!stop.load()) {
302 int ret = epoll_wait(epollFd2.get(), events.data(), events.size(), kTimeout);
303 ALOGE_IF(ret < 0 && errno != ETIMEDOUT, "Epoll failed.");
304
305 if (ret > 0) {
306 std::lock_guard<std::mutex> lock(mx);
307 countEpoll2++;
308 cv.notify_one();
309 }
310 }
311 });
312
313 {
314 std::unique_lock<std::mutex> lock(mx);
315
316 eventFd.signal();
317 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 1; }));
318 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 1; }));
319
320 eventFd.signal();
321 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 2; }));
322 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 2; }));
323
324 eventFd.clear();
325 EXPECT_EQ(countEpoll1, 2);
326 EXPECT_EQ(countEpoll2, 2);
327
328 eventFd.signal();
329 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll1 == 3; }));
330 EXPECT_TRUE(cv.wait_for(lock, kTimeoutMs, [&] { return countEpoll2 == 3; }));
331 }
332
333 stop.store(true);
334 pollingThread1.join();
335 pollingThread2.join();
336}
337
338} // namespace android