• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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