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