• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
17 #define BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
18 
19 #include <array>
20 #include <atomic>
21 #include <functional>
22 #include <list>
23 #include <map>
24 #include <mutex>
25 
26 #include "inner_event.h"
27 #include "event_handler_errors.h"
28 #include "file_descriptor_listener.h"
29 #include "dumper.h"
30 
31 namespace OHOS {
32 namespace AppExecFwk {
33 class IoWaiter;
34 class EventHandler;
35 class DeamonIoWaiter;
36 struct PendingTaskInfo;
37 
38 enum class EventInsertType: uint32_t {
39     // Insert event at end
40     AT_END = 0,
41     // Insert event at front
42     AT_FRONT
43 };
44 
45 enum class Observer {
46     ARKTS_GC,
47 };
48 
49 enum class EventRunnerStage {
50     // enter loop
51     STAGE_ENTRY_RUNNER = 1<<0,
52     // exit loop
53     STAGE_EXIT_RUNNER = 1<<1,
54     // waiting
55     STAGE_BEFORE_WAITING = 1<<2,
56     // recover form sleeping
57     STAGE_AFTER_WAITING = 1<<3,
58     // insert vip task
59     STAGE_VIP_EXISTED = 1<<4,
60     // current queue not exists vip task
61     STAGE_VIP_NONE = 1<<5,
62     // invaild key
63     STAGE_INVAILD = 0,
64 };
65 
66 struct StageInfo {
67     // STAGE_BEFORE_WAITING, timesteap
68     int64_t timestamp;
69     // STAGE_BEFORE_WAITING, milliseconds
70     int32_t sleepTime;
71     // STAGE_AFTER_WAITING
72     int reason;
73 };
74 
75 using EventRunnerObserverCallBack = std::function<int(EventRunnerStage stage, const StageInfo* info)>;
76 
77 struct EventRunnerObserver {
78     Observer observer;
79     uint32_t stages;
80     EventRunnerObserverCallBack notifyCb;
ClearObserverEventRunnerObserver81     void ClearObserver()
82     {
83         stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD);
84         notifyCb = nullptr;
85     }
86 };
87 
88 struct ObserverTrace {
89     std::string source;
90     std::string stage;
ObserverTraceObserverTrace91     ObserverTrace() {};
ObserverTraceObserverTrace92     ObserverTrace(std::string currentSource, std::string currentStage)
93         : source(currentSource), stage(currentStage) {}
getTraceInfoObserverTrace94     std::string getTraceInfo()
95     {
96         std::string traceInfo;
97         traceInfo.append("Et-obs:");
98         if (stage.empty()) {
99             traceInfo.append(" ");
100         } else {
101             traceInfo.append(stage);
102         }
103         traceInfo.append(",");
104         if (!source.empty()) {
105             traceInfo.append(source);
106         }
107         return traceInfo;
108     }
109 };
110 
111 #define NOW_NS std::chrono::duration_cast<std::chrono::nanoseconds>( \
112     InnerEvent::Clock::now().time_since_epoch()).count()
113 #define CHECK_VSYNC_DELAY_NS        1000000
114 #define MAX_INIT_VSYNC_PERIOD_NS    34000000
115 #define MAX_CHECK_VSYNC_PERIOD_NS   69000000
116 #define VSYNC_TASK_DELAYMS          50
117 #define MS_TO_NS_RATIO              1000000
118 
119 class EventQueue {
120 public:
121     // Priority for the events
122     enum class Priority : uint32_t {
123         // The highest priority queue, should be distributed until the tasks in the queue are completed.
124         VIP = 0,
125         // Event that should be distributed at once if possible.
126         IMMEDIATE,
127         // High priority event, sorted by handle time, should be distributed before low priority event.
128         HIGH,
129         // Normal event, sorted by handle time.
130         LOW,
131         // Event that should be distributed only if no other event right now.
132         IDLE,
133     };
134 
135     EventQueue();
136     explicit EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter);
137     virtual ~EventQueue();
138     DISALLOW_COPY_AND_MOVE(EventQueue);
139 
140     /**
141      * Insert an event into event queue with different priority.
142      * The events will be sorted by handle time.
143      *
144      * @param event Event instance which should be added into event queue.
145      * @param Priority Priority of the event
146      * @param insertType The type of insertint event to queue
147      *
148      * @see #Priority
149      */
150     virtual bool Insert(InnerEvent::Pointer &event, Priority priority = Priority::LOW,
151         EventInsertType insertType = EventInsertType::AT_END) = 0;
152 
153     /**
154      * Remove events if its owner is invalid, for base queue.
155      */
RemoveOrphan()156     virtual void RemoveOrphan() {};
157 
158     /**
159      * Remove events if its owner is invalid, for ffrt queue.
160      */
RemoveOrphanByHandlerId(const std::string & handlerId)161     virtual void RemoveOrphanByHandlerId(const std::string& handlerId) { (void)handlerId; };
162 
163     /**
164      * Remove all events.
165      */
166     virtual void RemoveAll() = 0;
167 
168     /**
169      * Remove events with specified requirements.
170      *
171      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
172      */
173     virtual void Remove(const std::shared_ptr<EventHandler> &owner) = 0;
174 
175     /**
176      * Remove events with specified requirements.
177      *
178      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
179      * @param innerEventId Remove events by event id.
180      */
181     virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0;
182 
183     /**
184      * Remove events with specified requirements.
185      *
186      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
187      * @param innerEventId Remove events by event id.
188      * @param param Remove events by value of param.
189      */
190     virtual void Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param) = 0;
191 
192     /**
193      * Remove events with specified requirements.
194      *
195      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
196      * @param name Remove events by name of the task.
197      */
198     virtual bool Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name) = 0;
199 
200     /**
201      * Add file descriptor listener for a file descriptor.
202      *
203      * @param fileDescriptor File descriptor.
204      * @param events Events from file descriptor, such as input, output, error
205      * @param listener Listener callback.
206      * @return Return 'ERR_OK' on success.
207      */
208     virtual ErrCode AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events,
209         const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName,
210         Priority priority = Priority::HIGH) = 0;
211 
212     /**
213      * Remove all file descriptor listeners for a specified owner.
214      *
215      * @param owner Owner of the event which is point to an instance of 'FileDescriptorListener'.
216      */
217     virtual void RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner) = 0;
218 
219     /**
220      * Remove file descriptor listener for a file descriptor.
221      *
222      * @param fileDescriptor File descriptor.
223      */
224     virtual void RemoveFileDescriptorListener(int32_t fileDescriptor) = 0;
225 
226     /**
227      * Prepare event queue, before calling {@link #GetEvent}.
228      * If {@link #Finish} is called, prepare event queue again, before calling {@link #GetEvent}.
229      */
230     virtual void Prepare() = 0;
231 
232     /**
233      * Exit from blocking in {@link #GetEvent}, and mark the event queue finished.
234      * After calling {@link #Finish}, {@link #GetEvent} never returns any event, until {@link #Prepare} is called.
235      */
236     virtual void Finish() = 0;
237 
238     /**
239      * Get event from event queue one by one.
240      * Before calling this method, developers should call {@link #Prepare} first.
241      * If none should be handled right now, the thread will be blocked in this method.
242      * Call {@link #Finish} to exit from blocking.
243      *
244      * @return Returns nullptr if event queue is not prepared yet, or {@link #Finish} is called.
245      * Otherwise returns event instance.
246      */
247     virtual InnerEvent::Pointer GetEvent();
248 
249     /**
250      * Get expired event from event queue one by one.
251      * Before calling this method, developers should call {@link #Prepare} first.
252      *
253      * @param nextExpiredTime Output the expired time for the next event.
254      * @return Returns nullptr if none in event queue is expired.
255      * Otherwise returns event instance.
256      */
257     virtual InnerEvent::Pointer GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime);
258 
259     /**
260      * Prints out the internal information about an object in the specified format,
261      * helping you diagnose internal errors of the object.
262      *
263      * @param dumper The Dumper object you have implemented to process the output internal information.
264      */
265     virtual void Dump(Dumper &dumper) = 0;
266 
267     /**
268      * Print out the internal information about an object in the specified format,
269      * helping you diagnose internal errors of the object.
270      *
271      * @param queueInfo queue Info.
272      */
273     virtual void DumpQueueInfo(std::string& queueInfo) = 0;
274 
275     /**
276      * Checks whether the current EventHandler is idle.
277      *
278      * @return Returns true if all events have been processed; returns false otherwise.
279      */
280     virtual bool IsIdle() = 0;
281 
282     /**
283      * Check whether this event queue is empty.
284      *
285      * @return If queue is empty return true otherwise return false.
286      */
287     virtual bool IsQueueEmpty() = 0;
288 
289     /**
290      * Check whether an event with the given ID can be found among the events that have been sent but not processed.
291      *
292      * @param owner Owner of the event which is point to an instance of 'EventHandler'.
293      * @param innerEventId The id of the event.
294      */
295     virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId) = 0;
296 
297     /**
298      * Check whether an event carrying the given param can be found among the events that have been sent but not
299      * processed.
300      *
301      * @param owner The owner of the event which is point to an instance of 'EventHandler'.
302      * @param param The basic parameter of the event.
303      */
304     virtual bool HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param) = 0;
305 
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)306     virtual void PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event) { (void)event; }
307 
PushHistoryQueueAfterDistribute()308     virtual void PushHistoryQueueAfterDistribute() {}
309 
310     virtual bool HasPreferEvent(int basePrio) = 0;
311 
312     virtual std::string DumpCurrentQueueSize() = 0;
313 
314     /**
315      * Check whether there are currenty file descriptors is need to be processed.
316      */
317     void CheckFileDescriptorEvent();
318 
319     /**
320      * Set waiter mode, true for deamon io waiter
321      */
SetIoWaiter(bool useDeamonIoWaiter)322     void SetIoWaiter(bool useDeamonIoWaiter)
323     {
324         useDeamonIoWaiter_ = useDeamonIoWaiter;
325     }
326 
327     /**
328      * Get ffrt queue handler type, only for ffrt thread mode.
329      */
GetFfrtQueue()330     virtual void* GetFfrtQueue() { return nullptr; }
331 
332     /**
333      * Insert task to ffrt queue, and wait to handled, only for ffrt thread mode.
334      */
335     virtual bool InsertSyncEvent(InnerEvent::Pointer &event, Priority priority = Priority::LOW,
336         EventInsertType insertType = EventInsertType::AT_END)
337     {
338         (void)event;
339         (void)priority;
340         (void)insertType;
341         return true;
342     }
343 
344     /**
345      * Get pending task info
346      */
347     virtual PendingTaskInfo QueryPendingTaskInfo(int32_t fileDescriptor) = 0;
348     /**
349      * add observer
350      *
351      * @param observer runner observer.
352      * @param stages The stages of observer
353      * @param callback observer callback.
354      */
AddObserver(Observer observer,uint32_t stages,EventRunnerObserverCallBack callback)355     void AddObserver(Observer observer, uint32_t stages, EventRunnerObserverCallBack callback)
356     {
357         observer_.observer = observer;
358         observer_.notifyCb = callback;
359         observer_.stages = stages;
360     }
361 
362     /**
363      * Cancel And Wait
364      */
365     virtual void CancelAndWait() = 0;
366 
367     /**
368      * notify GC Observer vip events finished
369      */
370     virtual void NotifyObserverVipDone(const InnerEvent::Pointer &event);
371 
372     /**
373      * Get the first event handle time in the prioritized task queue.
374      *
375      * @param priority The specified priority.
376      */
377     virtual inline uint64_t GetQueueFirstEventHandleTime(int32_t priority) = 0;
378 
379     /**
380      * Set the lazy mode for AppVsync
381      */
382     void SetVsyncLazyMode(bool isLazy);
383 
384     /**
385      * Set the first policy of AppVsync
386      */
387     void SetVsyncFirst(bool isFirst);
388 
389     /**
390      * the vsync task is comming.
391      */
DispatchVsyncTaskNotify()392     inline void DispatchVsyncTaskNotify()
393     {
394         ++sumOfPendingVsync_;
395         needEpoll_ = true;
396         vsyncCheckTime_ = INT64_MAX;
397     }
398 
399     /**
400      * the vsync task be handled.
401      */
HandleVsyncTaskNotify()402     inline void HandleVsyncTaskNotify()
403     {
404         --sumOfPendingVsync_;
405     }
406 
407     /**
408      * set the barrier mode.
409      */
SetBarrierMode(bool isBarrierMode)410     inline void SetBarrierMode(bool isBarrierMode)
411     {
412         isBarrierMode_ = isBarrierMode;
413     }
414 
415     /**
416      * get the barrier mode.
417      */
IsBarrierMode()418     inline bool IsBarrierMode()
419     {
420         return isBarrierMode_;
421     }
422 
423     /**
424      * get the delay time of vsync task.
425      */
GetDelayTimeOfVsyncTask()426     inline int64_t GetDelayTimeOfVsyncTask()
427     {
428         int64_t now = NOW_NS;
429         return isLazyMode_.load()? INT32_MAX : ((now > vsyncCheckTime_)?
430             VSYNC_TASK_DELAYMS - (now - vsyncCheckTime_ + CHECK_VSYNC_DELAY_NS) / MS_TO_NS_RATIO : VSYNC_TASK_DELAYMS);
431     }
432 
433     /**
434      * update the timestamp of epoll vsyncfd.
435      */
UpdateVsyncCheckTime(int64_t lastFrameTime,int64_t period)436     inline void UpdateVsyncCheckTime(int64_t lastFrameTime, int64_t period)
437     {
438         //In order to epolling vsync fd successfully, we delay a time(CHECK_VSYNC_DELAY_NS).
439         if (__builtin_expect(period > 0, 1)) {
440             int64_t now = NOW_NS;
441             vsyncPeriod_ = (period > MAX_INIT_VSYNC_PERIOD_NS) ? MAX_INIT_VSYNC_PERIOD_NS : period;
442             vsyncCheckTime_ = (lastFrameTime > now) ? (now + CHECK_VSYNC_DELAY_NS + ((lastFrameTime - now) % period)) :
443                 (now + period + CHECK_VSYNC_DELAY_NS - ((now - lastFrameTime) % period));
444         }
445     }
446 
447 protected:
448     void RemoveInvalidFileDescriptor();
449 
450     /**
451      * Add file descriptor base.
452      *
453      * @param fileDescriptor File descriptor.
454      * @param events Events from file descriptor, such as input, output, error
455      * @param listener Listener callback.
456      * @param taskName task name.
457      * @param Priority Priority of the event.
458      * @return Return result ErrCode.
459      */
460     ErrCode AddFileDescriptorListenerBase(int32_t fileDescriptor, uint32_t events,
461         const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName,
462         Priority priority);
463 
464     /**
465      * Add file descriptor by fd.
466      *
467      * @param fileDescriptor File descriptor.
468      * @param events Events from file descriptor, such as input, output, error
469      * @param taskName task name.
470      * @param listener Listener callback.
471      * @param Priority Priority of the event.
472      * @return Return result boolean.
473      */
474     bool AddFileDescriptorByFd(int32_t fileDescriptor, uint32_t events, const std::string &taskName,
475         const std::shared_ptr<FileDescriptorListener>& listener, EventQueue::Priority priority);
476 
477     bool EnsureIoWaiterLocked(const std::shared_ptr<FileDescriptorListener>& listener);
478 
479     /**
480      * handle file descriptor event.
481      *
482      * @param fileDescriptor File descriptor.
483      * @param events Events from file descriptor, such as input, output, error
484      * @param name task name.
485      * @param Priority Priority of the event.
486      */
487     void HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events, const std::string &name,
488         Priority priority);
489 
490     /**
491      * remove listener by owner.
492      *
493      * @param owner current eventhandler.
494      */
495     void RemoveListenerByOwner(const std::shared_ptr<EventHandler> &owner);
496 
497     /**
498      * remove listener by fd.
499      *
500      * @param fileDescriptor fd.
501      */
502     void RemoveListenerByFd(int32_t fileDescriptor);
503 
504     void PrepareBase();
505 
506     void FinishBase();
507 
508     void WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock, bool vsyncOnly = false);
509 
510     /**
511      * Try epoll fds according to the vsync info.
512      */
513     void TryEpollFd(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock);
514 
515     std::mutex queueLock_;
516 
517     std::atomic_bool usable_ {true};
518 
519     bool isIdle_ {true};
520 
521     // Mark if the event queue is finished.
522     bool finished_ {true};
523 
524     // IO waiter used to block if no events while calling 'GetEvent'.
525     std::shared_ptr<IoWaiter> ioWaiter_;
526 
527     // select different epoll
528     bool useDeamonIoWaiter_ = false;
529 
530     // File descriptor listeners to handle IO events.
531     std::map<int32_t, std::shared_ptr<FileDescriptorListener>> listeners_;
532 
533     EventRunnerObserver observer_ = {.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD),
534         .notifyCb = nullptr};
535 
536     int8_t sumOfPendingVsync_ = 0;
537     bool needEpoll_ = false;
538     std::atomic_bool isLazyMode_ = true;
539     bool isBarrierMode_ = false;
540     int64_t vsyncPeriod_ = INT64_MAX;
541     int64_t vsyncCheckTime_ = INT64_MAX;
542 
543 private:
544     std::shared_ptr<FileDescriptorListener> GetListenerByfd(int32_t FileDescriptor);
545 };
546 }  // namespace AppExecFwk
547 }  // namespace OHOS
548 
549 #endif  // #ifndef BASE_EVENTHANDLER_INTERFACES_INNER_API_EVENT_QUEUE_H
550