1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci 16d9f0492fSopenharmony_ci#include <errno.h> 17d9f0492fSopenharmony_ci#include <stdio.h> 18d9f0492fSopenharmony_ci#include "le_epoll.h" 19d9f0492fSopenharmony_ci#include "le_idle.h" 20d9f0492fSopenharmony_ci#include "le_timer.h" 21d9f0492fSopenharmony_ci 22d9f0492fSopenharmony_cistatic int IsValid_(const EventEpoll *loop) 23d9f0492fSopenharmony_ci{ 24d9f0492fSopenharmony_ci return loop->epollFd >= 0; 25d9f0492fSopenharmony_ci} 26d9f0492fSopenharmony_ci 27d9f0492fSopenharmony_cistatic void GetEpollEvent_(int fd, int op, struct epoll_event *event) 28d9f0492fSopenharmony_ci{ 29d9f0492fSopenharmony_ci event->data.fd = fd; 30d9f0492fSopenharmony_ci if (LE_TEST_FLAGS(op, EVENT_READ)) { 31d9f0492fSopenharmony_ci event->events |= EPOLLIN; 32d9f0492fSopenharmony_ci } 33d9f0492fSopenharmony_ci if (LE_TEST_FLAGS(op, EVENT_WRITE)) { 34d9f0492fSopenharmony_ci event->events |= EPOLLOUT; 35d9f0492fSopenharmony_ci } 36d9f0492fSopenharmony_ci} 37d9f0492fSopenharmony_ci 38d9f0492fSopenharmony_cistatic LE_STATUS Close_(const EventLoop *loop) 39d9f0492fSopenharmony_ci{ 40d9f0492fSopenharmony_ci LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 41d9f0492fSopenharmony_ci EventEpoll *epoll = (EventEpoll *)loop; 42d9f0492fSopenharmony_ci LE_LOGV("Close_ epollFd %d", epoll->epollFd); 43d9f0492fSopenharmony_ci close(epoll->epollFd); 44d9f0492fSopenharmony_ci free(epoll); 45d9f0492fSopenharmony_ci return LE_SUCCESS; 46d9f0492fSopenharmony_ci} 47d9f0492fSopenharmony_ci 48d9f0492fSopenharmony_cistatic LE_STATUS AddEvent_(const EventLoop *loop, const BaseTask *task, int op) 49d9f0492fSopenharmony_ci{ 50d9f0492fSopenharmony_ci LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 51d9f0492fSopenharmony_ci EventEpoll *epoll = (EventEpoll *)loop; 52d9f0492fSopenharmony_ci 53d9f0492fSopenharmony_ci int ret = LE_FAILURE; 54d9f0492fSopenharmony_ci struct epoll_event event = {}; 55d9f0492fSopenharmony_ci int fd = GetSocketFd((const TaskHandle)task); 56d9f0492fSopenharmony_ci GetEpollEvent_(fd, op, &event); 57d9f0492fSopenharmony_ci if (IsValid_(epoll) && fd >= 0) { 58d9f0492fSopenharmony_ci ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_ADD, fd, &event); 59d9f0492fSopenharmony_ci } 60d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add epoll_ctl %d ret %d", fd, errno); 61d9f0492fSopenharmony_ci return LE_SUCCESS; 62d9f0492fSopenharmony_ci} 63d9f0492fSopenharmony_ci 64d9f0492fSopenharmony_cistatic LE_STATUS ModEvent_(const EventLoop *loop, const BaseTask *task, int op) 65d9f0492fSopenharmony_ci{ 66d9f0492fSopenharmony_ci LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 67d9f0492fSopenharmony_ci EventEpoll *epoll = (EventEpoll *)loop; 68d9f0492fSopenharmony_ci 69d9f0492fSopenharmony_ci int ret = LE_FAILURE; 70d9f0492fSopenharmony_ci struct epoll_event event = {}; 71d9f0492fSopenharmony_ci int fd = GetSocketFd((const TaskHandle)task); 72d9f0492fSopenharmony_ci GetEpollEvent_(fd, op, &event); 73d9f0492fSopenharmony_ci if (IsValid_(epoll) && fd >= 0) { 74d9f0492fSopenharmony_ci ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_MOD, fd, &event); 75d9f0492fSopenharmony_ci } 76d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return LE_FAILURE, "Failed to mod epoll_ctl %d ret %d", fd, errno); 77d9f0492fSopenharmony_ci return LE_SUCCESS; 78d9f0492fSopenharmony_ci} 79d9f0492fSopenharmony_ci 80d9f0492fSopenharmony_cistatic LE_STATUS DelEvent_(const EventLoop *loop, int fd, int op) 81d9f0492fSopenharmony_ci{ 82d9f0492fSopenharmony_ci LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 83d9f0492fSopenharmony_ci EventEpoll *epoll = (EventEpoll *)loop; 84d9f0492fSopenharmony_ci 85d9f0492fSopenharmony_ci int ret = LE_FAILURE; 86d9f0492fSopenharmony_ci struct epoll_event event = {}; 87d9f0492fSopenharmony_ci GetEpollEvent_(fd, op, &event); 88d9f0492fSopenharmony_ci if (IsValid_(epoll) && fd >= 0) { 89d9f0492fSopenharmony_ci ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_DEL, fd, &event); 90d9f0492fSopenharmony_ci } 91d9f0492fSopenharmony_ci LE_CHECK(ret == 0, return LE_FAILURE, "Failed to del epoll_ctl %d ret %d", fd, errno); 92d9f0492fSopenharmony_ci return LE_SUCCESS; 93d9f0492fSopenharmony_ci} 94d9f0492fSopenharmony_ci 95d9f0492fSopenharmony_cistatic LE_STATUS RunLoop_(const EventLoop *loop) 96d9f0492fSopenharmony_ci{ 97d9f0492fSopenharmony_ci LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 98d9f0492fSopenharmony_ci 99d9f0492fSopenharmony_ci EventEpoll *epoll = (EventEpoll *)loop; 100d9f0492fSopenharmony_ci if (!IsValid_(epoll)) { 101d9f0492fSopenharmony_ci return LE_FAILURE; 102d9f0492fSopenharmony_ci } 103d9f0492fSopenharmony_ci 104d9f0492fSopenharmony_ci while (1) { 105d9f0492fSopenharmony_ci LE_RunIdle((LoopHandle)&(epoll->loop)); 106d9f0492fSopenharmony_ci 107d9f0492fSopenharmony_ci uint64_t minTimePeriod = GetMinTimeoutPeriod(loop); 108d9f0492fSopenharmony_ci int timeout = 0; 109d9f0492fSopenharmony_ci if (minTimePeriod == 0) { 110d9f0492fSopenharmony_ci timeout = -1; 111d9f0492fSopenharmony_ci } else if (GetCurrentTimespec(0) >= minTimePeriod) { 112d9f0492fSopenharmony_ci timeout = 0; 113d9f0492fSopenharmony_ci } else { 114d9f0492fSopenharmony_ci timeout = (int)(minTimePeriod - GetCurrentTimespec(0)); 115d9f0492fSopenharmony_ci } 116d9f0492fSopenharmony_ci if (timeout < 0 || timeout > 1000) { //1000ms 117d9f0492fSopenharmony_ci LE_LOGW("timeout:%d", timeout); 118d9f0492fSopenharmony_ci } 119d9f0492fSopenharmony_ci 120d9f0492fSopenharmony_ci int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, timeout); 121d9f0492fSopenharmony_ci for (int index = 0; index < number; index++) { 122d9f0492fSopenharmony_ci if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) { 123d9f0492fSopenharmony_ci ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_READ); 124d9f0492fSopenharmony_ci } 125d9f0492fSopenharmony_ci if ((epoll->waitEvents[index].events & EPOLLOUT) == EPOLLOUT) { 126d9f0492fSopenharmony_ci ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_WRITE); 127d9f0492fSopenharmony_ci } 128d9f0492fSopenharmony_ci if (epoll->waitEvents[index].events & (EPOLLERR | EPOLLHUP)) { 129d9f0492fSopenharmony_ci LE_LOGV("RunLoop_ fd:%d, error:%d", epoll->waitEvents[index].data.fd, errno); 130d9f0492fSopenharmony_ci ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_ERROR); 131d9f0492fSopenharmony_ci } 132d9f0492fSopenharmony_ci } 133d9f0492fSopenharmony_ci 134d9f0492fSopenharmony_ci if (number == 0) { 135d9f0492fSopenharmony_ci CheckTimeoutOfTimer((EventLoop *)loop, GetCurrentTimespec(0)); 136d9f0492fSopenharmony_ci } 137d9f0492fSopenharmony_ci 138d9f0492fSopenharmony_ci if (loop->stop) { 139d9f0492fSopenharmony_ci break; 140d9f0492fSopenharmony_ci } 141d9f0492fSopenharmony_ci } 142d9f0492fSopenharmony_ci return LE_SUCCESS; 143d9f0492fSopenharmony_ci} 144d9f0492fSopenharmony_ci 145d9f0492fSopenharmony_ciLE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout) 146d9f0492fSopenharmony_ci{ 147d9f0492fSopenharmony_ci LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 148d9f0492fSopenharmony_ci EventEpoll *epoll = (EventEpoll *)malloc(sizeof(EventEpoll) + sizeof(struct epoll_event) * (maxevents)); 149d9f0492fSopenharmony_ci LE_CHECK(epoll != NULL, return LE_FAILURE, "Failed to alloc memory for epoll"); 150d9f0492fSopenharmony_ci epoll->epollFd = epoll_create(maxevents); 151d9f0492fSopenharmony_ci LE_CHECK(epoll->epollFd >= 0, free(epoll); 152d9f0492fSopenharmony_ci return LE_FAILURE, "Failed to create epoll"); 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_ci *loop = (EventLoop *)epoll; 155d9f0492fSopenharmony_ci epoll->loop.maxevents = maxevents; 156d9f0492fSopenharmony_ci epoll->loop.timeout = timeout; 157d9f0492fSopenharmony_ci epoll->loop.close = Close_; 158d9f0492fSopenharmony_ci epoll->loop.runLoop = RunLoop_; 159d9f0492fSopenharmony_ci epoll->loop.delEvent = DelEvent_; 160d9f0492fSopenharmony_ci epoll->loop.addEvent = AddEvent_; 161d9f0492fSopenharmony_ci epoll->loop.modEvent = ModEvent_; 162d9f0492fSopenharmony_ci return LE_SUCCESS; 163d9f0492fSopenharmony_ci} 164