• 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 #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