• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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