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