1484543d1Sopenharmony_ci/*
2484543d1Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
3484543d1Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4484543d1Sopenharmony_ci * you may not use this file except in compliance with the License.
5484543d1Sopenharmony_ci * You may obtain a copy of the License at
6484543d1Sopenharmony_ci *
7484543d1Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8484543d1Sopenharmony_ci *
9484543d1Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10484543d1Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11484543d1Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12484543d1Sopenharmony_ci * See the License for the specific language governing permissions and
13484543d1Sopenharmony_ci * limitations under the License.
14484543d1Sopenharmony_ci */
15484543d1Sopenharmony_ci
16484543d1Sopenharmony_ci#ifndef HICORO_POLLER_H
17484543d1Sopenharmony_ci#define HICORO_POLLER_H
18484543d1Sopenharmony_ci#ifndef _MSC_VER
19484543d1Sopenharmony_ci#include <sys/epoll.h>
20484543d1Sopenharmony_ci#include <sys/eventfd.h>
21484543d1Sopenharmony_ci#endif
22484543d1Sopenharmony_ci#include <list>
23484543d1Sopenharmony_ci#include <map>
24484543d1Sopenharmony_ci#include <unordered_map>
25484543d1Sopenharmony_ci#include <array>
26484543d1Sopenharmony_ci#include "qos.h"
27484543d1Sopenharmony_ci#include "sync/sync.h"
28484543d1Sopenharmony_ci#include "internal_inc/non_copyable.h"
29484543d1Sopenharmony_ci#include "c/executor_task.h"
30484543d1Sopenharmony_ci#include "c/timer.h"
31484543d1Sopenharmony_ci#include "eu/worker_thread.h"
32484543d1Sopenharmony_cinamespace ffrt {
33484543d1Sopenharmony_cienum class PollerRet {
34484543d1Sopenharmony_ci    RET_NULL,
35484543d1Sopenharmony_ci    RET_EPOLL,
36484543d1Sopenharmony_ci    RET_TIMER,
37484543d1Sopenharmony_ci};
38484543d1Sopenharmony_ci
39484543d1Sopenharmony_cienum class EpollStatus {
40484543d1Sopenharmony_ci    WAIT,
41484543d1Sopenharmony_ci    WAKE,
42484543d1Sopenharmony_ci    TEARDOWN,
43484543d1Sopenharmony_ci};
44484543d1Sopenharmony_ci
45484543d1Sopenharmony_cienum class TimerStatus {
46484543d1Sopenharmony_ci    EXECUTING,
47484543d1Sopenharmony_ci    EXECUTED,
48484543d1Sopenharmony_ci};
49484543d1Sopenharmony_ci
50484543d1Sopenharmony_ciconstexpr int EPOLL_EVENT_SIZE = 1024;
51484543d1Sopenharmony_ci
52484543d1Sopenharmony_cistruct WakeDataWithCb {
53484543d1Sopenharmony_ci    WakeDataWithCb() {}
54484543d1Sopenharmony_ci    WakeDataWithCb(int fdVal, void *dataVal, std::function<void(void *, uint32_t)> cbVal, CPUEUTask *taskVal)
55484543d1Sopenharmony_ci        : fd(fdVal), data(dataVal), cb(cbVal), task(taskVal)
56484543d1Sopenharmony_ci    {}
57484543d1Sopenharmony_ci
58484543d1Sopenharmony_ci    int fd = 0;
59484543d1Sopenharmony_ci    void* data = nullptr;
60484543d1Sopenharmony_ci    std::function<void(void*, uint32_t)> cb = nullptr;
61484543d1Sopenharmony_ci    CPUEUTask* task = nullptr;
62484543d1Sopenharmony_ci    uint32_t monitorEvents = 0;
63484543d1Sopenharmony_ci};
64484543d1Sopenharmony_ci
65484543d1Sopenharmony_cistruct TimerDataWithCb {
66484543d1Sopenharmony_ci    TimerDataWithCb() {}
67484543d1Sopenharmony_ci    TimerDataWithCb(void *dataVal, void (*cbVal)(void *), CPUEUTask *taskVal, bool repeat, uint64_t timeout)
68484543d1Sopenharmony_ci        : data(dataVal), cb(cbVal), task(taskVal), repeat(repeat), timeout(timeout)
69484543d1Sopenharmony_ci    {}
70484543d1Sopenharmony_ci
71484543d1Sopenharmony_ci    void* data = nullptr;
72484543d1Sopenharmony_ci    void(*cb)(void*) = nullptr;
73484543d1Sopenharmony_ci    int handle = -1;
74484543d1Sopenharmony_ci    CPUEUTask* task = nullptr;
75484543d1Sopenharmony_ci    bool repeat = false;
76484543d1Sopenharmony_ci    uint64_t timeout = 0;
77484543d1Sopenharmony_ci};
78484543d1Sopenharmony_ci
79484543d1Sopenharmony_cistruct SyncData {
80484543d1Sopenharmony_ci    SyncData() {}
81484543d1Sopenharmony_ci    SyncData(void *eventsPtr, int maxEvents, int *nfdsPtr, TimePoint waitTP)
82484543d1Sopenharmony_ci        : eventsPtr(eventsPtr), maxEvents(maxEvents), nfdsPtr(nfdsPtr), waitTP(waitTP)
83484543d1Sopenharmony_ci    {}
84484543d1Sopenharmony_ci
85484543d1Sopenharmony_ci    void* eventsPtr = nullptr;
86484543d1Sopenharmony_ci    int maxEvents = 0;
87484543d1Sopenharmony_ci    int* nfdsPtr = nullptr;
88484543d1Sopenharmony_ci    TimePoint waitTP;
89484543d1Sopenharmony_ci};
90484543d1Sopenharmony_ci
91484543d1Sopenharmony_ciusing EventVec = typename std::vector<epoll_event>;
92484543d1Sopenharmony_ciclass Poller : private NonCopyable {
93484543d1Sopenharmony_ci    using WakeDataList = typename std::list<std::unique_ptr<struct WakeDataWithCb>>;
94484543d1Sopenharmony_cipublic:
95484543d1Sopenharmony_ci    Poller() noexcept;
96484543d1Sopenharmony_ci    ~Poller() noexcept;
97484543d1Sopenharmony_ci
98484543d1Sopenharmony_ci    int AddFdEvent(int op, uint32_t events, int fd, void* data, ffrt_poller_cb cb) noexcept;
99484543d1Sopenharmony_ci    int DelFdEvent(int fd) noexcept;
100484543d1Sopenharmony_ci    int WaitFdEvent(struct epoll_event *eventsVec, int maxevents, int timeout) noexcept;
101484543d1Sopenharmony_ci
102484543d1Sopenharmony_ci    PollerRet PollOnce(int timeout = -1) noexcept;
103484543d1Sopenharmony_ci    void WakeUp() noexcept;
104484543d1Sopenharmony_ci
105484543d1Sopenharmony_ci    int RegisterTimer(uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat = false) noexcept;
106484543d1Sopenharmony_ci    int UnregisterTimer(int handle) noexcept;
107484543d1Sopenharmony_ci    ffrt_timer_query_t GetTimerStatus(int handle) noexcept;
108484543d1Sopenharmony_ci
109484543d1Sopenharmony_ci    uint8_t GetPollCount() noexcept;
110484543d1Sopenharmony_ci
111484543d1Sopenharmony_ci    uint64_t GetTaskWaitTime(CPUEUTask* task) noexcept;
112484543d1Sopenharmony_ci
113484543d1Sopenharmony_ci    bool DetermineEmptyMap() noexcept;
114484543d1Sopenharmony_ci    bool DeterminePollerReady() noexcept;
115484543d1Sopenharmony_ci
116484543d1Sopenharmony_ci    void ClearCachedEvents(CPUEUTask* task) noexcept;
117484543d1Sopenharmony_ci
118484543d1Sopenharmony_ciprivate:
119484543d1Sopenharmony_ci    void ReleaseFdWakeData() noexcept;
120484543d1Sopenharmony_ci    void WakeSyncTask(std::unordered_map<CPUEUTask*, EventVec>& syncTaskEvents) noexcept;
121484543d1Sopenharmony_ci    void ProcessWaitedFds(int nfds, std::unordered_map<CPUEUTask*, EventVec>& syncTaskEvents,
122484543d1Sopenharmony_ci                          std::array<epoll_event, EPOLL_EVENT_SIZE>& waitedEvents) noexcept;
123484543d1Sopenharmony_ci
124484543d1Sopenharmony_ci    void ExecuteTimerCb(TimePoint timer) noexcept;
125484543d1Sopenharmony_ci    void ProcessTimerDataCb(CPUEUTask* task) noexcept;
126484543d1Sopenharmony_ci    void RegisterTimerImpl(const TimerDataWithCb& data) noexcept;
127484543d1Sopenharmony_ci
128484543d1Sopenharmony_ci    void CacheEventsAndDoMask(CPUEUTask* task, EventVec& eventVec) noexcept;
129484543d1Sopenharmony_ci    int FetchCachedEventAndDoUnmask(CPUEUTask* task, struct epoll_event* eventsVec) noexcept;
130484543d1Sopenharmony_ci    int FetchCachedEventAndDoUnmask(EventVec& cachedEventsVec, struct epoll_event* eventsVec) noexcept;
131484543d1Sopenharmony_ci
132484543d1Sopenharmony_ci    bool IsFdExist() noexcept;
133484543d1Sopenharmony_ci    bool IsTimerReady() noexcept;
134484543d1Sopenharmony_ci
135484543d1Sopenharmony_ci    int m_epFd;
136484543d1Sopenharmony_ci    uint8_t pollerCount_ = 0;
137484543d1Sopenharmony_ci    int timerHandle_ = -1;
138484543d1Sopenharmony_ci    EpollStatus flag_ = EpollStatus::WAKE;
139484543d1Sopenharmony_ci    struct WakeDataWithCb m_wakeData;
140484543d1Sopenharmony_ci    std::unordered_map<int, WakeDataList> m_wakeDataMap;
141484543d1Sopenharmony_ci    std::unordered_map<int, int> m_delCntMap;
142484543d1Sopenharmony_ci    std::unordered_map<CPUEUTask*, SyncData> m_waitTaskMap;
143484543d1Sopenharmony_ci    std::unordered_map<CPUEUTask*, EventVec> m_cachedTaskEvents;
144484543d1Sopenharmony_ci
145484543d1Sopenharmony_ci    std::unordered_map<int, TimerStatus> executedHandle_;
146484543d1Sopenharmony_ci    std::multimap<TimePoint, TimerDataWithCb> timerMap_;
147484543d1Sopenharmony_ci    std::atomic_bool fdEmpty_ {true};
148484543d1Sopenharmony_ci    std::atomic_bool timerEmpty_ {true};
149484543d1Sopenharmony_ci    mutable spin_mutex m_mapMutex;
150484543d1Sopenharmony_ci    mutable spin_mutex timerMutex_;
151484543d1Sopenharmony_ci};
152484543d1Sopenharmony_ci
153484543d1Sopenharmony_cistruct PollerProxy {
154484543d1Sopenharmony_cipublic:
155484543d1Sopenharmony_ci    static PollerProxy& Instance();
156484543d1Sopenharmony_ci
157484543d1Sopenharmony_ci    Poller& GetPoller(const QoS& qos = QoS(ffrt_qos_default))
158484543d1Sopenharmony_ci    {
159484543d1Sopenharmony_ci        return qosPollers[static_cast<size_t>(qos())];
160484543d1Sopenharmony_ci    }
161484543d1Sopenharmony_ci
162484543d1Sopenharmony_ciprivate:
163484543d1Sopenharmony_ci    std::array<Poller, QoS::MaxNum()> qosPollers;
164484543d1Sopenharmony_ci};
165484543d1Sopenharmony_ci} // namespace ffrt
166484543d1Sopenharmony_ci#endif