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 "event_handler.h"
26 #include "event_handler_utils.h"
27 #include "event_logger.h"
28 #include "inner_event.h"
29 #include "none_io_waiter.h"
30 #include "event_hitrace_meter_adapter.h"
31
32 namespace OHOS {
33 namespace AppExecFwk {
34 namespace {
35
36 DEFINE_EH_HILOG_LABEL("EventQueueBase");
37 constexpr uint32_t MAX_DUMP_SIZE = 500;
38 constexpr int64_t GC_TIME_OUT = 300;
39 constexpr std::string_view STAGE_BEFORE_WAITING = "BEFORE_WAITING";
40 constexpr std::string_view STAGE_AFTER_WAITING = "AFTER_WAITING";
41 // Help to insert events into the event queue sorted by handle time.
InsertEventsLocked(std::list<InnerEvent::Pointer> & events,InnerEvent::Pointer & event,EventInsertType insertType)42 void InsertEventsLocked(std::list<InnerEvent::Pointer> &events, InnerEvent::Pointer &event,
43 EventInsertType insertType)
44 {
45 if (insertType == EventInsertType::AT_FRONT) {
46 if (!events.empty()) {
47 // Ensure that events queue is in ordered
48 auto headEvent = events.begin();
49 if ((*headEvent)->GetHandleTime() < event->GetHandleTime()) {
50 event->SetHandleTime((*headEvent)->GetHandleTime());
51 }
52 }
53 events.emplace_front(std::move(event));
54 return;
55 }
56
57 auto f = [](const InnerEvent::Pointer &first, const InnerEvent::Pointer &second) {
58 if (!first || !second) {
59 return false;
60 }
61 return first->GetHandleTime() < second->GetHandleTime();
62 };
63 auto it = std::upper_bound(events.begin(), events.end(), event, f);
64 events.insert(it, std::move(event));
65 }
66
67 // 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)68 inline bool CheckEventInListLocked(const std::list<InnerEvent::Pointer> &events, const InnerEvent::TimePoint &now,
69 InnerEvent::TimePoint &nextWakeUpTime)
70 {
71 if (!events.empty()) {
72 const auto &handleTime = events.front()->GetHandleTime();
73 if (handleTime < nextWakeUpTime) {
74 nextWakeUpTime = handleTime;
75 return handleTime <= now;
76 }
77 }
78
79 return false;
80 }
81
PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> & events)82 inline InnerEvent::Pointer PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> &events)
83 {
84 InnerEvent::Pointer event = std::move(events.front());
85 events.pop_front();
86 return event;
87 }
88 } // unnamed namespace
89
EventQueueBase()90 EventQueueBase::EventQueueBase() : EventQueue(), historyEvents_(std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
91 {
92 HILOGD("enter");
93 }
94
EventQueueBase(const std::shared_ptr<IoWaiter> & ioWaiter)95 EventQueueBase::EventQueueBase(const std::shared_ptr<IoWaiter> &ioWaiter)
96 : EventQueue(ioWaiter), historyEvents_(std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
97 {
98 HILOGD("enter");
99 }
100
~EventQueueBase()101 EventQueueBase::~EventQueueBase()
102 {
103 std::lock_guard<std::mutex> lock(queueLock_);
104 usable_.store(false);
105 ioWaiter_ = nullptr;
106 ClearObserver();
107 EH_LOGI_LIMIT("EventQueueBase is unavailable hence");
108 }
109
Insert(InnerEvent::Pointer & event,Priority priority,EventInsertType insertType)110 void EventQueueBase::Insert(InnerEvent::Pointer &event, Priority priority, EventInsertType insertType)
111 {
112 if (!event) {
113 HILOGE("Could not insert an invalid event");
114 return;
115 }
116 HILOGD("Insert task: %{public}s %{public}d.", (event->GetEventUniqueId()).c_str(), insertType);
117 std::lock_guard<std::mutex> lock(queueLock_);
118 if (!usable_.load()) {
119 HILOGW("EventQueue is unavailable.");
120 return;
121 }
122 bool needNotify = false;
123 event->SetEventPriority(static_cast<int32_t>(priority));
124 switch (priority) {
125 case Priority::VIP:
126 case Priority::IMMEDIATE:
127 case Priority::HIGH:
128 case Priority::LOW: {
129 needNotify = (event->GetHandleTime() < wakeUpTime_);
130 InsertEventsLocked(subEventQueues_[static_cast<uint32_t>(priority)].queue, event, insertType);
131 break;
132 }
133 case Priority::IDLE: {
134 // Never wake up thread if insert an idle event.
135 InsertEventsLocked(idleEvents_, event, insertType);
136 break;
137 }
138 default:
139 break;
140 }
141
142 if (needNotify) {
143 ioWaiter_->NotifyOne();
144 }
145 }
146
RemoveOrphan()147 void EventQueueBase::RemoveOrphan()
148 {
149 HILOGD("enter");
150 // Remove all events which lost its owner.
151 auto filter = [](const InnerEvent::Pointer &p) { return p->GetWeakOwner().expired(); };
152
153 RemoveOrphan(filter);
154
155 std::lock_guard<std::mutex> lock(queueLock_);
156 if (!usable_.load()) {
157 HILOGW("EventQueueBase is unavailable.");
158 return;
159 }
160 RemoveInvalidFileDescriptor();
161 }
162
163
RemoveAll()164 void EventQueueBase::RemoveAll()
165 {
166 HILOGD("enter");
167 std::lock_guard<std::mutex> lock(queueLock_);
168 if (!usable_.load()) {
169 HILOGW("EventQueueBase is unavailable.");
170 return;
171 }
172 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
173 subEventQueues_[i].queue.clear();
174 }
175 idleEvents_.clear();
176 }
177
Remove(const std::shared_ptr<EventHandler> & owner)178 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner)
179 {
180 HILOGD("enter");
181 if (!owner) {
182 HILOGE("Invalid owner");
183 return;
184 }
185
186 auto filter = [&owner](const InnerEvent::Pointer &p) { return (p->GetOwner() == owner); };
187
188 Remove(filter);
189 }
190
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)191 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
192 {
193 HILOGD("enter");
194 if (!owner) {
195 HILOGE("Invalid owner");
196 return;
197 }
198 auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
199 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
200 };
201
202 Remove(filter);
203 }
204
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId,int64_t param)205 void EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param)
206 {
207 HILOGD("enter");
208 if (!owner) {
209 HILOGE("Invalid owner");
210 return;
211 }
212
213 auto filter = [&owner, innerEventId, param](const InnerEvent::Pointer &p) {
214 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId) &&
215 (p->GetParam() == param);
216 };
217
218 Remove(filter);
219 }
220
Remove(const std::shared_ptr<EventHandler> & owner,const std::string & name)221 bool EventQueueBase::Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name)
222 {
223 HILOGD("enter");
224 if ((!owner) || (name.empty())) {
225 HILOGE("Invalid owner or task name");
226 return false;
227 }
228
229 bool removed = false;
230 auto filter = [&owner, &name, &removed](const InnerEvent::Pointer &p) {
231 if (p == nullptr) {
232 return false;
233 }
234 bool ret = (p->HasTask()) && (p->GetOwner() == owner) && (p->GetTaskName() == name);
235 if (!removed) {
236 removed = ret;
237 }
238 return ret;
239 };
240
241 Remove(filter);
242 return removed;
243 }
244
Remove(const RemoveFilter & filter)245 void EventQueueBase::Remove(const RemoveFilter &filter)
246 {
247 HILOGD("enter");
248 std::lock_guard<std::mutex> lock(queueLock_);
249 if (!usable_.load()) {
250 HILOGW("EventQueueBase is unavailable.");
251 return;
252 }
253 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
254 subEventQueues_[i].queue.remove_if(filter);
255 }
256 idleEvents_.remove_if(filter);
257 }
258
RemoveOrphan(const RemoveFilter & filter)259 void EventQueueBase::RemoveOrphan(const RemoveFilter &filter)
260 {
261 std::list<InnerEvent::Pointer> releaseIdleEvents;
262 std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> releaseEventsQueue;
263 {
264 std::lock_guard<std::mutex> lock(queueLock_);
265 if (!usable_.load()) {
266 HILOGW("EventQueueBase is unavailable.");
267 return;
268 }
269 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
270 auto it = std::stable_partition(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
271 std::move(subEventQueues_[i].queue.begin(), it, std::back_inserter(releaseEventsQueue[i].queue));
272 subEventQueues_[i].queue.erase(subEventQueues_[i].queue.begin(), it);
273 }
274 auto idleEventIt = std::stable_partition(idleEvents_.begin(), idleEvents_.end(), filter);
275 std::move(idleEvents_.begin(), idleEventIt, std::back_inserter(releaseIdleEvents));
276 idleEvents_.erase(idleEvents_.begin(), idleEventIt);
277 }
278 }
279
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)280 bool EventQueueBase::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
281 {
282 if (!owner) {
283 HILOGE("Invalid owner");
284 return false;
285 }
286 auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
287 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
288 };
289 return HasInnerEvent(filter);
290 }
291
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,int64_t param)292 bool EventQueueBase::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param)
293 {
294 if (!owner) {
295 HILOGE("Invalid owner");
296 return false;
297 }
298 auto filter = [&owner, param](const InnerEvent::Pointer &p) {
299 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetParam() == param);
300 };
301 return HasInnerEvent(filter);
302 }
303
HasInnerEvent(const HasFilter & filter)304 bool EventQueueBase::HasInnerEvent(const HasFilter &filter)
305 {
306 std::lock_guard<std::mutex> lock(queueLock_);
307 if (!usable_.load()) {
308 HILOGW("EventQueueBase is unavailable.");
309 return false;
310 }
311 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
312 std::list<InnerEvent::Pointer>::iterator iter =
313 std::find_if(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
314 if (iter != subEventQueues_[i].queue.end()) {
315 return true;
316 }
317 }
318 if (std::find_if(idleEvents_.begin(), idleEvents_.end(), filter) != idleEvents_.end()) {
319 return true;
320 }
321 return false;
322 }
323
PickEventLocked(const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)324 InnerEvent::Pointer EventQueueBase::PickEventLocked(const InnerEvent::TimePoint &now,
325 InnerEvent::TimePoint &nextWakeUpTime)
326 {
327 uint32_t priorityIndex = SUB_EVENT_QUEUE_NUM;
328 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
329 // Check whether any event need to be distributed.
330 if (!CheckEventInListLocked(subEventQueues_[i].queue, now, nextWakeUpTime)) {
331 continue;
332 }
333
334 // Check whether any event in higher priority need to be distributed.
335 if (priorityIndex < SUB_EVENT_QUEUE_NUM) {
336 SubEventQueue &subQueue = subEventQueues_[priorityIndex];
337 // Check whether enough events in higher priority queue are handled continuously.
338 if (subQueue.handledEventsCount < subQueue.maxHandledEventsCount) {
339 subQueue.handledEventsCount++;
340 break;
341 }
342 }
343
344 // Try to pick event from this queue.
345 priorityIndex = i;
346 }
347
348 if (priorityIndex >= SUB_EVENT_QUEUE_NUM) {
349 // If not found any event to distribute, return nullptr.
350 return InnerEvent::Pointer(nullptr, nullptr);
351 }
352
353 // Reset handled event count for sub event queues in higher priority.
354 for (uint32_t i = 0; i < priorityIndex; ++i) {
355 subEventQueues_[i].handledEventsCount = 0;
356 }
357
358 return PopFrontEventFromListLocked(subEventQueues_[priorityIndex].queue);
359 }
360
GetExpiredEventLocked(InnerEvent::TimePoint & nextExpiredTime)361 InnerEvent::Pointer EventQueueBase::GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime)
362 {
363 auto now = InnerEvent::Clock::now();
364 wakeUpTime_ = InnerEvent::TimePoint::max();
365 // Find an event which could be distributed right now.
366 InnerEvent::Pointer event = PickEventLocked(now, wakeUpTime_);
367 if (event) {
368 // Exit idle mode, if found an event to distribute.
369 isIdle_ = false;
370 currentRunningEvent_ = CurrentRunningEvent(now, event);
371 return event;
372 }
373
374 // If found nothing, enter idle mode and make a time stamp.
375 if (!isIdle_) {
376 idleTimeStamp_ = now;
377 isIdle_ = true;
378 }
379
380 if (!idleEvents_.empty()) {
381 const auto &idleEvent = idleEvents_.front();
382
383 // Return the idle event that has been sent before time stamp and reaches its handle time.
384 if ((idleEvent->GetSendTime() <= idleTimeStamp_) && (idleEvent->GetHandleTime() <= now)) {
385 event = PopFrontEventFromListLocked(idleEvents_);
386 currentRunningEvent_ = CurrentRunningEvent(now, event);
387 return event;
388 }
389 }
390
391 // Update wake up time.
392 nextExpiredTime = wakeUpTime_;
393 currentRunningEvent_ = CurrentRunningEvent();
394 return InnerEvent::Pointer(nullptr, nullptr);
395 }
396
GetEvent()397 InnerEvent::Pointer EventQueueBase::GetEvent()
398 {
399 std::unique_lock<std::mutex> lock(queueLock_);
400 while (!finished_) {
401 InnerEvent::TimePoint nextWakeUpTime = InnerEvent::TimePoint::max();
402 InnerEvent::Pointer event = GetExpiredEventLocked(nextWakeUpTime);
403 if (event) {
404 return event;
405 }
406 TryExecuteObserverCallback(nextWakeUpTime, EventRunnerStage::STAGE_BEFORE_WAITING);
407 WaitUntilLocked(nextWakeUpTime, lock);
408 TryExecuteObserverCallback(nextWakeUpTime, EventRunnerStage::STAGE_AFTER_WAITING);
409 }
410
411 HILOGD("Break out");
412 return InnerEvent::Pointer(nullptr, nullptr);
413 }
414
TryExecuteObserverCallback(InnerEvent::TimePoint & nextExpiredTime,EventRunnerStage stage)415 void EventQueueBase::TryExecuteObserverCallback(InnerEvent::TimePoint &nextExpiredTime, EventRunnerStage stage)
416 {
417 uint32_t stageUint = static_cast<uint32_t>(stage);
418 if ((stageUint & observer_.stages) != stageUint) {
419 HILOGD("The observer does not subscribe to this type of notification");
420 return;
421 }
422 if (observer_.notifyCb == nullptr) {
423 HILOGD("notifyCb is nullptr");
424 return;
425 }
426 int64_t consumer = 0;
427 StageInfo info;
428 ObserverTrace obs;
429 obs.source = GetObserverTypeName(observer_.observer);
430 switch (stage) {
431 case EventRunnerStage::STAGE_BEFORE_WAITING:
432 info.sleepTime = NanosecondsToTimeout(TimePointToTimeOut(nextExpiredTime));
433 obs.stage = STAGE_BEFORE_WAITING.data();
434 consumer = ExecuteObserverCallback(obs, stage, info);
435 if (nextExpiredTime < InnerEvent::TimePoint::max()) {
436 HILOGD("time consumer: %{public}lld", static_cast<long long>(consumer));
437 nextExpiredTime = nextExpiredTime + std::chrono::milliseconds(consumer);
438 }
439 break;
440 case EventRunnerStage::STAGE_AFTER_WAITING:
441 obs.stage = STAGE_AFTER_WAITING.data();
442 consumer = ExecuteObserverCallback(obs, stage, info);
443 break;
444 default:
445 HILOGE("this branch is unreachable");
446 break;
447 }
448 if (consumer > GC_TIME_OUT) {
449 HILOGI("execute observer callback task consumer: %{public}lld, stage: %{public}u",
450 static_cast<long long>(consumer), stageUint);
451 }
452 }
453
ExecuteObserverCallback(ObserverTrace obsTrace,EventRunnerStage stage,StageInfo & info)454 int64_t EventQueueBase::ExecuteObserverCallback(ObserverTrace obsTrace, EventRunnerStage stage, StageInfo &info)
455 {
456 auto start = std::chrono::high_resolution_clock::now();
457 info.timestamp = std::chrono::time_point_cast<std::chrono::milliseconds>(start).time_since_epoch().count();
458
459 StartTraceObserver(obsTrace);
460 (observer_.notifyCb)(stage, &info);
461 FinishTraceAdapter();
462 auto end = std::chrono::high_resolution_clock::now();
463 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end-start);
464 return duration.count();
465 }
466
GetObserverTypeName(Observer observerType)467 std::string EventQueueBase::GetObserverTypeName(Observer observerType)
468 {
469 switch (observerType) {
470 case Observer::ARKTS_GC:
471 return "ARKTS_GC";
472 default :
473 return "UNKNOWN_TYPE";
474 }
475 }
476
477
ClearObserver()478 void EventQueueBase::ClearObserver()
479 {
480 observer_.stages = static_cast<uint32_t>(EventRunnerStage::STAGE_INVAILD);
481 observer_.notifyCb = nullptr;
482 }
483
GetExpiredEvent(InnerEvent::TimePoint & nextExpiredTime)484 InnerEvent::Pointer EventQueueBase::GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime)
485 {
486 std::unique_lock<std::mutex> lock(queueLock_);
487 return GetExpiredEventLocked(nextExpiredTime);
488 }
489
DumpCurrentRunningEventId(const InnerEvent::EventId & innerEventId,std::string & content)490 void EventQueueBase::DumpCurrentRunningEventId(const InnerEvent::EventId &innerEventId, std::string &content)
491 {
492 if (innerEventId.index() == TYPE_U32_INDEX) {
493 content.append(", id = " + std::to_string(std::get<uint32_t>(innerEventId)));
494 } else {
495 content.append(", id = " + std::get<std::string>(innerEventId));
496 }
497 }
498
DumpCurrentRunning()499 std::string EventQueueBase::DumpCurrentRunning()
500 {
501 std::string content;
502 if (currentRunningEvent_.beginTime_ == InnerEvent::TimePoint::max()) {
503 content.append("{}");
504 } else {
505 content.append("start at " + InnerEvent::DumpTimeToString(currentRunningEvent_.beginTime_) + ", ");
506 content.append("Event { ");
507 if (!currentRunningEvent_.owner_.expired()) {
508 content.append("send thread = " + std::to_string(currentRunningEvent_.senderKernelThreadId_));
509 content.append(", send time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.sendTime_));
510 content.append(", handle time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.handleTime_));
511 content.append(", trigger time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.triggerTime_));
512 if (currentRunningEvent_.hasTask_) {
513 content.append(", task name = " + currentRunningEvent_.taskName_);
514 } else {
515 DumpCurrentRunningEventId(currentRunningEvent_.innerEventId_, content);
516 }
517 if (currentRunningEvent_.param_ != 0) {
518 content.append(", param = " + std::to_string(currentRunningEvent_.param_));
519 }
520 content.append(", caller = " + currentRunningEvent_.callerInfo_);
521 } else {
522 content.append("No handler");
523 }
524 content.append(" }");
525 }
526
527 return content;
528 }
529
DumpCurentQueueInfo(Dumper & dumper,uint32_t dumpMaxSize)530 void EventQueueBase::DumpCurentQueueInfo(Dumper &dumper, uint32_t dumpMaxSize)
531 {
532 std::string priority[] = {"VIP", "Immediate", "High", "Low"};
533 uint32_t total = 0;
534 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
535 uint32_t n = 0;
536 dumper.Dump(dumper.GetTag() + " " + priority[i] + " priority event queue information:" +
537 std::string(LINE_SEPARATOR));
538 for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
539 ++n;
540 if (total < dumpMaxSize) {
541 dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
542 }
543 ++total;
544 }
545 dumper.Dump(dumper.GetTag() + " Total size of " + priority[i] + " events : " + std::to_string(n) +
546 std::string(LINE_SEPARATOR));
547 }
548 dumper.Dump(dumper.GetTag() + " Idle priority event queue information:" + std::string(LINE_SEPARATOR));
549 int n = 0;
550 for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
551 ++n;
552 if (total < dumpMaxSize) {
553 dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
554 }
555 ++total;
556 }
557 dumper.Dump(dumper.GetTag() + " Total size of Idle events : " + std::to_string(n) + std::string(LINE_SEPARATOR));
558 dumper.Dump(dumper.GetTag() + " Total event size : " + std::to_string(total) + std::string(LINE_SEPARATOR));
559 }
560
Dump(Dumper & dumper)561 void EventQueueBase::Dump(Dumper &dumper)
562 {
563 std::lock_guard<std::mutex> lock(queueLock_);
564 if (!usable_.load()) {
565 HILOGW("EventQueueBase is unavailable.");
566 return;
567 }
568 dumper.Dump(dumper.GetTag() + " Current Running: " + DumpCurrentRunning() + std::string(LINE_SEPARATOR));
569 dumper.Dump(dumper.GetTag() + " History event queue information:" + std::string(LINE_SEPARATOR));
570 uint32_t dumpMaxSize = MAX_DUMP_SIZE;
571 for (uint8_t i = 0; i < HISTORY_EVENT_NUM_POWER; i++) {
572 if (historyEvents_[i].senderKernelThreadId == 0) {
573 continue;
574 }
575 --dumpMaxSize;
576 dumper.Dump(dumper.GetTag() + " No. " + std::to_string(i) + " : " + HistoryQueueDump(historyEvents_[i]));
577 }
578 DumpCurentQueueInfo(dumper, dumpMaxSize);
579 }
580
DumpQueueInfo(std::string & queueInfo)581 void EventQueueBase::DumpQueueInfo(std::string& queueInfo)
582 {
583 std::lock_guard<std::mutex> lock(queueLock_);
584 if (!usable_.load()) {
585 HILOGW("EventQueueBase is unavailable.");
586 return;
587 }
588 std::string priority[] = {"VIP", "Immediate", "High", "Low"};
589 uint32_t total = 0;
590 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
591 uint32_t n = 0;
592 queueInfo += " " + priority[i] + " priority event queue:" + std::string(LINE_SEPARATOR);
593 for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
594 ++n;
595 queueInfo += " No." + std::to_string(n) + " : " + (*it)->Dump();
596 ++total;
597 }
598 queueInfo += " Total size of " + priority[i] + " events : " + std::to_string(n) +
599 std::string(LINE_SEPARATOR);
600 }
601
602 queueInfo += " Idle priority event queue:" + std::string(LINE_SEPARATOR);
603
604 int n = 0;
605 for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
606 ++n;
607 queueInfo += " No." + std::to_string(n) + " : " + (*it)->Dump();
608 ++total;
609 }
610 queueInfo += " Total size of Idle events : " + std::to_string(n) + std::string(LINE_SEPARATOR);
611 queueInfo += " Total event size : " + std::to_string(total);
612 }
613
IsIdle()614 bool EventQueueBase::IsIdle()
615 {
616 return isIdle_;
617 }
618
IsQueueEmpty()619 bool EventQueueBase::IsQueueEmpty()
620 {
621 std::lock_guard<std::mutex> lock(queueLock_);
622 if (!usable_.load()) {
623 HILOGW("EventQueueBase is unavailable.");
624 return false;
625 }
626 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
627 uint32_t queueSize = subEventQueues_[i].queue.size();
628 if (queueSize != 0) {
629 return false;
630 }
631 }
632
633 return idleEvents_.size() == 0;
634 }
635
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)636 void EventQueueBase::PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event)
637 {
638 if (event == nullptr) {
639 HILOGW("event is nullptr.");
640 return;
641 }
642 historyEvents_[historyEventIndex_].senderKernelThreadId = event->GetSenderKernelThreadId();
643 historyEvents_[historyEventIndex_].sendTime = event->GetSendTime();
644 historyEvents_[historyEventIndex_].handleTime = event->GetHandleTime();
645 historyEvents_[historyEventIndex_].triggerTime = InnerEvent::Clock::now();
646 historyEvents_[historyEventIndex_].priority = event->GetEventPriority();
647 historyEvents_[historyEventIndex_].completeTime = InnerEvent::TimePoint::max();
648 currentRunningEvent_.triggerTime_ = InnerEvent::Clock::now();
649
650 if (event->HasTask()) {
651 historyEvents_[historyEventIndex_].hasTask = true;
652 historyEvents_[historyEventIndex_].taskName = event->GetTaskName();
653 } else {
654 historyEvents_[historyEventIndex_].innerEventId = event->GetInnerEventIdEx();
655 }
656 }
657
PushHistoryQueueAfterDistribute()658 void EventQueueBase::PushHistoryQueueAfterDistribute()
659 {
660 historyEvents_[historyEventIndex_].completeTime = InnerEvent::Clock::now();
661 historyEventIndex_++;
662 historyEventIndex_ = historyEventIndex_ & (HISTORY_EVENT_NUM_POWER - 1);
663 }
664
HistoryQueueDump(const HistoryEvent & historyEvent)665 std::string EventQueueBase::HistoryQueueDump(const HistoryEvent &historyEvent)
666 {
667 std::string content;
668 std::vector<std::string> prioritys = {"VIP", "Immediate", "High", "Low", "IDEL"};
669
670 content.append("Event { ");
671 content.append("send thread = " + std::to_string(historyEvent.senderKernelThreadId));
672 content.append(", send time = " + InnerEvent::DumpTimeToString(historyEvent.sendTime));
673 content.append(", handle time = " + InnerEvent::DumpTimeToString(historyEvent.handleTime));
674 content.append(", trigger time = " + InnerEvent::DumpTimeToString(historyEvent.triggerTime));
675
676 if (historyEvent.completeTime == InnerEvent::TimePoint::max()) {
677 content.append(", completeTime time = ");
678 } else {
679 content.append(", completeTime time = " + InnerEvent::DumpTimeToString(historyEvent.completeTime));
680 }
681 if (historyEvent.priority >= 0 && historyEvent.priority < prioritys.size()) {
682 content.append(", priority = " + prioritys[historyEvent.priority]);
683 } else {
684 content.append(", priority = ");
685 }
686
687 if (historyEvent.hasTask) {
688 content.append(", task name = " + historyEvent.taskName);
689 } else {
690 DumpCurrentRunningEventId(historyEvent.innerEventId, content);
691 }
692 content.append(" }" + std::string(LINE_SEPARATOR));
693
694 return content;
695 }
696
DumpCurrentQueueSize()697 std::string EventQueueBase::DumpCurrentQueueSize()
698 {
699 return "Current queue size: VIP = " +
700 std::to_string(subEventQueues_[static_cast<int>(Priority::VIP)].queue.size()) + ", IMMEDIATE = " +
701 std::to_string(subEventQueues_[static_cast<int>(Priority::IMMEDIATE)].queue.size()) + ", HIGH = " +
702 std::to_string(subEventQueues_[static_cast<int>(Priority::HIGH)].queue.size()) + ", LOW = " +
703 std::to_string(subEventQueues_[static_cast<int>(Priority::LOW)].queue.size()) + ", IDLE = " +
704 std::to_string(idleEvents_.size()) + " ; ";
705 }
706
HasPreferEvent(int basePrio)707 bool EventQueueBase::HasPreferEvent(int basePrio)
708 {
709 for (int prio = 0; prio < basePrio; prio++) {
710 if (subEventQueues_[prio].queue.size() > 0) {
711 return true;
712 }
713 }
714 return false;
715 }
716
QueryPendingTaskInfo(int32_t fileDescriptor)717 PendingTaskInfo EventQueueBase::QueryPendingTaskInfo(int32_t fileDescriptor)
718 {
719 PendingTaskInfo pendingTaskInfo;
720 std::shared_ptr<FileDescriptorInfo> fileDescriptorInfo = nullptr;
721 if (useDeamonIoWaiter_) {
722 fileDescriptorInfo = DeamonIoWaiter::GetInstance().GetFileDescriptorMap(fileDescriptor);
723 } else if (ioWaiter_) {
724 fileDescriptorInfo = ioWaiter_->GetFileDescriptorMap(fileDescriptor);
725 }
726 if (fileDescriptorInfo == nullptr) {
727 HILOGW("QueryPendingTaskInfo fileDescriptorInfo is unavailable.");
728 return pendingTaskInfo;
729 }
730
731 std::lock_guard<std::mutex> lock(queueLock_);
732 if (!usable_.load()) {
733 HILOGW("QueryPendingTaskInfo event queue is unavailable.");
734 return pendingTaskInfo;
735 }
736
737 auto now = InnerEvent::Clock::now();
738 for (auto it = subEventQueues_[0].queue.begin(); it != subEventQueues_[0].queue.end(); it++) {
739 if ((*it)->GetTaskName() == fileDescriptorInfo->taskName_) {
740 pendingTaskInfo.taskCount++;
741 InnerEvent::TimePoint handlerTime = (*it)->GetHandleTime();
742 if (handlerTime >= now) {
743 continue;
744 }
745 auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(now - handlerTime).count();
746 if (duration > pendingTaskInfo.MaxPendingTime) {
747 pendingTaskInfo.MaxPendingTime = duration;
748 }
749 }
750 }
751 EH_LOGI_LIMIT("Pend task %{public}d %{public}d", pendingTaskInfo.taskCount, pendingTaskInfo.MaxPendingTime);
752 return PendingTaskInfo();
753 }
754
CancelAndWait()755 void EventQueueBase::CancelAndWait()
756 {
757 HILOGD("EventQueueBase CancelAndWait enter.");
758 }
759
CurrentRunningEvent()760 CurrentRunningEvent::CurrentRunningEvent()
761 {
762 beginTime_ = InnerEvent::TimePoint::max();
763 }
764
CurrentRunningEvent(InnerEvent::TimePoint time,InnerEvent::Pointer & event)765 CurrentRunningEvent::CurrentRunningEvent(InnerEvent::TimePoint time, InnerEvent::Pointer &event)
766 {
767 beginTime_ = time;
768 owner_ = event->GetWeakOwner();
769 senderKernelThreadId_ = event->GetSenderKernelThreadId();
770 sendTime_ = event->GetSendTime();
771 handleTime_ = event->GetHandleTime();
772 param_ = event->GetParam();
773 callerInfo_ = (event->GetCaller()).ToString();
774 if (event->HasTask()) {
775 hasTask_ = true;
776 taskName_ = event->GetTaskName();
777 } else {
778 innerEventId_ = event->GetInnerEventIdEx();
779 }
780 }
781
782 } // namespace AppExecFwk
783 } // namespace OHOS
784