• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 
2 /*
3  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "event_queue_base.h"
18 
19 #include <algorithm>
20 #include <chrono>
21 #include <iterator>
22 #include <mutex>
23 
24 #include "deamon_io_waiter.h"
25 #include "epoll_io_waiter.h"
26 #include "event_handler.h"
27 #include "event_handler_utils.h"
28 #include "event_logger.h"
29 #include "inner_event.h"
30 #include "none_io_waiter.h"
31 #include "event_hitrace_meter_adapter.h"
32 
33 namespace OHOS {
34 namespace AppExecFwk {
35 namespace {
36 
37 DEFINE_EH_HILOG_LABEL("EventQueueBase");
38 constexpr uint32_t MAX_DUMP_SIZE = 500;
39 constexpr int64_t GC_TIME_OUT = 300;
40 constexpr std::string_view STAGE_BEFORE_WAITING = "BEFORE_WAITING";
41 constexpr std::string_view STAGE_AFTER_WAITING = "AFTER_WAITING";
42 constexpr std::string_view STAGE_VIP_EXISTED = "STAGE_VIP_EXISTED";
43 constexpr std::string_view STAGE_VIP_NONE = "STAGE_VIP_NONE";
44 // Help to insert events into the event queue sorted by handle time.
InsertEventsLocked(std::list<InnerEvent::Pointer> & events,InnerEvent::Pointer & event,EventInsertType insertType)45 void InsertEventsLocked(std::list<InnerEvent::Pointer> &events, InnerEvent::Pointer &event,
46     EventInsertType insertType)
47 {
48     if (insertType == EventInsertType::AT_FRONT) {
49         if (!events.empty()) {
50             // Ensure that events queue is in ordered
51             auto headEvent = events.begin();
52             if ((*headEvent)->GetHandleTime() < event->GetHandleTime()) {
53                 event->SetHandleTime((*headEvent)->GetHandleTime());
54             }
55         }
56         events.emplace_front(std::move(event));
57         return;
58     }
59 
60     auto it = events.end();
61     auto eventTime = event->GetHandleTime();
62     while (it != events.begin()) {
63         auto prevIt = std::prev(it);
64         if ((*prevIt) == nullptr) {
65             it = prevIt;
66             continue;
67         }
68         if ((*prevIt)->GetHandleTime() <= eventTime) {
69             break;
70         }
71         it = prevIt;
72     }
73     events.insert(it, std::move(event));
74 }
75 
76 // Help to check whether there is a valid event in list and update wake up time.
CheckEventInListLocked(const std::list<InnerEvent::Pointer> & events,const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime,bool isBarrierMode)77 inline bool CheckEventInListLocked(const std::list<InnerEvent::Pointer> &events, const InnerEvent::TimePoint &now,
78     InnerEvent::TimePoint &nextWakeUpTime, bool isBarrierMode)
79 {
80     if (events.empty()) return false;
81 
82     auto filter = [&now, &nextWakeUpTime, isBarrierMode](const InnerEvent::Pointer &p) {
83         const auto &handleTime = p->GetHandleTime();
84         if (handleTime < nextWakeUpTime) {
85             nextWakeUpTime = handleTime;
86             return handleTime <= now && (!isBarrierMode || p->IsBarrierTask());
87         }
88         return false;
89     };
90     return std::find_if(events.begin(), events.end(), filter) != events.end();
91 }
92 
PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> & events)93 inline InnerEvent::Pointer PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> &events)
94 {
95     InnerEvent::Pointer event = std::move(events.front());
96     events.pop_front();
97     return event;
98 }
99 
PopFrontBarrierEventFromListLocked(std::list<InnerEvent::Pointer> & events)100 inline InnerEvent::Pointer PopFrontBarrierEventFromListLocked(std::list<InnerEvent::Pointer> &events)
101 {
102     auto filter = [](const InnerEvent::Pointer &p) {
103         return p->IsBarrierTask();
104     };
105     std::list<InnerEvent::Pointer>::iterator iter = std::find_if(events.begin(), events.end(), filter);
106     if (iter != events.end()) {
107         std::list<InnerEvent::Pointer> tempList;
108         tempList.splice(tempList.begin(), events, iter);
109         return PopFrontEventFromListLocked(tempList);
110     }
111     return InnerEvent::Pointer(nullptr, nullptr);
112 }
113 
PopFrontBarrierEventFromListWithTimeLocked(std::list<InnerEvent::Pointer> & events,const InnerEvent::TimePoint & sendTime,const InnerEvent::TimePoint & handleTime)114 inline InnerEvent::Pointer PopFrontBarrierEventFromListWithTimeLocked(std::list<InnerEvent::Pointer> &events,
115     const InnerEvent::TimePoint &sendTime, const InnerEvent::TimePoint &handleTime)
116 {
117     auto filter = [&sendTime, &handleTime](const InnerEvent::Pointer &p) {
118         return p->IsBarrierTask() && (p->GetSendTime() <= sendTime) && (p->GetHandleTime() <= handleTime);
119     };
120     std::list<InnerEvent::Pointer>::iterator iter = std::find_if(events.begin(), events.end(), filter);
121     if (iter != events.end()) {
122         std::list<InnerEvent::Pointer> tempList;
123         tempList.splice(tempList.begin(), events, iter);
124         return PopFrontEventFromListLocked(tempList);
125     }
126     return InnerEvent::Pointer(nullptr, nullptr);
127 }
128 }  // unnamed namespace
129 
EventQueueBase()130 EventQueueBase::EventQueueBase() : EventQueue(), historyEvents_(std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
131 {
132     HILOGD("enter");
133 }
134 
EventQueueBase(const std::shared_ptr<IoWaiter> & ioWaiter)135 EventQueueBase::EventQueueBase(const std::shared_ptr<IoWaiter> &ioWaiter)
136     : EventQueue(ioWaiter), historyEvents_(std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
137 {
138     HILOGD("enter");
139 }
140 
~EventQueueBase()141 EventQueueBase::~EventQueueBase()
142 {
143     std::lock_guard<std::mutex> lock(queueLock_);
144     usable_.store(false);
145     ioWaiter_ = nullptr;
146     ClearObserver();
147     EH_LOGD_LIMIT("EventQueueBase is unavailable hence");
148 }
149 
MarkBarrierTaskIfNeed(InnerEvent::Pointer & event)150 static inline void MarkBarrierTaskIfNeed(InnerEvent::Pointer &event)
151 {
152     if (EventRunner::IsAppMainThread() && (event->GetHandleTime() == event->GetSendTime()) &&
153         (EventRunner::GetMainEventRunner() == event->GetOwner()->GetEventRunner())) {
154         event->MarkBarrierTask();
155     }
156 }
157 
Insert(InnerEvent::Pointer & event,Priority priority,EventInsertType insertType)158 bool EventQueueBase::Insert(InnerEvent::Pointer &event, Priority priority, EventInsertType insertType)
159 {
160     if (!event) {
161         HILOGE("Could not insert an invalid event");
162         return false;
163     }
164     HILOGD("Insert task: %{public}s %{public}d.", (event->GetEventUniqueId()).c_str(), insertType);
165     MarkBarrierTaskIfNeed(event);
166     std::lock_guard<std::mutex> lock(queueLock_);
167     if (!usable_.load()) {
168         HILOGW("EventQueue is unavailable.");
169         return false;
170     }
171     bool needNotify = false;
172     event->SetEventPriority(static_cast<int32_t>(priority));
173     switch (priority) {
174         case Priority::VIP:
175         case Priority::IMMEDIATE:
176         case Priority::HIGH:
177         case Priority::LOW: {
178             needNotify = (event->GetHandleTime() < wakeUpTime_) || (wakeUpTime_ < InnerEvent::Clock::now());
179             if (event->IsVsyncTask()) {
180                 needNotify = true;
181                 DispatchVsyncTaskNotify();
182             }
183             InsertEventsLocked(subEventQueues_[static_cast<uint32_t>(priority)].queue, event, insertType);
184             subEventQueues_[static_cast<uint32_t>(priority)].frontEventHandleTime =
185                 static_cast<uint64_t>((*subEventQueues_[static_cast<uint32_t>(priority)].queue.begin())
186                     ->GetHandleTime().time_since_epoch().count());
187             break;
188         }
189         case Priority::IDLE: {
190             // Never wake up thread if insert an idle event.
191             InsertEventsLocked(idleEvents_, event, insertType);
192             break;
193         }
194         default:
195             break;
196     }
197 
198     if (needNotify) {
199         ioWaiter_->NotifyOne();
200     }
201 #ifdef NOTIFICATIONG_SMART_GC
202     if (priority == Priority::VIP && !isExistVipTask_) {
203         isExistVipTask_ = true;
204         InnerEvent::TimePoint time = InnerEvent::Clock::now();
205         TryExecuteObserverCallback(time, EventRunnerStage::STAGE_VIP_EXISTED);
206     }
207 #endif
208     return true;
209 }
210 
RemoveOrphan()211 void EventQueueBase::RemoveOrphan()
212 {
213     HILOGD("enter");
214     // Remove all events which lost its owner.
215     auto filter = [this](const InnerEvent::Pointer &p) {
216         bool ret = p->GetWeakOwner().expired();
217         if (ret && p->IsVsyncTask()) {
218             HandleVsyncTaskNotify();
219             SetBarrierMode(false);
220             needEpoll_ = false;
221         }
222         return ret;
223     };
224 
225     RemoveOrphan(filter);
226 
227     std::lock_guard<std::mutex> lock(queueLock_);
228     if (!usable_.load()) {
229         HILOGW("RemoveOrphan EventQueueBase is unavailable.");
230         return;
231     }
232     RemoveInvalidFileDescriptor();
233 }
234 
235 
RemoveAll()236 void EventQueueBase::RemoveAll()
237 {
238     HILOGD("enter");
239     std::lock_guard<std::mutex> lock(queueLock_);
240     if (!usable_.load()) {
241         HILOGW("RemoveAll EventQueueBase is unavailable.");
242         return;
243     }
244     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
245         subEventQueues_[i].queue.clear();
246         subEventQueues_[i].frontEventHandleTime = UINT64_MAX;
247     }
248     idleEvents_.clear();
249 }
250 
Remove(const std::shared_ptr<EventHandler> & owner)251 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner)
252 {
253     HILOGD("Remove owner enter");
254     if (!owner) {
255         HILOGE("Invalid owner");
256         return;
257     }
258 
259     auto filter = [&owner](const InnerEvent::Pointer &p) { return (p->GetOwner() == owner); };
260 
261     Remove(filter);
262 }
263 
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)264 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
265 {
266     HILOGD("Remove innerEventId enter");
267     if (!owner) {
268         HILOGE("Invalid owner");
269         return;
270     }
271     auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
272         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
273     };
274 
275     Remove(filter);
276 }
277 
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId,int64_t param)278 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param)
279 {
280     HILOGD("Remove param enter");
281     if (!owner) {
282         HILOGE("Invalid owner");
283         return;
284     }
285 
286     auto filter = [&owner, innerEventId, param](const InnerEvent::Pointer &p) {
287         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId) &&
288                (p->GetParam() == param);
289     };
290 
291     Remove(filter);
292 }
293 
Remove(const std::shared_ptr<EventHandler> & owner,const std::string & name)294 bool EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name)
295 {
296     HILOGD("Remove name enter");
297     if ((!owner) || (name.empty())) {
298         HILOGE("Invalid owner or task name");
299         return false;
300     }
301 
302     bool removed = false;
303     auto filter = [&owner, &name, &removed](const InnerEvent::Pointer &p) {
304         if (p == nullptr) {
305             return false;
306         }
307         bool ret = (p->HasTask()) && (p->GetOwner() == owner) && (p->GetTaskName() == name);
308         if (!removed) {
309             removed = ret;
310         }
311         return ret;
312     };
313 
314     Remove(filter);
315     return removed;
316 }
317 
Remove(const RemoveFilter & filter)318 void EventQueueBase::Remove(const RemoveFilter &filter) __attribute__((no_sanitize("cfi")))
319 {
320     HILOGD("Remove filter enter");
321     std::lock_guard<std::mutex> lock(queueLock_);
322     if (!usable_.load()) {
323         HILOGW("EventQueueBase is unavailable.");
324         return;
325     }
326 #ifdef NOTIFICATIONG_SMART_GC
327     bool result = HasVipTask();
328 #endif
329     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
330         subEventQueues_[i].queue.remove_if(filter);
331         subEventQueues_[i].frontEventHandleTime = (subEventQueues_[i].queue.size() ?
332             static_cast<uint64_t>((*subEventQueues_[i].queue.begin())
333             ->GetHandleTime().time_since_epoch().count()) : UINT64_MAX);
334     }
335     idleEvents_.remove_if(filter);
336 #ifdef NOTIFICATIONG_SMART_GC
337     if (result) {
338         NotifyObserverVipDoneBase();
339     }
340 #endif
341 }
342 
RemoveOrphan(const RemoveFilter & filter)343 void EventQueueBase::RemoveOrphan(const RemoveFilter &filter)
344 {
345     std::list<InnerEvent::Pointer> releaseIdleEvents;
346     std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> releaseEventsQueue;
347     {
348         std::lock_guard<std::mutex> lock(queueLock_);
349         if (!usable_.load()) {
350             HILOGW("EventQueueBase is unavailable.");
351             return;
352         }
353 #ifdef NOTIFICATIONG_SMART_GC
354         bool result = HasVipTask();
355 #endif
356         for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
357             auto it = std::stable_partition(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
358             std::move(subEventQueues_[i].queue.begin(), it, std::back_inserter(releaseEventsQueue[i].queue));
359             subEventQueues_[i].queue.erase(subEventQueues_[i].queue.begin(), it);
360             subEventQueues_[i].frontEventHandleTime = (subEventQueues_[i].queue.size() ?
361             static_cast<uint64_t>((*subEventQueues_[i].queue.begin())
362             ->GetHandleTime().time_since_epoch().count()) : UINT64_MAX);
363         }
364         auto idleEventIt = std::stable_partition(idleEvents_.begin(), idleEvents_.end(), filter);
365         std::move(idleEvents_.begin(), idleEventIt, std::back_inserter(releaseIdleEvents));
366         idleEvents_.erase(idleEvents_.begin(), idleEventIt);
367 #ifdef NOTIFICATIONG_SMART_GC
368         if (result) {
369             NotifyObserverVipDoneBase();
370         }
371 #endif
372     }
373 }
374 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)375 bool EventQueueBase::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
376 {
377     if (!owner) {
378         HILOGE("Invalid owner");
379         return false;
380     }
381     auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
382         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
383     };
384     return HasInnerEvent(filter);
385 }
386 
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,int64_t param)387 bool EventQueueBase::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param)
388 {
389     if (!owner) {
390         HILOGE("Invalid owner");
391         return false;
392     }
393     auto filter = [&owner, param](const InnerEvent::Pointer &p) {
394         return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetParam() == param);
395     };
396     return HasInnerEvent(filter);
397 }
398 
HasInnerEvent(const HasFilter & filter)399 bool EventQueueBase::HasInnerEvent(const HasFilter &filter)
400 {
401     std::lock_guard<std::mutex> lock(queueLock_);
402     if (!usable_.load()) {
403         HILOGW("EventQueueBase is unavailable.");
404         return false;
405     }
406     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
407         std::list<InnerEvent::Pointer>::iterator iter =
408             std::find_if(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
409         if (iter != subEventQueues_[i].queue.end()) {
410             return true;
411         }
412     }
413     if (std::find_if(idleEvents_.begin(), idleEvents_.end(), filter) != idleEvents_.end()) {
414         return true;
415     }
416     return false;
417 }
418 
PickFirstVsyncEventLocked()419 InnerEvent::Pointer EventQueueBase::PickFirstVsyncEventLocked()
420 {
421     auto &events = subEventQueues_[static_cast<uint32_t>(Priority::VIP)].queue;
422     auto removeFilter = [](const InnerEvent::Pointer &p) {
423         return !p->GetTaskName().compare("BarrierEvent");
424     };
425     std::list<InnerEvent::Pointer>::iterator iter = std::find_if(events.begin(), events.end(), removeFilter);
426     if (iter != events.end()) {
427         std::list<InnerEvent::Pointer> tempList;
428         tempList.splice(tempList.begin(), events, iter);
429     }
430 
431     auto filter = [](const InnerEvent::Pointer &p) {
432         return p->IsVsyncTask();
433     };
434     iter = std::find_if(events.begin(), events.end(), filter);
435     if (iter != events.end()) {
436         std::list<InnerEvent::Pointer> tempList;
437         tempList.splice(tempList.begin(), events, iter);
438         return PopFrontEventFromListLocked(tempList);
439     }
440     return InnerEvent::Pointer(nullptr, nullptr);
441 }
442 
PickEventLocked(const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)443 InnerEvent::Pointer EventQueueBase::PickEventLocked(const InnerEvent::TimePoint &now,
444     InnerEvent::TimePoint &nextWakeUpTime)
445 {
446     bool isBarrierMode = isBarrierMode_;
447     uint32_t priorityIndex = SUB_EVENT_QUEUE_NUM;
448     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
449         // Check whether any event need to be distributed.
450         if (!CheckEventInListLocked(subEventQueues_[i].queue, now, nextWakeUpTime, isBarrierMode)) {
451             continue;
452         }
453 
454         // Check whether any event in higher priority need to be distributed.
455         if (priorityIndex < SUB_EVENT_QUEUE_NUM) {
456             SubEventQueue &subQueue = subEventQueues_[priorityIndex];
457             // Check whether enough events in higher priority queue are handled continuously.
458             if (subQueue.handledEventsCount < subQueue.maxHandledEventsCount) {
459                 subQueue.handledEventsCount++;
460                 break;
461             }
462         }
463 
464         // Try to pick event from this queue.
465         priorityIndex = i;
466     }
467 
468     if ((priorityIndex >= static_cast<uint32_t>(Priority::HIGH)) &&
469         sumOfPendingVsync_ && !needEpoll_) {
470         auto event = PickFirstVsyncEventLocked();
471         if (event) {
472             return event;
473         }
474     }
475     if (priorityIndex >= SUB_EVENT_QUEUE_NUM) {
476         // If not found any event to distribute, return nullptr.
477         return InnerEvent::Pointer(nullptr, nullptr);
478     }
479 
480     // Reset handled event count for sub event queues in higher priority.
481     for (uint32_t i = 0; i < priorityIndex; ++i) {
482         subEventQueues_[i].handledEventsCount = 0;
483     }
484     if (isBarrierMode) {
485         return PopFrontBarrierEventFromListLocked(subEventQueues_[priorityIndex].queue);
486     }
487     return PopFrontEventFromListLocked(subEventQueues_[priorityIndex].queue);
488 }
489 
GetExpiredEventLocked(InnerEvent::TimePoint & nextExpiredTime)490 InnerEvent::Pointer EventQueueBase::GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime)
491 {
492     auto now = InnerEvent::Clock::now();
493     wakeUpTime_ = InnerEvent::TimePoint::max();
494     // Find an event which could be distributed right now.
495     InnerEvent::Pointer event = PickEventLocked(now, wakeUpTime_);
496     if (event) {
497         int32_t prio = event->GetEventPriority();
498         subEventQueues_[prio].frontEventHandleTime = subEventQueues_[prio].queue.empty() ? UINT64_MAX :
499             static_cast<uint64_t>((*subEventQueues_[prio].queue.begin())->GetHandleTime().time_since_epoch().count());
500         // Exit idle mode, if found an event to distribute.
501         isIdle_ = false;
502         currentRunningEvent_ = CurrentRunningEvent(now, event);
503         return event;
504     }
505 
506     // If found nothing, enter idle mode and make a time stamp.
507     if (!isIdle_) {
508         idleTimeStamp_ = now;
509         isIdle_ = true;
510     }
511 
512     if (!idleEvents_.empty()) {
513         if (isBarrierMode_) {
514             event = PopFrontBarrierEventFromListWithTimeLocked(idleEvents_, idleTimeStamp_, now);
515             if (event) {
516                 currentRunningEvent_ = CurrentRunningEvent(now, event);
517                 return event;
518             }
519         } else {
520             const auto &idleEvent = idleEvents_.front();
521 
522             // Return the idle event that has been sent before time stamp and reaches its handle time.
523             if ((idleEvent->GetSendTime() <= idleTimeStamp_) && (idleEvent->GetHandleTime() <= now)) {
524                 event = PopFrontEventFromListLocked(idleEvents_);
525                 currentRunningEvent_ = CurrentRunningEvent(now, event);
526                 return event;
527             }
528         }
529     }
530 
531     // Update wake up time.
532     nextExpiredTime = sumOfPendingVsync_? InnerEvent::Clock::now() : wakeUpTime_;
533     currentRunningEvent_ = CurrentRunningEvent();
534     return InnerEvent::Pointer(nullptr, nullptr);
535 }
536 
GetEvent()537 InnerEvent::Pointer EventQueueBase::GetEvent()
538 {
539     std::unique_lock<std::mutex> lock(queueLock_);
540     while (!finished_) {
541         InnerEvent::TimePoint nextWakeUpTime = InnerEvent::TimePoint::max();
542         InnerEvent::Pointer event = GetExpiredEventLocked(nextWakeUpTime);
543         if (event) {
544             auto now = InnerEvent::Clock::now();
545             if (!isLazyMode_.load() && !sumOfPendingVsync_ && (needEpoll_ || vsyncCheckTime_ <
546                 std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count())) {
547                 TryEpollFd(now, lock);
548             }
549             return event;
550         } else if (__builtin_expect(sumOfPendingVsync_, 0)) {
551             auto event = PickFirstVsyncEventLocked();
552             if (event) {
553                 return event;
554             }
555         }
556         TryExecuteObserverCallback(nextWakeUpTime, EventRunnerStage::STAGE_BEFORE_WAITING);
557         WaitUntilLocked(nextWakeUpTime, lock);
558         needEpoll_ = false;
559         TryExecuteObserverCallback(nextWakeUpTime, EventRunnerStage::STAGE_AFTER_WAITING);
560     }
561 
562     HILOGD("Break out");
563     return InnerEvent::Pointer(nullptr, nullptr);
564 }
565 
TryExecuteObserverCallback(InnerEvent::TimePoint & nextExpiredTime,EventRunnerStage stage)566 void EventQueueBase::TryExecuteObserverCallback(InnerEvent::TimePoint &nextExpiredTime, EventRunnerStage stage)
567 {
568     uint32_t stageUint = static_cast<uint32_t>(stage);
569     if ((stageUint & observer_.stages) != stageUint) {
570         HILOGD("The observer does not subscribe to this type of notification");
571         return;
572     }
573     if (observer_.notifyCb == nullptr) {
574         HILOGD("notifyCb is nullptr");
575         return;
576     }
577     int64_t consumer = 0;
578     StageInfo info;
579     ObserverTrace obs;
580     obs.source = GetObserverTypeName(observer_.observer);
581     switch (stage) {
582         case EventRunnerStage::STAGE_BEFORE_WAITING:
583             info.sleepTime = NanosecondsToTimeout(TimePointToTimeOut(nextExpiredTime));
584             obs.stage = STAGE_BEFORE_WAITING.data();
585             consumer = ExecuteObserverCallback(obs, stage, info);
586             if (nextExpiredTime < InnerEvent::TimePoint::max()) {
587                 HILOGD("time consumer: %{public}lld", static_cast<long long>(consumer));
588                 nextExpiredTime = nextExpiredTime + std::chrono::milliseconds(consumer);
589                 wakeUpTime_ = nextExpiredTime;
590             }
591             break;
592         case EventRunnerStage::STAGE_AFTER_WAITING:
593             obs.stage = STAGE_AFTER_WAITING.data();
594             consumer = ExecuteObserverCallback(obs, stage, info);
595             break;
596         case EventRunnerStage::STAGE_VIP_EXISTED:
597             obs.stage = STAGE_VIP_EXISTED.data();
598             consumer = ExecuteObserverCallback(obs, stage, info);
599             break;
600         case EventRunnerStage::STAGE_VIP_NONE:
601             obs.stage = STAGE_VIP_NONE.data();
602             consumer = ExecuteObserverCallback(obs, stage, info);
603             break;
604         default:
605             HILOGE("this branch is unreachable");
606             break;
607     }
608     if (consumer > GC_TIME_OUT) {
609         HILOGI("execute observer callback task consumer: %{public}lld, stage: %{public}u, wakeTime: %{public}s",
610             static_cast<long long>(consumer), stageUint, InnerEvent::DumpTimeToString(wakeUpTime_).c_str());
611     }
612 }
613 
ExecuteObserverCallback(ObserverTrace obsTrace,EventRunnerStage stage,StageInfo & info)614 int64_t EventQueueBase::ExecuteObserverCallback(ObserverTrace obsTrace, EventRunnerStage stage, StageInfo &info)
615 {
616     auto start = std::chrono::high_resolution_clock::now();
617     info.timestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(start).time_since_epoch().count();
618 
619     StartTraceObserver(obsTrace);
620     (observer_.notifyCb)(stage, &info);
621     FinishTraceAdapter();
622     auto end = std::chrono::high_resolution_clock::now();
623     auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
624     return duration.count();
625 }
626 
GetObserverTypeName(Observer observerType)627 std::string EventQueueBase::GetObserverTypeName(Observer observerType)
628 {
629     switch (observerType) {
630         case Observer::ARKTS_GC:
631             return "ARKTS_GC";
632         default :
633             return "UNKNOWN_TYPE";
634     }
635 }
636 
637 
ClearObserver()638 void EventQueueBase::ClearObserver()
639 {
640     observer_.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD);
641     observer_.notifyCb = nullptr;
642 }
643 
GetExpiredEvent(InnerEvent::TimePoint & nextExpiredTime)644 InnerEvent::Pointer EventQueueBase::GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime)
645 {
646     std::unique_lock<std::mutex> lock(queueLock_);
647     return GetExpiredEventLocked(nextExpiredTime);
648 }
649 
DumpCurrentRunningEventId(const InnerEvent::EventId & innerEventId,std::string & content)650 void EventQueueBase::DumpCurrentRunningEventId(const InnerEvent::EventId &innerEventId, std::string &content)
651 {
652     if (innerEventId.index() == TYPE_U32_INDEX) {
653         content.append(", id = " + std::to_string(std::get<uint32_t>(innerEventId)));
654     } else {
655         content.append(", id = " + std::get<std::string>(innerEventId));
656     }
657 }
658 
DumpCurrentRunning()659 std::string EventQueueBase::DumpCurrentRunning()
660 {
661     std::string content;
662     if (currentRunningEvent_.beginTime_ == InnerEvent::TimePoint::max()) {
663         content.append("{}");
664     } else {
665         content.append("start at " + InnerEvent::DumpTimeToString(currentRunningEvent_.beginTime_) + ", ");
666         content.append("Event { ");
667         if (!currentRunningEvent_.owner_.expired()) {
668             content.append("send thread = " + std::to_string(currentRunningEvent_.senderKernelThreadId_));
669             content.append(", send time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.sendTime_));
670             content.append(", handle time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.handleTime_));
671             content.append(", trigger time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.triggerTime_));
672             if (currentRunningEvent_.hasTask_) {
673                 content.append(", task name = " + currentRunningEvent_.taskName_);
674             } else {
675                 DumpCurrentRunningEventId(currentRunningEvent_.innerEventId_, content);
676             }
677             if (currentRunningEvent_.param_ != 0) {
678                 content.append(", param = " + std::to_string(currentRunningEvent_.param_));
679             }
680             content.append(", caller = " + currentRunningEvent_.callerInfo_);
681         } else {
682             content.append("No handler");
683         }
684         content.append(" }");
685     }
686 
687     return content;
688 }
689 
DumpCurentQueueInfo(Dumper & dumper,uint32_t dumpMaxSize)690 void EventQueueBase::DumpCurentQueueInfo(Dumper &dumper, uint32_t dumpMaxSize)
691 {
692     std::string priority[] = {"VIP", "Immediate", "High", "Low"};
693     uint32_t total = 0;
694     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
695         uint32_t n = 0;
696         dumper.Dump(dumper.GetTag() + " " + priority[i] + " priority event queue information:" + LINE_SEPARATOR);
697         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
698             ++n;
699             if (total < dumpMaxSize) {
700                 dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
701             }
702             ++total;
703         }
704         dumper.Dump(
705             dumper.GetTag() + " Total size of " + priority[i] + " events : " + std::to_string(n) + LINE_SEPARATOR);
706     }
707     dumper.Dump(dumper.GetTag() + " Idle priority event queue information:" + LINE_SEPARATOR);
708     int n = 0;
709     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
710         ++n;
711         if (total < dumpMaxSize) {
712             dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
713         }
714         ++total;
715     }
716     dumper.Dump(dumper.GetTag() + " Total size of Idle events : " + std::to_string(n) + LINE_SEPARATOR);
717     dumper.Dump(dumper.GetTag() + " Total event size : " + std::to_string(total) + LINE_SEPARATOR);
718 }
719 
Dump(Dumper & dumper)720 void EventQueueBase::Dump(Dumper &dumper)
721 {
722     std::lock_guard<std::mutex> lock(queueLock_);
723     HILOGI("EventQueue start dump.");
724     if (!usable_.load()) {
725         HILOGW("EventQueue is unavailable.");
726         return;
727     }
728     dumper.Dump(dumper.GetTag() + " Current Running: " + DumpCurrentRunning() + LINE_SEPARATOR);
729     dumper.Dump(dumper.GetTag() + " History event queue information:" + LINE_SEPARATOR);
730     uint32_t dumpMaxSize = MAX_DUMP_SIZE;
731     for (uint8_t i = 0; i < HISTORY_EVENT_NUM_POWER; i++) {
732         if (historyEvents_[i].senderKernelThreadId == 0) {
733             continue;
734         }
735         --dumpMaxSize;
736         dumper.Dump(dumper.GetTag() + " No. " + std::to_string(i) + " : " + HistoryQueueDump(historyEvents_[i]));
737     }
738     DumpCurentQueueInfo(dumper, dumpMaxSize);
739 }
740 
DumpQueueInfo(std::string & queueInfo)741 void EventQueueBase::DumpQueueInfo(std::string& queueInfo)
742 {
743     std::lock_guard<std::mutex> lock(queueLock_);
744     if (!usable_.load()) {
745         HILOGW("EventQueue is unavailable.");
746         return;
747     }
748     std::string priority[] = {"VIP", "Immediate", "High", "Low"};
749     uint32_t total = 0;
750     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
751         uint32_t n = 0;
752         queueInfo +=  "            " + priority[i] + " priority event queue:" + LINE_SEPARATOR;
753         for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
754             ++n;
755             queueInfo +=  "            No." + std::to_string(n) + " : " + (*it)->Dump();
756             ++total;
757         }
758         queueInfo +=  "              Total size of " + priority[i] + " events : " + std::to_string(n) + LINE_SEPARATOR;
759     }
760 
761     queueInfo += "            Idle priority event queue:" + LINE_SEPARATOR;
762 
763     int n = 0;
764     for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
765         ++n;
766         queueInfo += "            No." + std::to_string(n) + " : " + (*it)->Dump();
767         ++total;
768     }
769     queueInfo += "              Total size of Idle events : " + std::to_string(n) + LINE_SEPARATOR;
770     queueInfo += "            Total event size : " + std::to_string(total);
771 }
772 
IsIdle()773 bool EventQueueBase::IsIdle()
774 {
775     return isIdle_;
776 }
777 
IsQueueEmpty()778 bool EventQueueBase::IsQueueEmpty()
779 {
780     std::lock_guard<std::mutex> lock(queueLock_);
781     if (!usable_.load()) {
782         HILOGW("EventQueue is unavailable.");
783         return false;
784     }
785     for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
786         uint32_t queueSize = subEventQueues_[i].queue.size();
787         if (queueSize != 0) {
788             return false;
789         }
790     }
791 
792     return idleEvents_.size() == 0;
793 }
794 
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)795 void EventQueueBase::PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event)
796 {
797     if (event == nullptr) {
798         HILOGW("event is nullptr.");
799         return;
800     }
801     historyEvents_[historyEventIndex_].senderKernelThreadId = event->GetSenderKernelThreadId();
802     historyEvents_[historyEventIndex_].sendTime = event->GetSendTime();
803     historyEvents_[historyEventIndex_].handleTime = event->GetHandleTime();
804     historyEvents_[historyEventIndex_].triggerTime = InnerEvent::Clock::now();
805     historyEvents_[historyEventIndex_].priority = event->GetEventPriority();
806     historyEvents_[historyEventIndex_].completeTime = InnerEvent::TimePoint::max();
807     historyEvents_[historyEventIndex_].callerInfo_ = (event->GetCaller()).ToString();
808     currentRunningEvent_.triggerTime_ = InnerEvent::Clock::now();
809 
810     if (event->HasTask()) {
811         historyEvents_[historyEventIndex_].hasTask = true;
812         historyEvents_[historyEventIndex_].taskName = event->GetTaskName();
813     } else {
814         historyEvents_[historyEventIndex_].innerEventId = event->GetInnerEventIdEx();
815     }
816 }
817 
PushHistoryQueueAfterDistribute()818 void EventQueueBase::PushHistoryQueueAfterDistribute()
819 {
820     historyEvents_[historyEventIndex_].completeTime = InnerEvent::Clock::now();
821     historyEventIndex_++;
822     historyEventIndex_ = historyEventIndex_ & (HISTORY_EVENT_NUM_POWER - 1);
823 }
824 
HistoryQueueDump(const HistoryEvent & historyEvent)825 std::string EventQueueBase::HistoryQueueDump(const HistoryEvent &historyEvent)
826 {
827     std::string content;
828     std::vector<std::string> prioritys = {"VIP", "Immediate", "High", "Low"};
829     content.append("Event { ");
830     content.append("send thread = " + std::to_string(historyEvent.senderKernelThreadId));
831     content.append(", send time = " + InnerEvent::DumpTimeToString(historyEvent.sendTime));
832     content.append(", handle time = " + InnerEvent::DumpTimeToString(historyEvent.handleTime));
833     content.append(", trigger time = " + InnerEvent::DumpTimeToString(historyEvent.triggerTime));
834     if (historyEvent.completeTime == InnerEvent::TimePoint::max()) {
835         content.append(", completeTime time = ");
836     } else {
837         content.append(", completeTime time = " + InnerEvent::DumpTimeToString(historyEvent.completeTime));
838     }
839     if (historyEvent.priority >= 0 && historyEvent.priority < prioritys.size()) {
840         content.append(", priority = " + prioritys[historyEvent.priority]);
841     } else {
842         content.append(", priority = ");
843     }
844 
845     if (historyEvent.hasTask) {
846         content.append(", task name = " + historyEvent.taskName);
847     } else {
848         DumpCurrentRunningEventId(historyEvent.innerEventId, content);
849     }
850     content.append(", caller = " + historyEvent.callerInfo_);
851     content.append(" }" + LINE_SEPARATOR);
852 
853     return content;
854 }
855 
DumpCurrentQueueSize()856 std::string EventQueueBase::DumpCurrentQueueSize()
857 {
858     return "Current queue size: IMMEDIATE = " +
859     std::to_string(subEventQueues_[static_cast<int>(Priority::IMMEDIATE)].queue.size()) + ", HIGH = " +
860     std::to_string(subEventQueues_[static_cast<int>(Priority::HIGH)].queue.size()) + ", LOW = " +
861     std::to_string(subEventQueues_[static_cast<int>(Priority::LOW)].queue.size()) + ", IDLE = " +
862     std::to_string(idleEvents_.size()) + " ; ";
863 }
864 
HasPreferEvent(int basePrio)865 bool EventQueueBase::HasPreferEvent(int basePrio)
866 {
867     for (int prio = 0; prio < basePrio; prio++) {
868         if (subEventQueues_[prio].queue.size() > 0) {
869             return true;
870         }
871     }
872     return false;
873 }
874 
QueryPendingTaskInfo(int32_t fileDescriptor)875 PendingTaskInfo EventQueueBase::QueryPendingTaskInfo(int32_t fileDescriptor)
876 {
877     PendingTaskInfo pendingTaskInfo;
878     std::shared_ptr<FileDescriptorInfo> fileDescriptorInfo = nullptr;
879     if (useDeamonIoWaiter_) {
880         fileDescriptorInfo = DeamonIoWaiter::GetInstance().GetFileDescriptorMap(fileDescriptor);
881     } else if (ioWaiter_) {
882         fileDescriptorInfo = ioWaiter_->GetFileDescriptorMap(fileDescriptor);
883     }
884     if (fileDescriptorInfo == nullptr) {
885         HILOGW("QueryPendingTaskInfo fileDescriptorInfo is unavailable.");
886         return pendingTaskInfo;
887     }
888 
889     std::lock_guard<std::mutex> lock(queueLock_);
890     if (!usable_.load()) {
891         HILOGW("QueryPendingTaskInfo event queue is unavailable.");
892         return pendingTaskInfo;
893     }
894 
895     auto now = InnerEvent::Clock::now();
896     for (auto it = subEventQueues_[0].queue.begin(); it != subEventQueues_[0].queue.end(); it++) {
897         if ((*it)->GetTaskName() == fileDescriptorInfo->taskName_) {
898             pendingTaskInfo.taskCount++;
899             InnerEvent::TimePoint handlerTime = (*it)->GetHandleTime();
900             if (handlerTime >= now) {
901                 continue;
902             }
903             auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - handlerTime).count();
904             if (duration > pendingTaskInfo.MaxPendingTime) {
905                 pendingTaskInfo.MaxPendingTime = duration;
906             }
907         }
908     }
909     EH_LOGI_LIMIT("Pend task %{public}d %{public}d", pendingTaskInfo.taskCount, pendingTaskInfo.MaxPendingTime);
910     return PendingTaskInfo();
911 }
912 
CancelAndWait()913 void EventQueueBase::CancelAndWait()
914 {
915     HILOGD("EventQueueBase CancelAndWait enter.");
916 }
917 
CurrentRunningEvent()918 CurrentRunningEvent::CurrentRunningEvent()
919 {
920     beginTime_ = InnerEvent::TimePoint::max();
921 }
922 
CurrentRunningEvent(InnerEvent::TimePoint time,InnerEvent::Pointer & event)923 CurrentRunningEvent::CurrentRunningEvent(InnerEvent::TimePoint time, InnerEvent::Pointer &event)
924 {
925     beginTime_ = time;
926     owner_ = event->GetWeakOwner();
927     senderKernelThreadId_ = event->GetSenderKernelThreadId();
928     sendTime_ = event->GetSendTime();
929     handleTime_ = event->GetHandleTime();
930     param_ = event->GetParam();
931     callerInfo_ = (event->GetCaller()).ToString();
932     if (event->HasTask()) {
933         hasTask_ = true;
934         taskName_ = event->GetTaskName();
935     } else {
936         innerEventId_ = event->GetInnerEventIdEx();
937     }
938 }
939 
AddFileDescriptorListener(int32_t fileDescriptor,uint32_t events,const std::shared_ptr<FileDescriptorListener> & listener,const std::string & taskName,Priority priority)940 ErrCode EventQueueBase::AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events,
941     const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName,
942     Priority priority)
943 {
944     if ((fileDescriptor < 0) || ((events & FILE_DESCRIPTOR_EVENTS_MASK) == 0) || (!listener)) {
945         HILOGE("%{public}d, %{public}u, %{public}s: Invalid parameter",
946                fileDescriptor, events, listener ? "valid" : "null");
947         return EVENT_HANDLER_ERR_INVALID_PARAM;
948     }
949 
950     std::lock_guard<std::mutex> lock(queueLock_);
951     return AddFileDescriptorListenerBase(fileDescriptor, events, listener, taskName, priority);
952 }
953 
RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> & owner)954 void EventQueueBase::RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner)
955 {
956     HILOGD("enter");
957     if (!owner) {
958         HILOGE("Invalid owner");
959         return;
960     }
961 
962     std::lock_guard<std::mutex> lock(queueLock_);
963     RemoveListenerByOwner(owner);
964 }
965 
RemoveFileDescriptorListener(int32_t fileDescriptor)966 void EventQueueBase::RemoveFileDescriptorListener(int32_t fileDescriptor)
967 {
968     HILOGD("enter");
969     if (fileDescriptor < 0) {
970         HILOGE("%{public}d: Invalid file descriptor", fileDescriptor);
971         return;
972     }
973 
974     std::lock_guard<std::mutex> lock(queueLock_);
975     RemoveListenerByFd(fileDescriptor);
976 }
977 
Prepare()978 void EventQueueBase::Prepare()
979 {
980     HILOGD("enter");
981     std::lock_guard<std::mutex> lock(queueLock_);
982     PrepareBase();
983 }
984 
Finish()985 void EventQueueBase::Finish()
986 {
987     HILOGD("enter");
988     std::lock_guard<std::mutex> lock(queueLock_);
989     FinishBase();
990 }
991 
NotifyObserverVipDone(const InnerEvent::Pointer & event)992 void EventQueueBase::NotifyObserverVipDone(const InnerEvent::Pointer &event)
993 {
994     if (event->GetEventPriority() != static_cast<int32_t>(Priority::VIP)) {
995         return;
996     }
997     NotifyObserverVipDoneBase();
998 }
999 
NotifyObserverVipDoneBase()1000 void EventQueueBase::NotifyObserverVipDoneBase()
1001 {
1002     if (subEventQueues_[static_cast<uint32_t>(Priority::VIP)].queue.empty()) {
1003         InnerEvent::TimePoint time = InnerEvent::Clock::now();
1004         TryExecuteObserverCallback(time, EventRunnerStage::STAGE_VIP_NONE);
1005         isExistVipTask_ = false;
1006     }
1007 }
1008 
HasVipTask()1009 bool EventQueueBase::HasVipTask()
1010 {
1011     if (!subEventQueues_[static_cast<uint32_t>(Priority::VIP)].queue.empty()) {
1012         return true;
1013     }
1014     return false;
1015 }
1016 
GetQueueFirstEventHandleTime(int32_t priority)1017 inline uint64_t EventQueueBase::GetQueueFirstEventHandleTime(int32_t priority)
1018 {
1019     if (__builtin_expect(isBarrierMode_, 0)) {
1020         return UINT64_MAX;
1021     }
1022     return subEventQueues_[static_cast<uint32_t>(priority)].frontEventHandleTime;
1023 }
1024 
SetUsable(bool usable)1025 void EventQueueBase::SetUsable(bool usable)
1026 {
1027     usable_.store(usable);
1028 }
1029 }  // namespace AppExecFwk
1030 }  // namespace OHOS
1031