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 <errno.h> 17#include <stdio.h> 18#include "le_epoll.h" 19#include "le_idle.h" 20#include "le_timer.h" 21 22static int IsValid_(const EventEpoll *loop) 23{ 24 return loop->epollFd >= 0; 25} 26 27static void GetEpollEvent_(int fd, int op, struct epoll_event *event) 28{ 29 event->data.fd = fd; 30 if (LE_TEST_FLAGS(op, EVENT_READ)) { 31 event->events |= EPOLLIN; 32 } 33 if (LE_TEST_FLAGS(op, EVENT_WRITE)) { 34 event->events |= EPOLLOUT; 35 } 36} 37 38static LE_STATUS Close_(const EventLoop *loop) 39{ 40 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 41 EventEpoll *epoll = (EventEpoll *)loop; 42 LE_LOGV("Close_ epollFd %d", epoll->epollFd); 43 close(epoll->epollFd); 44 free(epoll); 45 return LE_SUCCESS; 46} 47 48static LE_STATUS AddEvent_(const EventLoop *loop, const BaseTask *task, int op) 49{ 50 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 51 EventEpoll *epoll = (EventEpoll *)loop; 52 53 int ret = LE_FAILURE; 54 struct epoll_event event = {}; 55 int fd = GetSocketFd((const TaskHandle)task); 56 GetEpollEvent_(fd, op, &event); 57 if (IsValid_(epoll) && fd >= 0) { 58 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_ADD, fd, &event); 59 } 60 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to add epoll_ctl %d ret %d", fd, errno); 61 return LE_SUCCESS; 62} 63 64static LE_STATUS ModEvent_(const EventLoop *loop, const BaseTask *task, int op) 65{ 66 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 67 EventEpoll *epoll = (EventEpoll *)loop; 68 69 int ret = LE_FAILURE; 70 struct epoll_event event = {}; 71 int fd = GetSocketFd((const TaskHandle)task); 72 GetEpollEvent_(fd, op, &event); 73 if (IsValid_(epoll) && fd >= 0) { 74 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_MOD, fd, &event); 75 } 76 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to mod epoll_ctl %d ret %d", fd, errno); 77 return LE_SUCCESS; 78} 79 80static LE_STATUS DelEvent_(const EventLoop *loop, int fd, int op) 81{ 82 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 83 EventEpoll *epoll = (EventEpoll *)loop; 84 85 int ret = LE_FAILURE; 86 struct epoll_event event = {}; 87 GetEpollEvent_(fd, op, &event); 88 if (IsValid_(epoll) && fd >= 0) { 89 ret = epoll_ctl(epoll->epollFd, EPOLL_CTL_DEL, fd, &event); 90 } 91 LE_CHECK(ret == 0, return LE_FAILURE, "Failed to del epoll_ctl %d ret %d", fd, errno); 92 return LE_SUCCESS; 93} 94 95static LE_STATUS RunLoop_(const EventLoop *loop) 96{ 97 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 98 99 EventEpoll *epoll = (EventEpoll *)loop; 100 if (!IsValid_(epoll)) { 101 return LE_FAILURE; 102 } 103 104 while (1) { 105 LE_RunIdle((LoopHandle)&(epoll->loop)); 106 107 uint64_t minTimePeriod = GetMinTimeoutPeriod(loop); 108 int timeout = 0; 109 if (minTimePeriod == 0) { 110 timeout = -1; 111 } else if (GetCurrentTimespec(0) >= minTimePeriod) { 112 timeout = 0; 113 } else { 114 timeout = (int)(minTimePeriod - GetCurrentTimespec(0)); 115 } 116 if (timeout < 0 || timeout > 1000) { //1000ms 117 LE_LOGW("timeout:%d", timeout); 118 } 119 120 int number = epoll_wait(epoll->epollFd, epoll->waitEvents, loop->maxevents, timeout); 121 for (int index = 0; index < number; index++) { 122 if ((epoll->waitEvents[index].events & EPOLLIN) == EPOLLIN) { 123 ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_READ); 124 } 125 if ((epoll->waitEvents[index].events & EPOLLOUT) == EPOLLOUT) { 126 ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_WRITE); 127 } 128 if (epoll->waitEvents[index].events & (EPOLLERR | EPOLLHUP)) { 129 LE_LOGV("RunLoop_ fd:%d, error:%d", epoll->waitEvents[index].data.fd, errno); 130 ProcessEvent(loop, epoll->waitEvents[index].data.fd, EVENT_ERROR); 131 } 132 } 133 134 if (number == 0) { 135 CheckTimeoutOfTimer((EventLoop *)loop, GetCurrentTimespec(0)); 136 } 137 138 if (loop->stop) { 139 break; 140 } 141 } 142 return LE_SUCCESS; 143} 144 145LE_STATUS CreateEpollLoop(EventLoop **loop, uint32_t maxevents, uint32_t timeout) 146{ 147 LE_CHECK(loop != NULL, return LE_FAILURE, "Invalid loop"); 148 EventEpoll *epoll = (EventEpoll *)malloc(sizeof(EventEpoll) + sizeof(struct epoll_event) * (maxevents)); 149 LE_CHECK(epoll != NULL, return LE_FAILURE, "Failed to alloc memory for epoll"); 150 epoll->epollFd = epoll_create(maxevents); 151 LE_CHECK(epoll->epollFd >= 0, free(epoll); 152 return LE_FAILURE, "Failed to create epoll"); 153 154 *loop = (EventLoop *)epoll; 155 epoll->loop.maxevents = maxevents; 156 epoll->loop.timeout = timeout; 157 epoll->loop.close = Close_; 158 epoll->loop.runLoop = RunLoop_; 159 epoll->loop.delEvent = DelEvent_; 160 epoll->loop.addEvent = AddEvent_; 161 epoll->loop.modEvent = ModEvent_; 162 return LE_SUCCESS; 163} 164