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 int timerHandle = -1; 90 }; 91 92 using EventVec = typename std::vector<epoll_event>; 93 class Poller : private NonCopyable { 94 using WakeDataList = typename std::list<std::unique_ptr<struct WakeDataWithCb>>; 95 public: 96 Poller() noexcept; 97 ~Poller() noexcept; 98 99 int AddFdEvent(int op, uint32_t events, int fd, void* data, ffrt_poller_cb cb) noexcept; 100 int DelFdEvent(int fd) noexcept; 101 int WaitFdEvent(struct epoll_event *eventsVec, int maxevents, int timeout) noexcept; 102 103 PollerRet PollOnce(int timeout = -1) noexcept; 104 void WakeUp() noexcept; 105 106 int RegisterTimer(uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat = false) noexcept; 107 int UnregisterTimer(int handle) noexcept; 108 ffrt_timer_query_t GetTimerStatus(int handle) noexcept; 109 110 uint64_t GetPollCount() noexcept; 111 112 uint64_t GetTaskWaitTime(CPUEUTask* task) noexcept; 113 114 bool DetermineEmptyMap() noexcept; 115 bool DeterminePollerReady() noexcept; 116 117 void ClearCachedEvents(CPUEUTask* task) noexcept; 118 119 private: 120 void ReleaseFdWakeData() noexcept; 121 void WakeSyncTask(std::unordered_map<CPUEUTask*, EventVec>& syncTaskEvents) noexcept; 122 void ProcessWaitedFds(int nfds, std::unordered_map<CPUEUTask*, EventVec>& syncTaskEvents, 123 std::array<epoll_event, EPOLL_EVENT_SIZE>& waitedEvents) noexcept; 124 125 void ExecuteTimerCb(TimePoint timer) noexcept; 126 void ProcessTimerDataCb(CPUEUTask* task) noexcept; 127 void RegisterTimerImpl(const TimerDataWithCb& data) noexcept; 128 129 void CacheEventsAndDoMask(CPUEUTask* task, EventVec& eventVec) noexcept; 130 int FetchCachedEventAndDoUnmask(CPUEUTask* task, struct epoll_event* eventsVec) noexcept; 131 int FetchCachedEventAndDoUnmask(EventVec& cachedEventsVec, struct epoll_event* eventsVec) noexcept; 132 CacheDelFd(int fd,CPUEUTask * task)133 inline void CacheDelFd(int fd, CPUEUTask *task) noexcept 134 { 135 m_delFdCacheMap.emplace(fd, task); 136 } 137 CacheMaskWakeData(CPUEUTask * task,std::unique_ptr<struct WakeDataWithCb> & maskWakeData)138 inline void CacheMaskWakeData(CPUEUTask* task, std::unique_ptr<struct WakeDataWithCb>& maskWakeData) noexcept 139 { 140 m_maskWakeDataWithCbMap[task].emplace_back(std::move(maskWakeData)); 141 } 142 143 void CacheMaskFdAndEpollDel(int fd, CPUEUTask *task) noexcept; 144 int ClearMaskWakeDataWithCbCache(CPUEUTask *task) noexcept; 145 int ClearMaskWakeDataWithCbCache(CPUEUTask *task, int fd) noexcept; 146 int ClearDelFdCache(int fd) noexcept; 147 148 bool IsFdExist() noexcept; 149 bool IsTimerReady() noexcept; 150 151 int m_epFd; 152 std::atomic<uint64_t> pollerCount_ = 0; 153 int timerHandle_ = -1; 154 std::atomic<EpollStatus> flag_ = EpollStatus::WAKE; 155 struct WakeDataWithCb m_wakeData; 156 std::unordered_map<int, WakeDataList> m_wakeDataMap; 157 std::unordered_map<int, int> m_delCntMap; 158 std::unordered_map<CPUEUTask*, SyncData> m_waitTaskMap; 159 std::unordered_map<CPUEUTask*, EventVec> m_cachedTaskEvents; 160 161 std::unordered_map<int, CPUEUTask*> m_delFdCacheMap; 162 std::unordered_map<CPUEUTask*, WakeDataList> m_maskWakeDataWithCbMap; 163 164 std::unordered_map<int, TimerStatus> executedHandle_; 165 std::multimap<TimePoint, TimerDataWithCb> timerMap_; 166 std::atomic_bool fdEmpty_ {true}; 167 std::atomic_bool timerEmpty_ {true}; 168 mutable spin_mutex m_mapMutex; 169 mutable spin_mutex timerMutex_; 170 }; 171 172 struct PollerProxy { 173 public: 174 static PollerProxy& Instance(); 175 176 Poller& GetPoller(const QoS& qos = QoS(ffrt_qos_default)) 177 { 178 return qosPollers[static_cast<size_t>(qos())]; 179 } 180 181 private: 182 std::array<Poller, QoS::MaxNum()> qosPollers; 183 }; 184 } // namespace ffrt 185 #endif