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