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 #ifdef USE_OHOS_QOS 27 #include "qos.h" 28 #else 29 #include "staging_qos/sched/qos.h" 30 #endif 31 #include "sync/sync.h" 32 #include "tm/task_base.h" 33 #include "internal_inc/non_copyable.h" 34 #include "c/executor_task.h" 35 #include "c/timer.h" 36 #ifdef FFRT_ENABLE_HITRACE_CHAIN 37 #include "dfx/trace/ffrt_trace_chain.h" 38 #endif 39 40 namespace ffrt { 41 enum class PollerRet { 42 RET_NULL, 43 RET_EPOLL, 44 RET_TIMER, 45 }; 46 47 enum class EpollStatus { 48 WAIT, 49 WAKE, 50 TEARDOWN, 51 }; 52 53 enum class TimerStatus { 54 EXECUTING, 55 EXECUTED, 56 }; 57 58 constexpr int EPOLL_EVENT_SIZE = 1024; 59 60 struct WakeDataWithCb { WakeDataWithCbWakeDataWithCb61 WakeDataWithCb() {} WakeDataWithCbWakeDataWithCb62 WakeDataWithCb(int fdVal, void *dataVal, std::function<void(void *, uint32_t)> cbVal, CoTask *taskVal) 63 : fd(fdVal), data(dataVal), cb(cbVal), task(taskVal) 64 { 65 if (cb != nullptr) { 66 #ifdef FFRT_ENABLE_HITRACE_CHAIN 67 if (TraceChainAdapter::Instance().HiTraceChainGetId().valid == HITRACE_ID_VALID) { 68 traceId = TraceChainAdapter::Instance().HiTraceChainCreateSpan(); 69 }; 70 #endif 71 } 72 } 73 74 int fd = 0; 75 void* data = nullptr; 76 std::function<void(void*, uint32_t)> cb = nullptr; 77 CoTask* task = nullptr; 78 uint32_t monitorEvents = 0; 79 HiTraceIdStruct traceId; 80 }; 81 82 struct TimerDataWithCb { TimerDataWithCbTimerDataWithCb83 TimerDataWithCb() {} TimerDataWithCbTimerDataWithCb84 TimerDataWithCb(void *dataVal, std::function<void(void *)> cbVal, CoTask *taskVal, bool repeat, uint64_t timeout) 85 : data(dataVal), cb(cbVal), task(taskVal), repeat(repeat), timeout(timeout) 86 { 87 if (cb != nullptr) { 88 #ifdef FFRT_ENABLE_HITRACE_CHAIN 89 if (TraceChainAdapter::Instance().HiTraceChainGetId().valid == HITRACE_ID_VALID) { 90 traceId = TraceChainAdapter::Instance().HiTraceChainCreateSpan(); 91 }; 92 #endif 93 } 94 } 95 96 void* data = nullptr; 97 std::function<void(void*)> cb = nullptr; 98 int handle = -1; 99 CoTask* task = nullptr; 100 bool repeat = false; 101 uint64_t timeout = 0; 102 HiTraceIdStruct traceId; 103 }; 104 105 struct SyncData { SyncDataSyncData106 SyncData() {} SyncDataSyncData107 SyncData(void *eventsPtr, int maxEvents, int *nfdsPtr, TimePoint waitTP) 108 : eventsPtr(eventsPtr), maxEvents(maxEvents), nfdsPtr(nfdsPtr), waitTP(waitTP) 109 {} 110 111 void* eventsPtr = nullptr; 112 int maxEvents = 0; 113 int* nfdsPtr = nullptr; 114 TimePoint waitTP; 115 int timerHandle = -1; 116 }; 117 118 using EventVec = typename std::vector<epoll_event>; 119 class Poller : private NonCopyable { 120 using WakeDataList = typename std::list<std::unique_ptr<struct WakeDataWithCb>>; 121 public: 122 Poller() noexcept; 123 ~Poller() noexcept; 124 125 int AddFdEvent(int op, uint32_t events, int fd, void* data, ffrt_poller_cb cb) noexcept; 126 int DelFdEvent(int fd) noexcept; 127 int WaitFdEvent(struct epoll_event *eventsVec, int maxevents, int timeout) noexcept; 128 129 PollerRet PollOnce(int timeout = -1) noexcept; 130 void WakeUp() noexcept; 131 132 int RegisterTimer(uint64_t timeout, void* data, ffrt_timer_cb cb, bool repeat = false) noexcept; 133 int UnregisterTimer(int handle) noexcept; 134 ffrt_timer_query_t GetTimerStatus(int handle) noexcept; 135 136 uint64_t GetPollCount() noexcept; 137 138 uint64_t GetTaskWaitTime(CoTask* task) noexcept; 139 140 bool DetermineEmptyMap() noexcept; 141 bool DeterminePollerReady() noexcept; 142 143 void ClearCachedEvents(CoTask* task) noexcept; 144 145 private: 146 void ReleaseFdWakeData() noexcept; 147 void WakeSyncTask(std::unordered_map<CoTask*, EventVec>& syncTaskEvents) noexcept; 148 void ProcessWaitedFds(int nfds, std::unordered_map<CoTask*, EventVec>& syncTaskEvents, 149 std::array<epoll_event, EPOLL_EVENT_SIZE>& waitedEvents) noexcept; 150 151 void ExecuteTimerCb(TimePoint timer) noexcept; 152 void ProcessTimerDataCb(CoTask* task) noexcept; 153 void RegisterTimerImpl(const TimerDataWithCb& data) noexcept; 154 155 void CacheEventsAndDoMask(CoTask* task, EventVec& eventVec) noexcept; 156 int FetchCachedEventAndDoUnmask(CoTask* task, struct epoll_event* eventsVec) noexcept; 157 int FetchCachedEventAndDoUnmask(EventVec& cachedEventsVec, struct epoll_event* eventsVec) noexcept; 158 CacheDelFd(int fd,CoTask * task)159 inline void CacheDelFd(int fd, CoTask *task) noexcept 160 { 161 m_delFdCacheMap.emplace(fd, task); 162 } 163 CacheMaskWakeData(CoTask * task,std::unique_ptr<struct WakeDataWithCb> & maskWakeData)164 inline void CacheMaskWakeData(CoTask* task, std::unique_ptr<struct WakeDataWithCb>& maskWakeData) noexcept 165 { 166 m_maskWakeDataWithCbMap[task].emplace_back(std::move(maskWakeData)); 167 } 168 169 void CacheMaskFdAndEpollDel(int fd, CoTask *task) noexcept; 170 int ClearMaskWakeDataWithCbCache(CoTask *task) noexcept; 171 int ClearMaskWakeDataWithCbCacheWithFd(CoTask *task, int fd) noexcept; 172 int ClearDelFdCache(int fd) noexcept; 173 174 bool IsFdExist() noexcept; 175 bool IsTimerReady() noexcept; 176 177 int m_epFd; 178 std::atomic<uint64_t> pollerCount_ = 0; 179 int timerHandle_ = -1; 180 std::atomic<EpollStatus> flag_ = EpollStatus::WAKE; 181 struct WakeDataWithCb m_wakeData; 182 std::unordered_map<int, WakeDataList> m_wakeDataMap; 183 std::unordered_map<int, int> m_delCntMap; 184 std::unordered_map<CoTask*, SyncData> m_waitTaskMap; 185 std::unordered_map<CoTask*, EventVec> m_cachedTaskEvents; 186 187 std::unordered_map<int, CoTask*> m_delFdCacheMap; 188 std::unordered_map<CoTask*, WakeDataList> m_maskWakeDataWithCbMap; 189 190 std::unordered_map<int, TimerStatus> executedHandle_; 191 std::multimap<TimePoint, TimerDataWithCb> timerMap_; 192 std::atomic_bool fdEmpty_ {true}; 193 std::atomic_bool timerEmpty_ {true}; 194 mutable spin_mutex m_mapMutex; 195 mutable spin_mutex timerMutex_; 196 }; 197 198 struct PollerProxy { 199 public: 200 static PollerProxy& Instance(); 201 202 Poller& GetPoller(const QoS& qos = QoS(ffrt_qos_default)) 203 { 204 return qosPollers[static_cast<size_t>(qos())]; 205 } 206 207 private: 208 std::array<Poller, QoS::MaxNum()> qosPollers; 209 }; 210 } // namespace ffrt 211 #endif