13f4cbf05Sopenharmony_ci/* 23f4cbf05Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd. 33f4cbf05Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43f4cbf05Sopenharmony_ci * you may not use this file except in compliance with the License. 53f4cbf05Sopenharmony_ci * You may obtain a copy of the License at 63f4cbf05Sopenharmony_ci * 73f4cbf05Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83f4cbf05Sopenharmony_ci * 93f4cbf05Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103f4cbf05Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113f4cbf05Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123f4cbf05Sopenharmony_ci * See the License for the specific language governing permissions and 133f4cbf05Sopenharmony_ci * limitations under the License. 143f4cbf05Sopenharmony_ci */ 153f4cbf05Sopenharmony_ci#include <cstdio> 163f4cbf05Sopenharmony_ci#include <cstring> 173f4cbf05Sopenharmony_ci#include <queue> 183f4cbf05Sopenharmony_ci#include <vector> 193f4cbf05Sopenharmony_ci#include <sys/epoll.h> 203f4cbf05Sopenharmony_ci#include <unistd.h> 213f4cbf05Sopenharmony_ci#include "utils_log.h" 223f4cbf05Sopenharmony_ci#include "io_event_common.h" 233f4cbf05Sopenharmony_ci#include "common_event_sys_errors.h" 243f4cbf05Sopenharmony_ci#include "io_event_epoll.h" 253f4cbf05Sopenharmony_ci 263f4cbf05Sopenharmony_cinamespace OHOS { 273f4cbf05Sopenharmony_cinamespace Utils { 283f4cbf05Sopenharmony_ciIOEventEpoll::IOEventEpoll() 293f4cbf05Sopenharmony_ci : epollFd_(epoll_create1(EPOLL_CLOEXEC)), maxEvents_(EPOLL_MAX_EVENTS_INIT) {} 303f4cbf05Sopenharmony_ci 313f4cbf05Sopenharmony_ciIOEventEpoll::~IOEventEpoll() 323f4cbf05Sopenharmony_ci{ 333f4cbf05Sopenharmony_ci CleanUp(); 343f4cbf05Sopenharmony_ci} 353f4cbf05Sopenharmony_ci 363f4cbf05Sopenharmony_ciErrCode IOEventEpoll::SetUp() 373f4cbf05Sopenharmony_ci{ 383f4cbf05Sopenharmony_ci if (epollFd_ < 0) { 393f4cbf05Sopenharmony_ci epollFd_ = epoll_create1(EPOLL_CLOEXEC); 403f4cbf05Sopenharmony_ci if (epollFd_ < 0) { 413f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_BADF; 423f4cbf05Sopenharmony_ci } 433f4cbf05Sopenharmony_ci } 443f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_OK; 453f4cbf05Sopenharmony_ci} 463f4cbf05Sopenharmony_ci 473f4cbf05Sopenharmony_civoid IOEventEpoll::CleanUp() 483f4cbf05Sopenharmony_ci{ 493f4cbf05Sopenharmony_ci if (epollFd_ != IO_EVENT_INVALID_FD) { 503f4cbf05Sopenharmony_ci if (close(epollFd_) != 0) { 513f4cbf05Sopenharmony_ci UTILS_LOGW("%{public}s: Failed, cannot close fd: %{public}s.", __FUNCTION__, strerror(errno)); 523f4cbf05Sopenharmony_ci } 533f4cbf05Sopenharmony_ci epollFd_ = IO_EVENT_INVALID_FD; 543f4cbf05Sopenharmony_ci } 553f4cbf05Sopenharmony_ci} 563f4cbf05Sopenharmony_ci 573f4cbf05Sopenharmony_cibool IOEventEpoll::OperateEpoll(int op, int fd, EPEventId epollEvents) 583f4cbf05Sopenharmony_ci{ 593f4cbf05Sopenharmony_ci struct epoll_event event; 603f4cbf05Sopenharmony_ci bzero(&event, sizeof(event)); 613f4cbf05Sopenharmony_ci event.events = epollEvents; 623f4cbf05Sopenharmony_ci event.data.fd = fd; 633f4cbf05Sopenharmony_ci 643f4cbf05Sopenharmony_ci if (epoll_ctl(epollFd_, op, fd, &event) != 0) { 653f4cbf05Sopenharmony_ci UTILS_LOGE("%{public}s: Operate on epoll failed, %{public}s. epoll_fd: %{public}d , operation: %{public}d, \ 663f4cbf05Sopenharmony_ci target fd: %{public}d", __FUNCTION__, strerror(errno), epollFd_, op, fd); 673f4cbf05Sopenharmony_ci return false; 683f4cbf05Sopenharmony_ci } 693f4cbf05Sopenharmony_ci 703f4cbf05Sopenharmony_ci switch (op) { 713f4cbf05Sopenharmony_ci case EPOLL_CTL_ADD: 723f4cbf05Sopenharmony_ci interestFds_.insert(fd); 733f4cbf05Sopenharmony_ci break; 743f4cbf05Sopenharmony_ci case EPOLL_CTL_DEL: 753f4cbf05Sopenharmony_ci interestFds_.erase(fd); 763f4cbf05Sopenharmony_ci break; 773f4cbf05Sopenharmony_ci default: 783f4cbf05Sopenharmony_ci break; 793f4cbf05Sopenharmony_ci } 803f4cbf05Sopenharmony_ci return true; 813f4cbf05Sopenharmony_ci} 823f4cbf05Sopenharmony_ci 833f4cbf05Sopenharmony_ciErrCode IOEventEpoll::ModifyEvents(int fd, REventId events) 843f4cbf05Sopenharmony_ci{ 853f4cbf05Sopenharmony_ci if (fd == -1) { 863f4cbf05Sopenharmony_ci UTILS_LOGE("%{public}s: Failed, bad fd.", __FUNCTION__); 873f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_BADF; 883f4cbf05Sopenharmony_ci } 893f4cbf05Sopenharmony_ci 903f4cbf05Sopenharmony_ci int op = EPOLL_CTL_ADD; 913f4cbf05Sopenharmony_ci if (interestFds_.find(fd) != interestFds_.end()) { 923f4cbf05Sopenharmony_ci if (events == Events::EVENT_NONE) { 933f4cbf05Sopenharmony_ci op = EPOLL_CTL_DEL; 943f4cbf05Sopenharmony_ci } else { 953f4cbf05Sopenharmony_ci op = EPOLL_CTL_MOD; 963f4cbf05Sopenharmony_ci } 973f4cbf05Sopenharmony_ci } 983f4cbf05Sopenharmony_ci 993f4cbf05Sopenharmony_ci if (!OperateEpoll(op, fd, Reactor2Epoll(events))) { 1003f4cbf05Sopenharmony_ci UTILS_LOGE("%{public}s: Modify events failed.", __FUNCTION__); 1013f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_FAILED; 1023f4cbf05Sopenharmony_ci } 1033f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_OK; 1043f4cbf05Sopenharmony_ci} 1053f4cbf05Sopenharmony_ci 1063f4cbf05Sopenharmony_ciErrCode IOEventEpoll::Polling(int timeout /* ms */, std::vector<std::pair<int, REventId>>& res) 1073f4cbf05Sopenharmony_ci{ 1083f4cbf05Sopenharmony_ci struct epoll_event epollEvents[maxEvents_]; 1093f4cbf05Sopenharmony_ci int nfds = epoll_wait(epollFd_, &epollEvents[0], maxEvents_, timeout); 1103f4cbf05Sopenharmony_ci if (nfds == 0) { 1113f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_NOEVENT; 1123f4cbf05Sopenharmony_ci } 1133f4cbf05Sopenharmony_ci if (nfds == -1) { 1143f4cbf05Sopenharmony_ci UTILS_LOGE("%{public}s: epoll_wait() failed, %{public}s", __FUNCTION__, strerror(errno)); 1153f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_FAILED; 1163f4cbf05Sopenharmony_ci } 1173f4cbf05Sopenharmony_ci for (int idx = 0; idx < nfds; ++idx) { 1183f4cbf05Sopenharmony_ci res.emplace_back(std::make_pair(epollEvents[idx].data.fd, Epoll2Reactor(epollEvents[idx].events))); 1193f4cbf05Sopenharmony_ci } 1203f4cbf05Sopenharmony_ci 1213f4cbf05Sopenharmony_ci if (nfds == maxEvents_) { 1223f4cbf05Sopenharmony_ci maxEvents_ *= EXPANSION_COEFF; 1233f4cbf05Sopenharmony_ci } 1243f4cbf05Sopenharmony_ci return EVENT_SYS_ERR_OK; 1253f4cbf05Sopenharmony_ci} 1263f4cbf05Sopenharmony_ci 1273f4cbf05Sopenharmony_ciREventId IOEventEpoll::Epoll2Reactor(EPEventId epollEvents) 1283f4cbf05Sopenharmony_ci{ 1293f4cbf05Sopenharmony_ci REventId res = Events::EVENT_NONE; 1303f4cbf05Sopenharmony_ci if ((epollEvents & EPOLLHUP) && !(epollEvents & EPOLLIN)) { 1313f4cbf05Sopenharmony_ci res |= Events::EVENT_CLOSE; 1323f4cbf05Sopenharmony_ci } 1333f4cbf05Sopenharmony_ci 1343f4cbf05Sopenharmony_ci if (epollEvents & EPOLLERR) { 1353f4cbf05Sopenharmony_ci res |= Events::EVENT_ERROR; 1363f4cbf05Sopenharmony_ci } 1373f4cbf05Sopenharmony_ci 1383f4cbf05Sopenharmony_ci if (epollEvents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) { 1393f4cbf05Sopenharmony_ci res |= Events::EVENT_READ; 1403f4cbf05Sopenharmony_ci } 1413f4cbf05Sopenharmony_ci 1423f4cbf05Sopenharmony_ci if (epollEvents & EPOLLOUT) { 1433f4cbf05Sopenharmony_ci res |= Events::EVENT_WRITE; 1443f4cbf05Sopenharmony_ci } 1453f4cbf05Sopenharmony_ci 1463f4cbf05Sopenharmony_ci return res; 1473f4cbf05Sopenharmony_ci} 1483f4cbf05Sopenharmony_ci 1493f4cbf05Sopenharmony_ciEPEventId IOEventEpoll::Reactor2Epoll(REventId reactorEvent) 1503f4cbf05Sopenharmony_ci{ 1513f4cbf05Sopenharmony_ci EPEventId res = 0u; 1523f4cbf05Sopenharmony_ci 1533f4cbf05Sopenharmony_ci if (reactorEvent & Events::EVENT_READ) { 1543f4cbf05Sopenharmony_ci res |= EPOLLIN | EPOLLPRI; 1553f4cbf05Sopenharmony_ci } 1563f4cbf05Sopenharmony_ci 1573f4cbf05Sopenharmony_ci if (reactorEvent & Events::EVENT_WRITE) { 1583f4cbf05Sopenharmony_ci res |= EPOLLOUT; 1593f4cbf05Sopenharmony_ci } 1603f4cbf05Sopenharmony_ci 1613f4cbf05Sopenharmony_ci if (reactorEvent & Events::EVENT_ERROR) { 1623f4cbf05Sopenharmony_ci res |= EPOLLERR; 1633f4cbf05Sopenharmony_ci } 1643f4cbf05Sopenharmony_ci 1653f4cbf05Sopenharmony_ci return res; 1663f4cbf05Sopenharmony_ci} 1673f4cbf05Sopenharmony_ci 1683f4cbf05Sopenharmony_ci} // namespace Utils 1693f4cbf05Sopenharmony_ci} // namespace OHOS 170