1 /*
2  * Copyright (c) 2021 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 "event_demultiplexer.h"
17 #include "event_reactor.h"
18 #include "event_handler.h"
19 #include "common_timer_errors.h"
20 #include "utils_log.h"
21 
22 #include <vector>
23 #include <cstdio>
24 #include <strings.h>
25 #include <unistd.h>
26 #include <sys/epoll.h>
27 
28 namespace OHOS {
29 namespace Utils {
30 
31 static const int EPOLL_MAX_EVENS_INIT = 8;
32 static const int HALF_OF_MAX_EVENT = 2;
33 static const int EPOLL_INVALID_FD = -1;
34 static const int INTERRUPTED_SYS_CALL = 4;
35 static const int EPOLL_ERROR_BADF = 9;
36 static const int EPOLL_ERROR_EINVAL = 22;
37 
EventDemultiplexer()38 EventDemultiplexer::EventDemultiplexer()
39     : epollFd_(epoll_create1(EPOLL_CLOEXEC)), maxEvents_(EPOLL_MAX_EVENS_INIT), mutex_(), eventHandlers_()
40 {
41 }
42 
~EventDemultiplexer()43 EventDemultiplexer::~EventDemultiplexer()
44 {
45     CleanUp();
46 }
47 
StartUp()48 uint32_t EventDemultiplexer::StartUp()
49 {
50     if (epollFd_ < 0) {
51         epollFd_ = epoll_create1(EPOLL_CLOEXEC);
52         if (epollFd_ < 0) {
53             return TIMER_ERR_BADF;
54         }
55     }
56     return TIMER_ERR_OK;
57 }
58 
CleanUp()59 void EventDemultiplexer::CleanUp()
60 {
61     if (epollFd_ != EPOLL_INVALID_FD) {
62         close(epollFd_);
63         epollFd_ = EPOLL_INVALID_FD;
64     }
65 }
66 
UpdateEventHandler(EventHandler* handler)67 uint32_t EventDemultiplexer::UpdateEventHandler(EventHandler* handler)
68 {
69     if (handler == nullptr) {
70         return TIMER_ERR_INVALID_VALUE;
71     }
72 
73     std::lock_guard<std::recursive_mutex> lock(mutex_);
74     auto itor = eventHandlers_.find(handler->GetHandle());
75     if (itor == eventHandlers_.end()) {
76         eventHandlers_.insert(std::make_pair(handler->GetHandle(), handler->shared_from_this()));
77         return Update(EPOLL_CTL_ADD, handler);
78     }
79 
80     if (handler->Events() == EventReactor::NONE_EVENT) {
81         eventHandlers_.erase(itor);
82         return Update(EPOLL_CTL_DEL, handler);
83     }
84 
85     if (handler != itor->second.get()) {
86         return TIMER_ERR_DEAL_FAILED;
87     }
88     return Update(EPOLL_CTL_MOD, handler);
89 }
90 
Update(int operation, EventHandler* handler)91 uint32_t EventDemultiplexer::Update(int operation, EventHandler* handler)
92 {
93     struct epoll_event event;
94     bzero(&event, sizeof(event));
95     event.events   = Reactor2Epoll(handler->Events());
96     event.data.fd = handler->GetHandle();
97 
98     if (epoll_ctl(epollFd_, operation, handler->GetHandle(), &event) != 0) {
99         UTILS_LOGD("epoll_ctl %{public}d  operation %{public}d on handle %{public}d failed",
100             epollFd_, operation, handler->GetHandle());
101         return TIMER_ERR_DEAL_FAILED;
102     }
103     return TIMER_ERR_OK;
104 }
105 
Polling(int timeout )106 int EventDemultiplexer::Polling(int timeout /* ms */)
107 {
108     std::vector<struct epoll_event> epollEvents(maxEvents_);
109     std::vector<std::shared_ptr<EventHandler>> taskQue;
110     std::vector<uint32_t> eventQue;
111 
112     int nfds = epoll_wait(epollFd_, &epollEvents[0], static_cast<int>(epollEvents.size()), timeout);
113     if (nfds == 0) {
114         return nfds;
115     }
116     if (nfds == -1) {
117         if (errno != INTERRUPTED_SYS_CALL) {
118             UTILS_LOGE("epoll_wait failed, errno %{public}d, epollFd_: %{public}d, pollEvents.size: %{public}zu",
119                 errno, epollFd_, epollEvents.size());
120         }
121         if (errno == EPOLL_ERROR_BADF || errno == EPOLL_ERROR_EINVAL) {
122             UTILS_LOGE("epoll_wait critical error, thread exit");
123             return EPOLL_CRITICAL_ERROR;
124         }
125         return nfds;
126     }
127 
128     {
129         std::lock_guard<std::recursive_mutex> lock(mutex_);
130         for (int idx = 0; idx < nfds; ++idx) {
131             int targetFd = epollEvents[idx].data.fd;
132             uint32_t events = epollEvents[idx].events;
133 
134             auto itor = eventHandlers_.find(targetFd);
135             if (itor != eventHandlers_.end()) {
136                 taskQue.emplace_back(itor->second);
137                 eventQue.emplace_back(events);
138             } else {
139                 UTILS_LOGE("fd not found in eventHandlers_, fd=%{public}d", targetFd);
140             }
141         }
142     }
143 
144     for (size_t idx = 0u; idx < taskQue.size() && idx < eventQue.size(); idx++) {
145         taskQue[idx]->HandleEvents(eventQue[idx]);
146     }
147 
148     if (nfds == maxEvents_) {
149         maxEvents_ *= HALF_OF_MAX_EVENT;
150     }
151     return nfds;
152 }
153 
Epoll2Reactor(uint32_t epollEvents)154 uint32_t EventDemultiplexer::Epoll2Reactor(uint32_t epollEvents)
155 {
156     if (epollEvents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
157         return EventReactor::READ_EVENT;
158     }
159 
160     return EventReactor::NONE_EVENT;
161 }
162 
Reactor2Epoll(uint32_t reactorEvent)163 uint32_t EventDemultiplexer::Reactor2Epoll(uint32_t reactorEvent)
164 {
165     switch (reactorEvent) {
166         case EventReactor::NONE_EVENT:
167             return TIMER_ERR_OK;
168         case EventReactor::READ_EVENT:
169             return EPOLLIN | EPOLLPRI;
170         default:
171             UTILS_LOGD("invalid event %{public}u.", reactorEvent);
172             return TIMER_ERR_DEAL_FAILED;
173     }
174 }
175 
176 }
177 }
178