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 28namespace OHOS { 29namespace Utils { 30 31static const int EPOLL_MAX_EVENS_INIT = 8; 32static const int HALF_OF_MAX_EVENT = 2; 33static const int EPOLL_INVALID_FD = -1; 34static const int INTERRUPTED_SYS_CALL = 4; 35static const int EPOLL_ERROR_BADF = 9; 36static const int EPOLL_ERROR_EINVAL = 22; 37 38EventDemultiplexer::EventDemultiplexer() 39 : epollFd_(epoll_create1(EPOLL_CLOEXEC)), maxEvents_(EPOLL_MAX_EVENS_INIT), mutex_(), eventHandlers_() 40{ 41} 42 43EventDemultiplexer::~EventDemultiplexer() 44{ 45 CleanUp(); 46} 47 48uint32_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 59void EventDemultiplexer::CleanUp() 60{ 61 if (epollFd_ != EPOLL_INVALID_FD) { 62 close(epollFd_); 63 epollFd_ = EPOLL_INVALID_FD; 64 } 65} 66 67uint32_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 91uint32_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 106int 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 154uint32_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 163uint32_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