• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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