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