1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "epoll_manager.h"
17
18 #include <unistd.h>
19
20 #include "devicestatus_define.h"
21
22 #undef LOG_TAG
23 #define LOG_TAG "EpollManager"
24
25 namespace OHOS {
26 namespace Msdp {
27 namespace DeviceStatus {
28 namespace {
29 constexpr int32_t MAX_N_EVENTS { 64 };
30 } // namespace
31
~EpollManager()32 EpollManager::~EpollManager()
33 {
34 Close();
35 }
36
Open()37 int32_t EpollManager::Open()
38 {
39 epollFd_ = ::epoll_create1(EPOLL_CLOEXEC);
40 if (epollFd_ == -1) {
41 FI_HILOGE("epoll_create1 failed:%{public}s", ::strerror(errno));
42 return RET_ERR;
43 }
44 return RET_OK;
45 }
46
Close()47 void EpollManager::Close()
48 {
49 if (epollFd_ != -1) {
50 if (::close(epollFd_) != 0) {
51 FI_HILOGE("close(%{public}d) failed:%{public}s", epollFd_, ::strerror(errno));
52 }
53 epollFd_ = -1;
54 }
55 }
56
Add(IEpollEventSource & source)57 int32_t EpollManager::Add(IEpollEventSource &source)
58 {
59 CALL_DEBUG_ENTER;
60 struct epoll_event ev {};
61 ev.events = source.GetEvents();
62 ev.data.ptr = &source;
63
64 int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_ADD, source.GetFd(), &ev);
65 if (ret != 0) {
66 FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
67 return RET_ERR;
68 }
69 return RET_OK;
70 }
71
Remove(IEpollEventSource & source)72 void EpollManager::Remove(IEpollEventSource &source)
73 {
74 CALL_DEBUG_ENTER;
75 int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_DEL, source.GetFd(), nullptr);
76 if (ret != 0) {
77 FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
78 }
79 }
80
Update(IEpollEventSource & source)81 int32_t EpollManager::Update(IEpollEventSource &source)
82 {
83 CALL_DEBUG_ENTER;
84 struct epoll_event ev {};
85 ev.events = source.GetEvents();
86 ev.data.ptr = &source;
87
88 int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_MOD, source.GetFd(), &ev);
89 if (ret != 0) {
90 FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
91 return RET_ERR;
92 }
93 return RET_OK;
94 }
95
Wait(struct epoll_event * events,int32_t maxevents)96 int32_t EpollManager::Wait(struct epoll_event *events, int32_t maxevents)
97 {
98 return WaitTimeout(events, maxevents, -1);
99 }
100
WaitTimeout(struct epoll_event * events,int32_t maxevents,int32_t timeout)101 int32_t EpollManager::WaitTimeout(struct epoll_event *events, int32_t maxevents, int32_t timeout)
102 {
103 int32_t ret = ::epoll_wait(epollFd_, events, maxevents, timeout);
104 if (ret < 0) {
105 FI_HILOGE("epoll_wait failed:%{public}s", ::strerror(errno));
106 } else if (ret == 0) {
107 FI_HILOGE("epoll_wait timeout");
108 }
109 return ret;
110 }
111
Dispatch(const struct epoll_event & ev)112 void EpollManager::Dispatch(const struct epoll_event &ev)
113 {
114 CALL_DEBUG_ENTER;
115 if ((ev.events & EPOLLIN) == EPOLLIN) {
116 DispatchOne(ev);
117 } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
118 FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
119 }
120 }
121
DispatchOne(const struct epoll_event & ev)122 void EpollManager::DispatchOne(const struct epoll_event &ev)
123 {
124 struct epoll_event evs[MAX_N_EVENTS];
125 int32_t cnt = WaitTimeout(evs, MAX_N_EVENTS, 0);
126
127 for (int32_t index = 0; index < cnt; ++index) {
128 IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
129 CHKPC(source);
130 if ((evs[index].events & EPOLLIN) == EPOLLIN) {
131 source->Dispatch(evs[index]);
132 } else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
133 FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
134 }
135 }
136 }
137 } // namespace DeviceStatus
138 } // namespace Msdp
139 } // namespace OHOS