1 /*
2 * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "event_queue.h"
17
18 #include <algorithm>
19 #include <iterator>
20 #include <mutex>
21
22 #include "epoll_io_waiter.h"
23 #include "event_handler.h"
24 #include "event_handler_utils.h"
25 #include "event_logger.h"
26 #include "none_io_waiter.h"
27
28
29 namespace OHOS {
30 namespace AppExecFwk {
31 namespace {
32
33 DEFINE_EH_HILOG_LABEL("EventQueue");
34 constexpr uint32_t MAX_DUMP_SIZE = 500;
35 // Help to insert events into the event queue sorted by handle time.
InsertEventsLocked(std::list<InnerEvent::Pointer> & events,InnerEvent::Pointer & event)36 inline void InsertEventsLocked(std::list<InnerEvent::Pointer> &events, InnerEvent::Pointer &event)
37 {
38 auto f = [](const InnerEvent::Pointer &first, const InnerEvent::Pointer &second) {
39 if (!first || !second) {
40 return false;
41 }
42 return first->GetHandleTime() < second->GetHandleTime();
43 };
44 auto it = std::upper_bound(events.begin(), events.end(), event, f);
45 events.insert(it, std::move(event));
46 }
47
48 // Help to remove file descriptor listeners.
49 template<typename T>
RemoveFileDescriptorListenerLocked(std::map<int32_t,std::shared_ptr<FileDescriptorListener>> & listeners,const std::shared_ptr<IoWaiter> & ioWaiter,const T & filter)50 void RemoveFileDescriptorListenerLocked(std::map<int32_t, std::shared_ptr<FileDescriptorListener>> &listeners,
51 const std::shared_ptr<IoWaiter> &ioWaiter, const T &filter)
52 {
53 if (!ioWaiter) {
54 return;
55 }
56 for (auto it = listeners.begin(); it != listeners.end();) {
57 if (filter(it->second)) {
58 ioWaiter->RemoveFileDescriptor(it->first);
59 it = listeners.erase(it);
60 } else {
61 ++it;
62 }
63 }
64 }
65
66 // 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)67 inline bool CheckEventInListLocked(const std::list<InnerEvent::Pointer> &events, const InnerEvent::TimePoint &now,
68 InnerEvent::TimePoint &nextWakeUpTime)
69 {
70 if (!events.empty()) {
71 const auto &handleTime = events.front()->GetHandleTime();
72 if (handleTime < nextWakeUpTime) {
73 nextWakeUpTime = handleTime;
74 return handleTime <= now;
75 }
76 }
77
78 return false;
79 }
80
PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> & events)81 inline InnerEvent::Pointer PopFrontEventFromListLocked(std::list<InnerEvent::Pointer> &events)
82 {
83 InnerEvent::Pointer event = std::move(events.front());
84 events.pop_front();
85 return event;
86 }
87 } // unnamed namespace
88
EventQueue()89 EventQueue::EventQueue() : ioWaiter_(std::make_shared<NoneIoWaiter>()), historyEvents_(
90 std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
91 {
92 HILOGD("enter");
93 }
94
EventQueue(const std::shared_ptr<IoWaiter> & ioWaiter)95 EventQueue::EventQueue(const std::shared_ptr<IoWaiter> &ioWaiter)
96 : ioWaiter_(ioWaiter ? ioWaiter : std::make_shared<NoneIoWaiter>()), historyEvents_(
97 std::vector<HistoryEvent>(HISTORY_EVENT_NUM_POWER))
98 {
99 HILOGD("enter");
100 if (ioWaiter_->SupportListeningFileDescriptor()) {
101 // Set callback to handle events from file descriptors.
102 ioWaiter_->SetFileDescriptorEventCallback(
103 std::bind(&EventQueue::HandleFileDescriptorEvent, this, std::placeholders::_1, std::placeholders::_2,
104 std::placeholders::_3));
105 }
106 }
107
~EventQueue()108 EventQueue::~EventQueue()
109 {
110 std::lock_guard<std::mutex> lock(queueLock_);
111 usable_.store(false);
112 ioWaiter_ = nullptr;
113 HILOGI("EventQueue is unavailable hence");
114 }
115
Insert(InnerEvent::Pointer & event,Priority priority)116 void EventQueue::Insert(InnerEvent::Pointer &event, Priority priority)
117 {
118 if (!event) {
119 HILOGE("Could not insert an invalid event");
120 return;
121 }
122 HILOGD("Insert task: %{public}s .", (event->GetEventUniqueId()).c_str());
123 std::lock_guard<std::mutex> lock(queueLock_);
124 if (!usable_.load()) {
125 HILOGW("EventQueue is unavailable.");
126 return;
127 }
128 bool needNotify = false;
129 switch (priority) {
130 case Priority::IMMEDIATE:
131 case Priority::HIGH:
132 case Priority::LOW: {
133 needNotify = (event->GetHandleTime() < wakeUpTime_);
134 InsertEventsLocked(subEventQueues_[static_cast<uint32_t>(priority)].queue, event);
135 break;
136 }
137 case Priority::IDLE: {
138 // Never wake up thread if insert an idle event.
139 InsertEventsLocked(idleEvents_, event);
140 break;
141 }
142 default:
143 break;
144 }
145
146 if (needNotify) {
147 ioWaiter_->NotifyOne();
148 }
149 }
150
RemoveOrphan()151 void EventQueue::RemoveOrphan()
152 {
153 HILOGD("enter");
154 // Remove all events which lost its owner.
155 auto filter = [](const InnerEvent::Pointer &p) { return !p->GetOwner(); };
156
157 RemoveOrphan(filter);
158
159 // Remove all listeners which lost its owner.
160 auto listenerFilter = [](const std::shared_ptr<FileDescriptorListener> &listener) {
161 if (!listener) {
162 return true;
163 }
164 HILOGD("Start get to GetOwner");
165 return !listener->GetOwner();
166 };
167
168 std::lock_guard<std::mutex> lock(queueLock_);
169 if (!usable_.load()) {
170 HILOGW("EventQueue is unavailable.");
171 return;
172 }
173 RemoveFileDescriptorListenerLocked(listeners_, ioWaiter_, listenerFilter);
174 }
175
176
RemoveAll()177 void EventQueue::RemoveAll()
178 {
179 HILOGD("enter");
180 std::lock_guard<std::mutex> lock(queueLock_);
181 if (!usable_.load()) {
182 HILOGW("EventQueue is unavailable.");
183 return;
184 }
185 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
186 subEventQueues_[i].queue.clear();
187 }
188 idleEvents_.clear();
189 }
190
Remove(const std::shared_ptr<EventHandler> & owner)191 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner)
192 {
193 HILOGD("enter");
194 if (!owner) {
195 HILOGE("Invalid owner");
196 return;
197 }
198
199 auto filter = [&owner](const InnerEvent::Pointer &p) { return (p->GetOwner() == owner); };
200
201 Remove(filter);
202 }
203
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)204 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
205 {
206 HILOGD("enter");
207 if (!owner) {
208 HILOGE("Invalid owner");
209 return;
210 }
211 auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
212 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
213 };
214
215 Remove(filter);
216 }
217
Remove(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId,int64_t param)218 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId, int64_t param)
219 {
220 HILOGD("enter");
221 if (!owner) {
222 HILOGE("Invalid owner");
223 return;
224 }
225
226 auto filter = [&owner, innerEventId, param](const InnerEvent::Pointer &p) {
227 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId) &&
228 (p->GetParam() == param);
229 };
230
231 Remove(filter);
232 }
233
Remove(const std::shared_ptr<EventHandler> & owner,const std::string & name)234 void EventQueue::Remove(const std::shared_ptr<EventHandler> &owner, const std::string &name)
235 {
236 HILOGD("enter");
237 if ((!owner) || (name.empty())) {
238 HILOGE("Invalid owner or task name");
239 return;
240 }
241
242 auto filter = [&owner, &name](const InnerEvent::Pointer &p) {
243 if (p == nullptr) {
244 return false;
245 }
246 HILOGD("Event address: %{public}p .", &p);
247 return (p->HasTask()) && (p->GetOwner() == owner) && (p->GetTaskName() == name);
248 };
249
250 Remove(filter);
251 }
252
Remove(const RemoveFilter & filter)253 void EventQueue::Remove(const RemoveFilter &filter)
254 {
255 HILOGD("enter");
256 std::lock_guard<std::mutex> lock(queueLock_);
257 if (!usable_.load()) {
258 HILOGW("EventQueue is unavailable.");
259 return;
260 }
261 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
262 subEventQueues_[i].queue.remove_if(filter);
263 }
264 idleEvents_.remove_if(filter);
265 }
266
RemoveOrphan(const RemoveFilter & filter)267 void EventQueue::RemoveOrphan(const RemoveFilter &filter)
268 {
269 std::list<InnerEvent::Pointer> releaseIdleEvents;
270 std::array<SubEventQueue, SUB_EVENT_QUEUE_NUM> releaseEventsQueue;
271 {
272 std::lock_guard<std::mutex> lock(queueLock_);
273 if (!usable_.load()) {
274 HILOGW("EventQueue is unavailable.");
275 return;
276 }
277 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
278 auto it = std::stable_partition(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
279 std::move(subEventQueues_[i].queue.begin(), it, std::back_inserter(releaseEventsQueue[i].queue));
280 subEventQueues_[i].queue.erase(subEventQueues_[i].queue.begin(), it);
281 }
282 auto idleEventIt = std::stable_partition(idleEvents_.begin(), idleEvents_.end(), filter);
283 std::move(idleEvents_.begin(), idleEventIt, std::back_inserter(releaseIdleEvents));
284 idleEvents_.erase(idleEvents_.begin(), idleEventIt);
285 }
286 }
287
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,uint32_t innerEventId)288 bool EventQueue::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, uint32_t innerEventId)
289 {
290 if (!owner) {
291 HILOGE("Invalid owner");
292 return false;
293 }
294 auto filter = [&owner, innerEventId](const InnerEvent::Pointer &p) {
295 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetInnerEventId() == innerEventId);
296 };
297 return HasInnerEvent(filter);
298 }
299
HasInnerEvent(const std::shared_ptr<EventHandler> & owner,int64_t param)300 bool EventQueue::HasInnerEvent(const std::shared_ptr<EventHandler> &owner, int64_t param)
301 {
302 if (!owner) {
303 HILOGE("Invalid owner");
304 return false;
305 }
306 auto filter = [&owner, param](const InnerEvent::Pointer &p) {
307 return (!p->HasTask()) && (p->GetOwner() == owner) && (p->GetParam() == param);
308 };
309 return HasInnerEvent(filter);
310 }
311
HasInnerEvent(const HasFilter & filter)312 bool EventQueue::HasInnerEvent(const HasFilter &filter)
313 {
314 std::lock_guard<std::mutex> lock(queueLock_);
315 if (!usable_.load()) {
316 HILOGW("EventQueue is unavailable.");
317 return false;
318 }
319 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
320 std::list<InnerEvent::Pointer>::iterator iter =
321 std::find_if(subEventQueues_[i].queue.begin(), subEventQueues_[i].queue.end(), filter);
322 if (iter != subEventQueues_[i].queue.end()) {
323 return true;
324 }
325 }
326 std::list<InnerEvent::Pointer>::iterator iter = std::find_if(idleEvents_.begin(), idleEvents_.end(), filter);
327 return iter != idleEvents_.end();
328 }
329
PickEventLocked(const InnerEvent::TimePoint & now,InnerEvent::TimePoint & nextWakeUpTime)330 InnerEvent::Pointer EventQueue::PickEventLocked(const InnerEvent::TimePoint &now, InnerEvent::TimePoint &nextWakeUpTime)
331 {
332 uint32_t priorityIndex = SUB_EVENT_QUEUE_NUM;
333 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
334 // Check whether any event need to be distributed.
335 if (!CheckEventInListLocked(subEventQueues_[i].queue, now, nextWakeUpTime)) {
336 continue;
337 }
338
339 // Check whether any event in higher priority need to be distributed.
340 if (priorityIndex < SUB_EVENT_QUEUE_NUM) {
341 SubEventQueue &subQueue = subEventQueues_[priorityIndex];
342 // Check whether enough events in higher priority queue are handled continuously.
343 if (subQueue.handledEventsCount < subQueue.maxHandledEventsCount) {
344 subQueue.handledEventsCount++;
345 break;
346 }
347 }
348
349 // Try to pick event from this queue.
350 priorityIndex = i;
351 }
352
353 if (priorityIndex >= SUB_EVENT_QUEUE_NUM) {
354 // If not found any event to distribute, return nullptr.
355 return InnerEvent::Pointer(nullptr, nullptr);
356 }
357
358 // Reset handled event count for sub event queues in higher priority.
359 for (uint32_t i = 0; i < priorityIndex; ++i) {
360 subEventQueues_[i].handledEventsCount = 0;
361 }
362
363 return PopFrontEventFromListLocked(subEventQueues_[priorityIndex].queue);
364 }
365
GetExpiredEventLocked(InnerEvent::TimePoint & nextExpiredTime)366 InnerEvent::Pointer EventQueue::GetExpiredEventLocked(InnerEvent::TimePoint &nextExpiredTime)
367 {
368 auto now = InnerEvent::Clock::now();
369 wakeUpTime_ = InnerEvent::TimePoint::max();
370 // Find an event which could be distributed right now.
371 InnerEvent::Pointer event = PickEventLocked(now, wakeUpTime_);
372 if (event) {
373 // Exit idle mode, if found an event to distribute.
374 isIdle_ = false;
375 currentRunningEvent_ = CurrentRunningEvent(now, event);
376 return event;
377 }
378
379 // If found nothing, enter idle mode and make a time stamp.
380 if (!isIdle_) {
381 idleTimeStamp_ = now;
382 isIdle_ = true;
383 }
384
385 if (!idleEvents_.empty()) {
386 const auto &idleEvent = idleEvents_.front();
387
388 // Return the idle event that has been sent before time stamp and reaches its handle time.
389 if ((idleEvent->GetSendTime() <= idleTimeStamp_) && (idleEvent->GetHandleTime() <= now)) {
390 event = PopFrontEventFromListLocked(idleEvents_);
391 currentRunningEvent_ = CurrentRunningEvent(now, event);
392 return event;
393 }
394 }
395
396 // Update wake up time.
397 nextExpiredTime = wakeUpTime_;
398 currentRunningEvent_ = CurrentRunningEvent();
399 return InnerEvent::Pointer(nullptr, nullptr);
400 }
401
GetEvent()402 InnerEvent::Pointer EventQueue::GetEvent()
403 {
404 std::unique_lock<std::mutex> lock(queueLock_);
405 while (!finished_) {
406 InnerEvent::TimePoint nextWakeUpTime = InnerEvent::TimePoint::max();
407 InnerEvent::Pointer event = GetExpiredEventLocked(nextWakeUpTime);
408 if (event) {
409 return event;
410 }
411 WaitUntilLocked(nextWakeUpTime, lock);
412 }
413
414 HILOGD("Break out");
415 return InnerEvent::Pointer(nullptr, nullptr);
416 }
417
GetExpiredEvent(InnerEvent::TimePoint & nextExpiredTime)418 InnerEvent::Pointer EventQueue::GetExpiredEvent(InnerEvent::TimePoint &nextExpiredTime)
419 {
420 std::unique_lock<std::mutex> lock(queueLock_);
421 return GetExpiredEventLocked(nextExpiredTime);
422 }
423
AddFileDescriptorListener(int32_t fileDescriptor,uint32_t events,const std::shared_ptr<FileDescriptorListener> & listener,const std::string & taskName)424 ErrCode EventQueue::AddFileDescriptorListener(int32_t fileDescriptor, uint32_t events,
425 const std::shared_ptr<FileDescriptorListener> &listener, const std::string &taskName)
426 {
427 if ((fileDescriptor < 0) || ((events & FILE_DESCRIPTOR_EVENTS_MASK) == 0) || (!listener)) {
428 HILOGE("%{public}d, %{public}u, %{public}s: Invalid parameter",
429 fileDescriptor, events, listener ? "valid" : "null");
430 return EVENT_HANDLER_ERR_INVALID_PARAM;
431 }
432
433 std::lock_guard<std::mutex> lock(queueLock_);
434 if (!usable_.load()) {
435 HILOGW("EventQueue is unavailable.");
436 return EVENT_HANDLER_ERR_NO_EVENT_RUNNER;
437 }
438 auto it = listeners_.find(fileDescriptor);
439 if (it != listeners_.end()) {
440 HILOGE("File descriptor %{public}d is already in listening", fileDescriptor);
441 return EVENT_HANDLER_ERR_FD_ALREADY;
442 }
443
444 if (!EnsureIoWaiterSupportListerningFileDescriptorLocked()) {
445 return EVENT_HANDLER_ERR_FD_NOT_SUPPORT;
446 }
447
448 if (!ioWaiter_->AddFileDescriptor(fileDescriptor, events, taskName)) {
449 HILOGE("Failed to add file descriptor into IO waiter");
450 return EVENT_HANDLER_ERR_FD_FAILED;
451 }
452
453 listeners_.emplace(fileDescriptor, listener);
454 return ERR_OK;
455 }
456
RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> & owner)457 void EventQueue::RemoveFileDescriptorListener(const std::shared_ptr<EventHandler> &owner)
458 {
459 HILOGD("enter");
460 if (!owner) {
461 HILOGE("Invalid owner");
462 return;
463 }
464
465 auto listenerFilter = [&owner](const std::shared_ptr<FileDescriptorListener> &listener) {
466 if (!listener) {
467 return false;
468 }
469 return listener->GetOwner() == owner;
470 };
471
472 std::lock_guard<std::mutex> lock(queueLock_);
473 if (!usable_.load()) {
474 HILOGW("EventQueue is unavailable.");
475 return;
476 }
477 RemoveFileDescriptorListenerLocked(listeners_, ioWaiter_, listenerFilter);
478 }
479
RemoveFileDescriptorListener(int32_t fileDescriptor)480 void EventQueue::RemoveFileDescriptorListener(int32_t fileDescriptor)
481 {
482 HILOGD("enter");
483 if (fileDescriptor < 0) {
484 HILOGE("%{public}d: Invalid file descriptor", fileDescriptor);
485 return;
486 }
487
488 std::lock_guard<std::mutex> lock(queueLock_);
489 if (!usable_.load()) {
490 HILOGW("EventQueue is unavailable.");
491 return;
492 }
493 if (listeners_.erase(fileDescriptor) > 0) {
494 ioWaiter_->RemoveFileDescriptor(fileDescriptor);
495 }
496 }
497
Prepare()498 void EventQueue::Prepare()
499 {
500 HILOGD("enter");
501 std::lock_guard<std::mutex> lock(queueLock_);
502 if (!usable_.load()) {
503 HILOGW("EventQueue is unavailable.");
504 return;
505 }
506 finished_ = false;
507 }
508
Finish()509 void EventQueue::Finish()
510 {
511 HILOGD("enter");
512 std::lock_guard<std::mutex> lock(queueLock_);
513 if (!usable_.load()) {
514 HILOGW("EventQueue is unavailable.");
515 return;
516 }
517 finished_ = true;
518 ioWaiter_->NotifyAll();
519 }
520
WaitUntilLocked(const InnerEvent::TimePoint & when,std::unique_lock<std::mutex> & lock)521 void EventQueue::WaitUntilLocked(const InnerEvent::TimePoint &when, std::unique_lock<std::mutex> &lock)
522 {
523 // Get a temp reference of IO waiter, otherwise it maybe released while waiting.
524 auto ioWaiterHolder = ioWaiter_;
525 if (!ioWaiterHolder->WaitFor(lock, TimePointToTimeOut(when))) {
526 HILOGE("Failed to call wait, reset IO waiter");
527 ioWaiter_ = std::make_shared<NoneIoWaiter>();
528 listeners_.clear();
529 }
530 }
531
HandleFileDescriptorEvent(int32_t fileDescriptor,uint32_t events,const std::string & taskName)532 void EventQueue::HandleFileDescriptorEvent(int32_t fileDescriptor, uint32_t events,
533 const std::string &taskName) __attribute__((no_sanitize("cfi")))
534 {
535 std::shared_ptr<FileDescriptorListener> listener;
536 {
537 std::lock_guard<std::mutex> lock(queueLock_);
538 if (!usable_.load()) {
539 HILOGW("EventQueue is unavailable.");
540 return;
541 }
542 auto it = listeners_.find(fileDescriptor);
543 if (it == listeners_.end()) {
544 HILOGW("Can not found listener, maybe it is removed");
545 return;
546 }
547
548 // Hold instance of listener.
549 listener = it->second;
550 if (!listener) {
551 return;
552 }
553 }
554
555 auto handler = listener->GetOwner();
556 if (!handler) {
557 HILOGW("Owner of listener is released");
558 return;
559 }
560
561 std::weak_ptr<FileDescriptorListener> wp = listener;
562 auto f = [fileDescriptor, events, wp]() {
563 auto listener = wp.lock();
564 if (!listener) {
565 HILOGW("Listener is released");
566 return;
567 }
568
569 if ((events & FILE_DESCRIPTOR_INPUT_EVENT) != 0) {
570 listener->OnReadable(fileDescriptor);
571 }
572
573 if ((events & FILE_DESCRIPTOR_OUTPUT_EVENT) != 0) {
574 listener->OnWritable(fileDescriptor);
575 }
576
577 if ((events & FILE_DESCRIPTOR_SHUTDOWN_EVENT) != 0) {
578 listener->OnShutdown(fileDescriptor);
579 }
580
581 if ((events & FILE_DESCRIPTOR_EXCEPTION_EVENT) != 0) {
582 listener->OnException(fileDescriptor);
583 }
584 };
585
586 // Post a high priority task to handle file descriptor events.
587 handler->PostHighPriorityTask(f, taskName);
588 }
589
EnsureIoWaiterSupportListerningFileDescriptorLocked()590 bool EventQueue::EnsureIoWaiterSupportListerningFileDescriptorLocked()
591 {
592 HILOGD("enter");
593 if (ioWaiter_->SupportListeningFileDescriptor()) {
594 return true;
595 }
596
597 auto newIoWaiter = std::make_shared<EpollIoWaiter>();
598 if (!newIoWaiter->Init()) {
599 HILOGE("Failed to initialize epoll");
600 return false;
601 }
602
603 // Set callback to handle events from file descriptors.
604 newIoWaiter->SetFileDescriptorEventCallback(
605 std::bind(&EventQueue::HandleFileDescriptorEvent, this, std::placeholders::_1, std::placeholders::_2,
606 std::placeholders::_3));
607
608 ioWaiter_->NotifyAll();
609 ioWaiter_ = newIoWaiter;
610 return true;
611 }
612
DumpCurrentRunningEventId(const InnerEvent::EventId & innerEventId,std::string & content)613 void EventQueue::DumpCurrentRunningEventId(const InnerEvent::EventId &innerEventId, std::string &content)
614 {
615 if (innerEventId.index() == TYPE_U32_INDEX) {
616 content.append(", id = " + std::to_string(std::get<uint32_t>(innerEventId)));
617 } else {
618 content.append(", id = " + std::get<std::string>(innerEventId));
619 }
620 }
621
DumpCurrentRunning()622 std::string EventQueue::DumpCurrentRunning()
623 {
624 std::string content;
625 if (currentRunningEvent_.beginTime_ == InnerEvent::TimePoint::max()) {
626 content.append("{}");
627 } else {
628 content.append("start at " + InnerEvent::DumpTimeToString(currentRunningEvent_.beginTime_) + ", ");
629 content.append("Event { ");
630 if (!currentRunningEvent_.owner_.expired()) {
631 content.append("send thread = " + std::to_string(currentRunningEvent_.senderKernelThreadId_));
632 content.append(", send time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.sendTime_));
633 content.append(", handle time = " + InnerEvent::DumpTimeToString(currentRunningEvent_.handleTime_));
634 if (currentRunningEvent_.hasTask_) {
635 content.append(", task name = " + currentRunningEvent_.taskName_);
636 } else {
637 DumpCurrentRunningEventId(currentRunningEvent_.innerEventId_, content);
638 }
639 if (currentRunningEvent_.param_ != 0) {
640 content.append(", param = " + std::to_string(currentRunningEvent_.param_));
641 }
642 } else {
643 content.append("No handler");
644 }
645 content.append(" }");
646 }
647
648 return content;
649 }
650
Dump(Dumper & dumper)651 void EventQueue::Dump(Dumper &dumper)
652 {
653 std::lock_guard<std::mutex> lock(queueLock_);
654 if (!usable_.load()) {
655 HILOGW("EventQueue is unavailable.");
656 return;
657 }
658
659 dumper.Dump(dumper.GetTag() + " Current Running: " + DumpCurrentRunning() + std::string(LINE_SEPARATOR));
660
661 dumper.Dump(dumper.GetTag() + " History event queue information:" + std::string(LINE_SEPARATOR));
662 uint32_t dumpMaxSize = MAX_DUMP_SIZE;
663 for (uint8_t i = 0; i < HISTORY_EVENT_NUM_POWER; i++) {
664 if (historyEvents_[i].senderKernelThreadId == 0) {
665 continue;
666 }
667 --dumpMaxSize;
668 dumper.Dump(dumper.GetTag() + " No. " + std::to_string(i) + " : " + HistoryQueueDump(historyEvents_[i]));
669 }
670
671 std::string priority[] = {"Immediate", "High", "Low"};
672 uint32_t total = 0;
673 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
674 uint32_t n = 0;
675 dumper.Dump(dumper.GetTag() + " " + priority[i] + " priority event queue information:" + std::string(LINE_SEPARATOR));
676 for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
677 if (total < dumpMaxSize) {
678 ++n;
679 dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
680 }
681 ++total;
682 }
683 dumper.Dump(
684 dumper.GetTag() + " Total size of " + priority[i] + " events : " + std::to_string(n) + std::string(LINE_SEPARATOR));
685 }
686
687 dumper.Dump(dumper.GetTag() + " Idle priority event queue information:" + std::string(LINE_SEPARATOR));
688 int n = 0;
689 for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
690 if (total < dumpMaxSize) {
691 ++n;
692 dumper.Dump(dumper.GetTag() + " No." + std::to_string(n) + " : " + (*it)->Dump());
693 }
694 ++total;
695 }
696 dumper.Dump(dumper.GetTag() + " Total size of Idle events : " + std::to_string(n) + std::string(LINE_SEPARATOR));
697
698 dumper.Dump(dumper.GetTag() + " Total event size : " + std::to_string(total) + std::string(LINE_SEPARATOR));
699 }
700
DumpQueueInfo(std::string & queueInfo)701 void EventQueue::DumpQueueInfo(std::string& queueInfo)
702 {
703 std::lock_guard<std::mutex> lock(queueLock_);
704 if (!usable_.load()) {
705 HILOGW("EventQueue is unavailable.");
706 return;
707 }
708 std::string priority[] = {"Immediate", "High", "Low"};
709 uint32_t total = 0;
710 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
711 uint32_t n = 0;
712 queueInfo += " " + priority[i] + " priority event queue:" + std::string(LINE_SEPARATOR);
713 for (auto it = subEventQueues_[i].queue.begin(); it != subEventQueues_[i].queue.end(); ++it) {
714 ++n;
715 queueInfo += " No." + std::to_string(n) + " : " + (*it)->Dump();
716 ++total;
717 }
718 queueInfo += " Total size of " + priority[i] + " events : " + std::to_string(n) + std::string(LINE_SEPARATOR);
719 }
720
721 queueInfo += " Idle priority event queue:" + std::string(LINE_SEPARATOR);
722
723 int n = 0;
724 for (auto it = idleEvents_.begin(); it != idleEvents_.end(); ++it) {
725 ++n;
726 queueInfo += " No." + std::to_string(n) + " : " + (*it)->Dump();
727 ++total;
728 }
729 queueInfo += " Total size of Idle events : " + std::to_string(n) + std::string(LINE_SEPARATOR);
730
731 queueInfo += " Total event size : " + std::to_string(total);
732 }
733
IsIdle()734 bool EventQueue::IsIdle()
735 {
736 return isIdle_;
737 }
738
IsQueueEmpty()739 bool EventQueue::IsQueueEmpty()
740 {
741 std::lock_guard<std::mutex> lock(queueLock_);
742 if (!usable_.load()) {
743 HILOGW("EventQueue is unavailable.");
744 return false;
745 }
746 for (uint32_t i = 0; i < SUB_EVENT_QUEUE_NUM; ++i) {
747 uint32_t queueSize = subEventQueues_[i].queue.size();
748 if (queueSize != 0) {
749 return false;
750 }
751 }
752
753 return idleEvents_.size() == 0;
754 }
755
PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer & event)756 void EventQueue::PushHistoryQueueBeforeDistribute(const InnerEvent::Pointer &event)
757 {
758 if (event == nullptr) {
759 HILOGW("event is nullptr.");
760 return;
761 }
762 historyEvents_[historyEventIndex_].senderKernelThreadId = event->GetSenderKernelThreadId();
763 historyEvents_[historyEventIndex_].sendTime = event->GetSendTime();
764 historyEvents_[historyEventIndex_].handleTime = event->GetHandleTime();
765 historyEvents_[historyEventIndex_].triggerTime = InnerEvent::Clock::now();
766
767 if (event->HasTask()) {
768 historyEvents_[historyEventIndex_].hasTask = true;
769 historyEvents_[historyEventIndex_].taskName = event->GetTaskName();
770 } else {
771 historyEvents_[historyEventIndex_].innerEventId = event->GetInnerEventIdEx();
772 }
773 }
774
PushHistoryQueueAfterDistribute()775 void EventQueue::PushHistoryQueueAfterDistribute()
776 {
777 historyEvents_[historyEventIndex_].completeTime = InnerEvent::Clock::now();
778 historyEventIndex_++;
779 historyEventIndex_ = historyEventIndex_ & (HISTORY_EVENT_NUM_POWER - 1);
780 }
781
HistoryQueueDump(const HistoryEvent & historyEvent)782 std::string EventQueue::HistoryQueueDump(const HistoryEvent &historyEvent)
783 {
784 std::string content;
785
786 content.append("Event { ");
787 content.append("send thread = " + std::to_string(historyEvent.senderKernelThreadId));
788 content.append(", send time = " + InnerEvent::DumpTimeToString(historyEvent.sendTime));
789 content.append(", handle time = " + InnerEvent::DumpTimeToString(historyEvent.handleTime));
790 content.append(", trigger time = " + InnerEvent::DumpTimeToString(historyEvent.triggerTime));
791 content.append(", completeTime time = " + InnerEvent::DumpTimeToString(historyEvent.completeTime));
792 if (historyEvent.hasTask) {
793 content.append(", task name = " + historyEvent.taskName);
794 } else {
795 DumpCurrentRunningEventId(historyEvent.innerEventId, content);
796 }
797 content.append(" }" + std::string(LINE_SEPARATOR));
798
799 return content;
800 }
801
DumpCurrentQueueSize()802 std::string EventQueue::DumpCurrentQueueSize()
803 {
804 return "Current queue size: IMMEDIATE = " +
805 std::to_string(subEventQueues_[static_cast<int>(Priority::IMMEDIATE)].queue.size()) + ", HIGH = " +
806 std::to_string(subEventQueues_[static_cast<int>(Priority::HIGH)].queue.size()) + ", LOW = " +
807 std::to_string(subEventQueues_[static_cast<int>(Priority::LOW)].queue.size()) + ", IDLE = " +
808 std::to_string(idleEvents_.size()) + " ;";
809 }
810
CurrentRunningEvent()811 CurrentRunningEvent::CurrentRunningEvent()
812 {
813 beginTime_ = InnerEvent::TimePoint::max();
814 }
815
CurrentRunningEvent(InnerEvent::TimePoint time,InnerEvent::Pointer & event)816 CurrentRunningEvent::CurrentRunningEvent(InnerEvent::TimePoint time, InnerEvent::Pointer &event)
817 {
818 beginTime_ = time;
819 owner_ = event->GetOwner();
820 senderKernelThreadId_ = event->GetSenderKernelThreadId();
821 sendTime_ = event->GetSendTime();
822 handleTime_ = event->GetHandleTime();
823 param_ = event->GetParam();
824 if (event->HasTask()) {
825 hasTask_ = true;
826 taskName_ = event->GetTaskName();
827 } else {
828 innerEventId_ = event->GetInnerEventIdEx();
829 }
830 }
831
832 } // namespace AppExecFwk
833 } // namespace OHOS
834