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 namespace OHOS {
23 namespace Msdp {
24 namespace DeviceStatus {
25 namespace {
26 constexpr OHOS::HiviewDFX::HiLogLabel LABEL { LOG_CORE, MSDP_DOMAIN_ID, "EpollManager" };
27 constexpr int32_t MAX_N_EVENTS { 64 };
28 } // namespace
29
~EpollManager()30 EpollManager::~EpollManager()
31 {
32 Close();
33 }
34
Open()35 int32_t EpollManager::Open()
36 {
37 epollFd_ = ::epoll_create1(EPOLL_CLOEXEC);
38 if (epollFd_ == -1) {
39 FI_HILOGE("epoll_create1 failed:%{public}s", ::strerror(errno));
40 return RET_ERR;
41 }
42 return RET_OK;
43 }
44
Close()45 void EpollManager::Close()
46 {
47 if (epollFd_ != -1) {
48 if (::close(epollFd_) != 0) {
49 FI_HILOGE("close(%{public}d) failed:%{public}s", epollFd_, ::strerror(errno));
50 }
51 epollFd_ = -1;
52 }
53 }
54
Add(IEpollEventSource & source)55 int32_t EpollManager::Add(IEpollEventSource &source)
56 {
57 CALL_DEBUG_ENTER;
58 struct epoll_event ev {};
59 ev.events = source.GetEvents();
60 ev.data.ptr = &source;
61
62 int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_ADD, source.GetFd(), &ev);
63 if (ret != 0) {
64 FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
65 return RET_ERR;
66 }
67 return RET_OK;
68 }
69
Remove(IEpollEventSource & source)70 void EpollManager::Remove(IEpollEventSource &source)
71 {
72 CALL_DEBUG_ENTER;
73 int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_DEL, source.GetFd(), nullptr);
74 if (ret != 0) {
75 FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
76 }
77 }
78
Update(IEpollEventSource & source)79 int32_t EpollManager::Update(IEpollEventSource &source)
80 {
81 CALL_DEBUG_ENTER;
82 struct epoll_event ev {};
83 ev.events = source.GetEvents();
84 ev.data.ptr = &source;
85
86 int32_t ret = ::epoll_ctl(epollFd_, EPOLL_CTL_MOD, source.GetFd(), &ev);
87 if (ret != 0) {
88 FI_HILOGE("epoll_ctl failed:%{public}s", ::strerror(errno));
89 return RET_ERR;
90 }
91 return RET_OK;
92 }
93
Wait(struct epoll_event * events,int32_t maxevents)94 int32_t EpollManager::Wait(struct epoll_event *events, int32_t maxevents)
95 {
96 return WaitTimeout(events, maxevents, -1);
97 }
98
WaitTimeout(struct epoll_event * events,int32_t maxevents,int32_t timeout)99 int32_t EpollManager::WaitTimeout(struct epoll_event *events, int32_t maxevents, int32_t timeout)
100 {
101 int32_t ret = ::epoll_wait(epollFd_, events, maxevents, timeout);
102 if (ret < 0) {
103 FI_HILOGE("epoll_wait failed:%{public}s", ::strerror(errno));
104 } else if (ret == 0) {
105 FI_HILOGE("epoll_wait timeout");
106 }
107 return ret;
108 }
109
Dispatch(const struct epoll_event & ev)110 void EpollManager::Dispatch(const struct epoll_event &ev)
111 {
112 CALL_DEBUG_ENTER;
113 if ((ev.events & EPOLLIN) == EPOLLIN) {
114 DispatchOne(ev);
115 } else if ((ev.events & (EPOLLHUP | EPOLLERR)) != 0) {
116 FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
117 }
118 }
119
DispatchOne(const struct epoll_event & ev)120 void EpollManager::DispatchOne(const struct epoll_event &ev)
121 {
122 struct epoll_event evs[MAX_N_EVENTS];
123 int32_t cnt = WaitTimeout(evs, MAX_N_EVENTS, 0);
124
125 for (int32_t index = 0; index < cnt; ++index) {
126 IEpollEventSource *source = reinterpret_cast<IEpollEventSource *>(evs[index].data.ptr);
127 CHKPC(source);
128 if ((evs[index].events & EPOLLIN) == EPOLLIN) {
129 source->Dispatch(evs[index]);
130 } else if ((evs[index].events & (EPOLLHUP | EPOLLERR)) != 0) {
131 FI_HILOGE("Epoll hangup:%{public}s", ::strerror(errno));
132 }
133 }
134 }
135 } // namespace DeviceStatus
136 } // namespace Msdp
137 } // namespace OHOS