1 /* 2 * Copyright (c) 2023 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 #ifndef HICORO_POLLER_H 17 #define HICORO_POLLER_H 18 #ifndef _MSC_VER 19 #include <sys/epoll.h> 20 #include <sys/eventfd.h> 21 #endif 22 #include <list> 23 #include <map> 24 #include <unordered_map> 25 #include <array> 26 #include "qos.h" 27 #include "sync/sync.h" 28 #include "internal_inc/non_copyable.h" 29 #include "c/executor_task.h" 30 #include "c/timer.h" 31 #include "eu/worker_thread.h" 32 namespace ffrt { 33 enum class PollerRet { 34 RET_NULL, 35 RET_EPOLL, 36 RET_TIMER, 37 }; 38 39 enum class EpollStatus { 40 WAIT, 41 WAKE, 42 TEARDOWN, 43 }; 44 45 enum class TimerStatus { 46 EXECUTING, 47 EXECUTED, 48 }; 49 50 constexpr int EPOLL_EVENT_SIZE = 1024; 51 52 struct WakeDataWithCb { WakeDataWithCbWakeDataWithCb53 WakeDataWithCb() {} WakeDataWithCbWakeDataWithCb54 WakeDataWithCb(int fdVal, void *dataVal, std::function<void(void *, uint32_t)> cbVal, CPUEUTask *taskVal) 55 : fd(fdVal), data(dataVal), cb(cbVal), task(taskVal) 56 {} 57 58 int fd = 0; 59 void* data = nullptr; 60 std::function<void(void*, uint32_t)> cb = nullptr; 61 CPUEUTask* task = nullptr; 62 uint32_t monitorEvents = 0; 63 }; 64 65 struct TimerDataWithCb { TimerDataWithCbTimerDataWithCb66 TimerDataWithCb() {} TimerDataWithCbTimerDataWithCb67 TimerDataWithCb(void *dataVal, void (*cbVal)(void *), CPUEUTask *taskVal, bool repeat, uint64_t timeout) 68 : data(dataVal), cb(cbVal), task(taskVal), repeat(repeat), timeout(timeout) 69 {} 70 71 void* data = nullptr; 72 void(*cb)(void*) = nullptr; 73 int handle = -1; 74 CPUEUTask* task = nullptr; 75 bool repeat = false; 76 uint64_t timeout = 0; 77 }; 78 79 struct SyncData { SyncDataSyncData80 SyncData() {} SyncDataSyncData81 SyncData(void *eventsPtr, int maxEvents, int *nfdsPtr, TimePoint waitTP) 82 : eventsPtr(eventsPtr), maxEvents(maxEvents), nfdsPtr(nfdsPtr), waitTP(waitTP) 83 {} 84 85 void* eventsPtr = nullptr; 86 int maxEvents = 0; 87 int* nfdsPtr = nullptr; 88 TimePoint waitTP; 89 }; 90 91 using EventVec = typename std::vector<epoll_event>; 92 class Poller : private NonCopyable { 93 using WakeDataList = typename std::list<std::unique_ptr<struct WakeDataWithCb>>; 94 public: 95 Poller() noexcept; 96 ~Poller() noexcept; 97 98 int AddFdEvent(int op, uint32_t events, int fd, void* data, ffrt_poller_cb cb) noexcept; 99 int DelFdEvent(int fd) noexcept; 100 int WaitFdEvent(struct epoll_event *eventsVec, int maxevents, int timeout) noexcept; 101 102 PollerRet PollOnce(int timeout = -1) noexcept; 103 void WakeUp() noexcept; 104 105 int RegisterTimer(uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat = false) noexcept; 106 int UnregisterTimer(int handle) noexcept; 107 ffrt_timer_query_t GetTimerStatus(int handle) noexcept; 108 109 uint8_t GetPollCount() noexcept; 110 111 uint64_t GetTaskWaitTime(CPUEUTask* task) noexcept; 112 113 bool DetermineEmptyMap() noexcept; 114 bool DeterminePollerReady() noexcept; 115 116 void ClearCachedEvents(CPUEUTask* task) noexcept; 117 118 private: 119 void ReleaseFdWakeData() noexcept; 120 void WakeSyncTask(std::unordered_map<CPUEUTask*, EventVec>& syncTaskEvents) noexcept; 121 void ProcessWaitedFds(int nfds, std::unordered_map<CPUEUTask*, EventVec>& syncTaskEvents, 122 std::array<epoll_event, EPOLL_EVENT_SIZE>& waitedEvents) noexcept; 123 124 void ExecuteTimerCb(TimePoint timer) noexcept; 125 void ProcessTimerDataCb(CPUEUTask* task) noexcept; 126 void RegisterTimerImpl(const TimerDataWithCb& data) noexcept; 127 128 void CacheEventsAndDoMask(CPUEUTask* task, EventVec& eventVec) noexcept; 129 int FetchCachedEventAndDoUnmask(CPUEUTask* task, struct epoll_event* eventsVec) noexcept; 130 int FetchCachedEventAndDoUnmask(EventVec& cachedEventsVec, struct epoll_event* eventsVec) noexcept; 131 132 bool IsFdExist() noexcept; 133 bool IsTimerReady() noexcept; 134 135 int m_epFd; 136 uint8_t pollerCount_ = 0; 137 int timerHandle_ = -1; 138 EpollStatus flag_ = EpollStatus::WAKE; 139 struct WakeDataWithCb m_wakeData; 140 std::unordered_map<int, WakeDataList> m_wakeDataMap; 141 std::unordered_map<int, int> m_delCntMap; 142 std::unordered_map<CPUEUTask*, SyncData> m_waitTaskMap; 143 std::unordered_map<CPUEUTask*, EventVec> m_cachedTaskEvents; 144 145 std::unordered_map<int, TimerStatus> executedHandle_; 146 std::multimap<TimePoint, TimerDataWithCb> timerMap_; 147 std::atomic_bool fdEmpty_ {true}; 148 std::atomic_bool timerEmpty_ {true}; 149 mutable spin_mutex m_mapMutex; 150 mutable spin_mutex timerMutex_; 151 }; 152 153 struct PollerProxy { 154 public: 155 static PollerProxy& Instance(); 156 157 Poller& GetPoller(const QoS& qos = QoS(ffrt_qos_default)) 158 { 159 return qosPollers[static_cast<size_t>(qos())]; 160 } 161 162 private: 163 std::array<Poller, QoS::MaxNum()> qosPollers; 164 }; 165 } // namespace ffrt 166 #endif