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_runner.h"
17
18 #include <condition_variable>
19 #include <mutex>
20 #include <sstream>
21 #include <thread>
22 #include <unordered_map>
23 #include <vector>
24
25 #include <unistd.h>
26 #include <sys/prctl.h>
27 #include <sys/syscall.h>
28
29 #include "event_handler.h"
30 #include "event_queue_base.h"
31 #include "event_inner_runner.h"
32 #include "event_logger.h"
33 #include "securec.h"
34 #include "singleton.h"
35 #ifdef FFRT_USAGE_ENABLE
36 #include "event_queue_ffrt.h"
37 #include "ffrt_inner.h"
38 #endif // FFRT_USAGE_ENABLE
39
40
41 namespace OHOS {
42 namespace AppExecFwk {
43 namespace {
44 const char *g_crashEmptyDumpInfo = "Current Event Caller is empty. Nothing to dump";
45 const int CRASH_BUF_MIN_LEN = 2;
46 constexpr int64_t MIN_APP_UID = 20000;
47 thread_local static Caller g_currentEventCaller = {};
48 thread_local static std::string g_currentEventName = {};
49
50 DEFINE_EH_HILOG_LABEL("EventRunner");
51
52 // Invoke system call to set name of current thread.
SystemCallSetThreadName(const std::string & name)53 inline void SystemCallSetThreadName(const std::string &name)
54 {
55 if (prctl(PR_SET_NAME, name.c_str()) < 0) {
56 char errmsg[MAX_ERRORMSG_LEN] = {0};
57 GetLastErr(errmsg, MAX_ERRORMSG_LEN);
58 HILOGE("Failed to set thread name, %{public}s", errmsg);
59 }
60 HILOGD("thread name is %{public}s", name.c_str());
61 }
62
63 // Help to calculate hash code of object.
64 template<typename T>
CalculateHashCode(const T & obj)65 inline size_t CalculateHashCode(const T &obj)
66 {
67 std::hash<T> calculateHashCode;
68 return calculateHashCode(obj);
69 }
70
71 // Thread collector is used to reclaim thread that needs to finish running.
72 class ThreadCollector : public DelayedRefSingleton<ThreadCollector> {
73 DECLARE_DELAYED_REF_SINGLETON(ThreadCollector);
74
75 public:
76 DISALLOW_COPY_AND_MOVE(ThreadCollector);
77
78 using ExitFunction = std::function<void()>;
79
ReclaimCurrentThread()80 void ReclaimCurrentThread()
81 {
82 // Get id of current thread.
83 auto threadId = std::this_thread::get_id();
84 HILOGD("Thread id: %{public}zu", CalculateHashCode(threadId));
85
86 {
87 // Add thread id to list and notify to reclaim.
88 std::lock_guard<std::mutex> lock(collectorLock_);
89 if (destroying_) {
90 HILOGI("Thread collector is destroying");
91 return;
92 }
93
94 reclaims_.emplace_back(threadId);
95 if (isWaiting_) {
96 condition_.notify_one();
97 }
98 }
99
100 if (threadLock_.try_lock()) {
101 if ((!thread_) && (needCreateThread_)) {
102 // Start daemon thread to collect finished threads, if not exist.
103 thread_ = std::make_unique<std::thread>(&ThreadCollector::Run, this);
104 }
105 threadLock_.unlock();
106 }
107 }
108
Deposit(std::unique_ptr<std::thread> & thread,const ExitFunction & threadExit)109 bool Deposit(std::unique_ptr<std::thread> &thread, const ExitFunction &threadExit)
110 {
111 if ((!thread) || (!thread->joinable()) || (!threadExit)) {
112 auto threadState = thread ? (thread->joinable() ? "active" : "finished") : "null";
113 HILOGE("%{public}s, %{public}s: Invalid parameter", threadState, threadExit ? "valid" : "null");
114 return false;
115 }
116
117 auto threadId = thread->get_id();
118 HILOGD("New thread id: %{public}zu", CalculateHashCode(threadId));
119 // Save these information into map.
120 std::lock_guard<std::mutex> lock(collectorLock_);
121 if (destroying_) {
122 HILOGW("Collector thread is destroying");
123 return false;
124 }
125 // Save thread object and its exit callback.
126 depositMap_.emplace(threadId,
127 ThreadExitInfo {
128 .thread = std::move(thread),
129 .threadExit = threadExit,
130 });
131 return true;
132 }
133
134 private:
135 DEFINE_EH_HILOG_LABEL("ThreadCollector");
136
137 struct ThreadExitInfo {
138 std::unique_ptr<std::thread> thread;
139 ExitFunction threadExit;
140 };
141
ReclaimAll()142 inline void ReclaimAll()
143 {
144 HILOGD("enter");
145 std::unique_lock<std::mutex> lock(collectorLock_);
146 // All thread deposited need to stop one by one.
147 while (!depositMap_.empty()) {
148 DoReclaimLocked(lock, depositMap_.begin());
149 }
150 }
151
Stop()152 void Stop()
153 {
154 HILOGD("enter");
155 {
156 // Stop the collect thread, while destruction of collector.
157 std::lock_guard<std::mutex> lock(collectorLock_);
158 destroying_ = true;
159 if (isWaiting_) {
160 condition_.notify_all();
161 }
162 }
163
164 {
165 std::lock_guard<std::mutex> lock(threadLock_);
166 if ((thread_) && (thread_->joinable())) {
167 // Wait utils collect thread finished, if exists.
168 thread_->join();
169 }
170 needCreateThread_ = false;
171 }
172
173 ReclaimAll();
174 }
175
DoReclaimLocked(std::unique_lock<std::mutex> & lock,std::unordered_map<std::thread::id,ThreadExitInfo>::iterator it,bool needCallExit=true)176 void DoReclaimLocked(std::unique_lock<std::mutex> &lock,
177 std::unordered_map<std::thread::id, ThreadExitInfo>::iterator it, bool needCallExit = true)
178 {
179 if (it == depositMap_.end()) {
180 return;
181 }
182
183 // Remove thread information from map.
184 auto threadId = it->first;
185 auto exitInfo = std::move(it->second);
186 (void)depositMap_.erase(it);
187
188 // Unlock, because stopping thread maybe spend lot of time, it should be out of the lock.
189 lock.unlock();
190
191 size_t hashThreadId = CalculateHashCode(threadId);
192 HILOGD("Thread id: %{public}zu", hashThreadId);
193 if (needCallExit) {
194 // Call exit callback to stop loop in thread.
195 exitInfo.threadExit();
196 }
197 // Wait until thread finished.
198 exitInfo.thread->join();
199 HILOGD("Done, thread id: %{public}zu", hashThreadId);
200
201 // Lock again.
202 lock.lock();
203 }
204
Run()205 void Run()
206 {
207 HILOGD("Collector thread is started");
208
209 std::unique_lock<std::mutex> lock(collectorLock_);
210 while (!destroying_) {
211 // Reclaim threads in list one by one.
212 while (!reclaims_.empty()) {
213 auto threadId = reclaims_.back();
214 reclaims_.pop_back();
215 DoReclaimLocked(lock, depositMap_.find(threadId), false);
216 }
217
218 // Maybe stop running while doing reclaim, so check before waiting.
219 if (destroying_) {
220 break;
221 }
222
223 isWaiting_ = true;
224 condition_.wait(lock);
225 isWaiting_ = false;
226 }
227
228 HILOGD("Collector thread is stopped");
229 }
230
231 std::mutex collectorLock_;
232 std::condition_variable condition_;
233 bool isWaiting_ {false};
234 bool destroying_ {false};
235 std::vector<std::thread::id> reclaims_;
236 std::unordered_map<std::thread::id, ThreadExitInfo> depositMap_;
237
238 std::mutex threadLock_;
239 // Thread for collector
240 std::unique_ptr<std::thread> thread_;
241 bool needCreateThread_ {true};
242
243 // Avatar of thread collector, used to stop collector at the specified opportunity.
244 class Avatar {
245 public:
246 DISALLOW_COPY_AND_MOVE(Avatar);
247
248 Avatar() = default;
~Avatar()249 ~Avatar()
250 {
251 HILOGD("enter");
252 if (avatarEnabled_) {
253 GetInstance().avatarDestructed_ = true;
254 GetInstance().Stop();
255 }
256 }
257
Disable()258 static inline void Disable()
259 {
260 avatarEnabled_ = false;
261 }
262 };
263
264 // Mark whether avatar is destructed.
265 volatile bool avatarDestructed_ {false};
266 // Mark whether avatar is enabled.
267 static volatile bool avatarEnabled_;
268 static Avatar avatar_;
269 };
270
ThreadCollector()271 ThreadCollector::ThreadCollector()
272 : collectorLock_(), condition_(), reclaims_(), depositMap_(), threadLock_(), thread_(nullptr)
273 {
274 // Thread collector is created, so enable avatar.
275 HILOGD("enter");
276 avatarEnabled_ = true;
277 }
278
~ThreadCollector()279 ThreadCollector::~ThreadCollector()
280 {
281 // If avatar is not destructed, stop collector by itself.
282 HILOGD("enter");
283 if (!avatarDestructed_) {
284 avatar_.Disable();
285 Stop();
286 }
287 }
288
289 typedef void(*ThreadInfoCallback)(char *buf, size_t len, void *ucontext);
290 extern "C" void SetThreadInfoCallback(ThreadInfoCallback func) __attribute__((weak));
291
292 class EventRunnerImpl final : public EventInnerRunner {
293 public:
EventRunnerImpl(const std::shared_ptr<EventRunner> & runner)294 explicit EventRunnerImpl(const std::shared_ptr<EventRunner> &runner) : EventInnerRunner(runner)
295 {
296 HILOGD("enter");
297 queue_ = std::make_shared<EventQueueBase>();
298 }
299
~EventRunnerImpl()300 ~EventRunnerImpl() final
301 {
302 HILOGD("enter");
303 queue_->RemoveAll();
304 }
305 DISALLOW_COPY_AND_MOVE(EventRunnerImpl);
306
ThreadMain(const std::weak_ptr<EventRunnerImpl> & wp)307 static void ThreadMain(const std::weak_ptr<EventRunnerImpl> &wp)
308 {
309 HILOGD("enter");
310 if (SetThreadInfoCallback != nullptr) {
311 SetThreadInfoCallback(CrashCallback);
312 }
313 std::shared_ptr<EventRunnerImpl> inner = wp.lock();
314 if (inner) {
315 HILOGD("Start running for thread '%{public}s'", inner->threadName_.c_str());
316
317 // Call system call to modify thread name.
318 SystemCallSetThreadName(inner->threadName_);
319
320 // Enter event loop.
321 inner->Run();
322
323 HILOGD("Stopped running for thread '%{public}s'", inner->threadName_.c_str());
324 } else {
325 EH_LOGW_LIMIT("EventRunner has been released just after its creation");
326 }
327
328 // Reclaim current thread.
329 ThreadCollector::GetInstance().ReclaimCurrentThread();
330 }
331
Run()332 void Run() final
333 {
334 HILOGD("enter");
335 // Prepare to start event loop.
336 queue_->Prepare();
337
338 // Make sure instance of 'EventRunner' exists.
339 if (owner_.expired()) {
340 return;
341 }
342
343 threadId_ = std::this_thread::get_id();
344 kernelThreadId_ = getproctid();
345
346 // Save old event runner.
347 std::weak_ptr<EventRunner> oldRunner = currentEventRunner;
348 // Set current event runner into thread local data.
349 currentEventRunner = owner_;
350
351 // Start event looper.
352 if (runningMode_ == Mode::NO_WAIT) {
353 NoWaitModeLoop();
354 } else {
355 DefaultModeLoop();
356 }
357
358 // Restore current event runner.
359 currentEventRunner = oldRunner;
360 }
361
Stop()362 void Stop() final
363 {
364 HILOGD("enter");
365 queue_->Finish();
366 }
367
NoWaitModeLoop()368 void NoWaitModeLoop()
369 {
370 // handler event queue
371 InnerEvent::TimePoint nextWakeTime = InnerEvent::TimePoint::max();
372 for (auto event = queue_->GetExpiredEvent(nextWakeTime); event; event =
373 queue_->GetExpiredEvent(nextWakeTime)) {
374 ExecuteEventHandler(event);
375 }
376 // wait for file descriptor
377 queue_->CheckFileDescriptorEvent();
378 // handler file descriptor event
379 for (auto event = queue_->GetExpiredEvent(nextWakeTime); event; event =
380 queue_->GetExpiredEvent(nextWakeTime)) {
381 ExecuteEventHandler(event);
382 }
383 }
384
DefaultModeLoop()385 inline void DefaultModeLoop()
386 {
387 // Default running loop
388 for (auto event = queue_->GetEvent(); event; event = queue_->GetEvent()) {
389 ExecuteEventHandler(event);
390 }
391 }
392
RecordDispatchEventId(InnerEvent::Pointer & event)393 void RecordDispatchEventId(InnerEvent::Pointer &event)
394 {
395 std::shared_ptr<Logger> logging = logger_;
396 if (logging != nullptr) {
397 if (!event->HasTask()) {
398 InnerEvent::EventId eventId = event->GetInnerEventIdEx();
399 if (eventId.index() == TYPE_U32_INDEX) {
400 logging->Log(
401 "Dispatching to handler event id = " + std::to_string(std::get<uint32_t>(eventId)));
402 } else {
403 logging->Log("Dispatching to handler event id = " + std::get<std::string>(eventId));
404 }
405 } else {
406 logging->Log("Dispatching to handler event task name = " + event->GetTaskName());
407 }
408 }
409 }
410
ExecuteEventHandler(InnerEvent::Pointer & event)411 void ExecuteEventHandler(InnerEvent::Pointer &event)
412 {
413 std::shared_ptr<EventHandler> handler = event->GetOwner();
414 // Make sure owner of the event exists.
415 if (handler) {
416 RecordDispatchEventId(event);
417 SetCurrentEventInfo(event);
418 queue_->PushHistoryQueueBeforeDistribute(event);
419 handler->DistributeEvent(event);
420 queue_->PushHistoryQueueAfterDistribute();
421 ClearCurrentEventInfo();
422 #ifdef NOTIFICATIONG_SMART_GC
423 queue_->NotifyObserverVipDone(event);
424 #endif
425 } else {
426 HILOGW("Invalid event handler.");
427 }
428 // Release event manually, otherwise event will be released until next event coming.
429 event.reset();
430 }
431
Attach(std::unique_ptr<std::thread> & thread)432 inline bool Attach(std::unique_ptr<std::thread> &thread)
433 {
434 auto exitThread = [queue = queue_]() { queue->Finish(); };
435
436 return ThreadCollector::GetInstance().Deposit(thread, exitThread);
437 }
438
SetThreadName(const std::string & threadName)439 inline void SetThreadName(const std::string &threadName)
440 {
441 static std::atomic<uint32_t> idGenerator(1);
442
443 if (threadName.empty()) {
444 // Generate a default name
445 threadName_ = "EventRunner#";
446 threadName_ += std::to_string(idGenerator++);
447 } else {
448 threadName_ = threadName;
449 }
450 }
451
SetRunningMode(const Mode runningMode)452 inline void SetRunningMode(const Mode runningMode)
453 {
454 runningMode_ = runningMode;
455 }
456
457 private:
458 DEFINE_EH_HILOG_LABEL("EventRunnerImpl");
459
460 static void CrashCallback(char *buf, size_t len, void *ucontext);
461
SetCurrentEventInfo(const InnerEvent::Pointer & event)462 void SetCurrentEventInfo(const InnerEvent::Pointer &event)
463 {
464 g_currentEventCaller = event->GetCaller();
465 if (event->HasTask()) {
466 g_currentEventName = event->GetTaskName();
467 } else {
468 InnerEvent::EventId eventId = event->GetInnerEventIdEx();
469 if (eventId.index() == TYPE_U32_INDEX) {
470 g_currentEventName = std::to_string(std::get<uint32_t>(eventId));
471 } else {
472 g_currentEventName = std::get<std::string>(eventId);
473 }
474 }
475 }
476
ClearCurrentEventInfo()477 inline void ClearCurrentEventInfo()
478 {
479 g_currentEventCaller = {};
480 g_currentEventName.clear();
481 }
482 };
483 } // unnamed namespace
484
CrashCallback(char * buf,size_t len,void * ucontext)485 void EventRunnerImpl::CrashCallback(char *buf, size_t len, void *ucontext)
486 {
487 if (len < CRASH_BUF_MIN_LEN) {
488 return;
489 }
490 if (memset_s(buf, len, 0x00, len) != EOK) {
491 HILOGE("memset_s failed");
492 return;
493 }
494
495 if (!g_currentEventName.empty()) {
496 const char* file = g_currentEventCaller.file_.c_str();
497 const char* func = g_currentEventCaller.func_.c_str();
498 const char* eventName = g_currentEventName.c_str();
499 int line = g_currentEventCaller.line_;
500 if (snprintf_s(buf, len, len - 1, "Current Event Caller info: [%s(%s:%d)]. EventName is '%s'",
501 file, func, line, eventName) < 0) {
502 HILOGE("snprintf_s failed");
503 return;
504 }
505 return;
506 }
507
508 if (memcpy_s(buf, len - 1, g_crashEmptyDumpInfo, len - 1) != EOK) {
509 HILOGE("memcpy_s failed");
510 return;
511 }
512 }
513
EventInnerRunner(const std::shared_ptr<EventRunner> & runner)514 EventInnerRunner::EventInnerRunner(const std::shared_ptr<EventRunner> &runner)
515 : queue_(nullptr), owner_(runner), logger_(nullptr), threadName_(""), threadId_()
516 {
517 HILOGD("enter");
518 }
519
GetCurrentEventRunner()520 std::shared_ptr<EventRunner> EventInnerRunner::GetCurrentEventRunner()
521 {
522 const std::weak_ptr<EventRunner> &wp = currentEventRunner;
523 return wp.lock();
524 }
525
526 ThreadLocalData<std::weak_ptr<EventRunner>> EventInnerRunner::currentEventRunner;
527
528 namespace {
529 volatile bool ThreadCollector::avatarEnabled_ = false;
530
531 /*
532 * All event runners are relied on 'currentEventRunner', so make sure destruction of 'currentEventRunner'
533 * should after all event runners finished. All event runners finished in destruction of 'ThreadCollector::Avatar',
534 * so instance of 'ThreadCollector::Avatar' MUST defined after 'currentEventRunner'.
535 */
536 ThreadCollector::Avatar ThreadCollector::avatar_;
537 } // unnamed namespace
538
539 std::shared_ptr<EventRunner> EventRunner::mainRunner_;
540 EventRunner::DistributeBeginTime EventRunner::distributeBegin_ = nullptr;
541 EventRunner::DistributeEndTime EventRunner::distributeEnd_ = nullptr;
542 EventRunner::CallbackTime EventRunner::distributeCallback_ = nullptr;
543
Create(bool inNewThread)544 std::shared_ptr<EventRunner> EventRunner::Create(bool inNewThread)
545 {
546 HILOGD("inNewThread is %{public}d", inNewThread);
547 if (inNewThread) {
548 EH_LOGI_LIMIT("EventRunner created");
549 return Create(std::string(), Mode::DEFAULT, ThreadMode::NEW_THREAD);
550 }
551
552 // Constructor of 'EventRunner' is private, could not use 'std::make_shared' to construct it.
553 std::shared_ptr<EventRunner> sp(new (std::nothrow) EventRunner(false, Mode::DEFAULT));
554 if (sp == nullptr) {
555 HILOGI("Failed to create EventRunner Instance");
556 return nullptr;
557 }
558 auto innerRunner = std::make_shared<EventRunnerImpl>(sp);
559 innerRunner->SetRunningMode(Mode::DEFAULT);
560 sp->innerRunner_ = innerRunner;
561 sp->queue_ = innerRunner->GetEventQueue();
562 sp->threadMode_ = ThreadMode::NEW_THREAD;
563 sp->queue_->SetIoWaiter(false);
564 return sp;
565 }
566
Create(bool inNewThread,ThreadMode threadMode)567 std::shared_ptr<EventRunner> EventRunner::Create(bool inNewThread, ThreadMode threadMode)
568 {
569 HILOGD("inNewThread is %{public}d %{public}d", inNewThread, threadMode);
570 if (inNewThread) {
571 EH_LOGI_LIMIT("EventRunner created");
572 return Create(std::string(), Mode::DEFAULT, threadMode);
573 }
574
575 // Constructor of 'EventRunner' is private, could not use 'std::make_shared' to construct it.
576 std::shared_ptr<EventRunner> sp(new (std::nothrow) EventRunner(false, Mode::DEFAULT));
577 if (sp == nullptr) {
578 HILOGI("Failed to create EventRunner Instance");
579 return nullptr;
580 }
581 auto innerRunner = std::make_shared<EventRunnerImpl>(sp);
582 innerRunner->SetRunningMode(Mode::DEFAULT);
583 sp->innerRunner_ = innerRunner;
584 sp->queue_ = innerRunner->GetEventQueue();
585 sp->threadMode_ = ThreadMode::NEW_THREAD;
586 sp->queue_->SetIoWaiter(false);
587 return sp;
588 }
589
Create(const std::string & threadName,Mode mode,ThreadMode threadMode)590 std::shared_ptr<EventRunner> EventRunner::Create(const std::string &threadName, Mode mode, ThreadMode threadMode)
591 {
592 HILOGD("threadName is %{public}s %{public}d %{public}d", threadName.c_str(), mode, threadMode);
593 // Constructor of 'EventRunner' is private, could not use 'std::make_shared' to construct it.
594 std::shared_ptr<EventRunner> sp(new EventRunner(true, mode));
595 auto innerRunner = std::make_shared<EventRunnerImpl>(sp);
596 innerRunner->SetRunningMode(mode);
597 sp->innerRunner_ = innerRunner;
598 innerRunner->SetThreadName(threadName);
599
600 #ifdef FFRT_USAGE_ENABLE
601 if (threadMode == ThreadMode::FFRT && mode == Mode::DEFAULT) {
602 sp->threadMode_ = ThreadMode::FFRT;
603 sp->queue_ = std::make_shared<EventQueueFFRT>();
604 sp->queue_->SetIoWaiter(true);
605 } else {
606 sp->threadMode_ = ThreadMode::NEW_THREAD;
607 sp->queue_ = innerRunner->GetEventQueue();
608 sp->queue_->SetIoWaiter(false);
609 }
610 if (threadMode == ThreadMode::FFRT || mode == Mode::NO_WAIT) {
611 return sp;
612 }
613 #else
614 sp->threadMode_ = ThreadMode::NEW_THREAD;
615 sp->queue_ = innerRunner->GetEventQueue();
616 sp->queue_->SetIoWaiter(false);
617 if (mode == Mode::NO_WAIT) {
618 return sp;
619 }
620 #endif
621
622 // Start new thread
623 auto thread =
624 std::make_unique<std::thread>(EventRunnerImpl::ThreadMain, std::weak_ptr<EventRunnerImpl>(innerRunner));
625 if (!innerRunner->Attach(thread)) {
626 HILOGW("Failed to attach thread, maybe process is exiting");
627 innerRunner->Stop();
628 thread->join();
629 }
630
631 return sp;
632 }
633
Current()634 std::shared_ptr<EventRunner> EventRunner::Current()
635 {
636 #ifdef FFRT_USAGE_ENABLE
637 if (ffrt_this_task_get_id()) {
638 auto handler = ffrt_get_current_queue_eventhandler();
639 if (handler == nullptr) {
640 HILOGW("Current handler is null.");
641 return nullptr;
642 }
643 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
644 return sharedHandler->GetEventRunner();
645 } else {
646 auto runner = EventInnerRunner::GetCurrentEventRunner();
647 if (runner) {
648 return runner;
649 }
650 return nullptr;
651 }
652 #else
653 auto runner = EventInnerRunner::GetCurrentEventRunner();
654 if (runner) {
655 return runner;
656 }
657 return nullptr;
658 #endif
659 }
660
EventRunner(bool deposit,Mode runningMode)661 EventRunner::EventRunner(bool deposit, Mode runningMode) : deposit_(deposit), runningMode_(runningMode)
662 {
663 runnerId_ = std::to_string(GetTimeStamp());
664 HILOGD("deposit_ is %{public}d %{public}d", deposit_, runningMode_);
665 }
666
GetRunnerThreadName() const667 std::string EventRunner::GetRunnerThreadName() const
668 {
669 return innerRunner_->GetThreadName();
670 }
671
~EventRunner()672 EventRunner::~EventRunner()
673 {
674 HILOGI("~EventRunner deposit_ is %{public}d %{public}s", deposit_, runnerId_.c_str());
675 if (deposit_ && innerRunner_ != nullptr) {
676 innerRunner_->Stop();
677 }
678 }
679
StartRunningForNoWait()680 void EventRunner::StartRunningForNoWait()
681 {
682 auto innerRunner = std::static_pointer_cast<EventRunnerImpl>(innerRunner_);
683 auto thread =
684 std::make_unique<std::thread>(EventRunnerImpl::ThreadMain, std::weak_ptr<EventRunnerImpl>(innerRunner));
685 if (!innerRunner->Attach(thread)) {
686 HILOGW("Failed to attach thread for no wait, maybe process is exiting");
687 innerRunner->Stop();
688 thread->join();
689 }
690 }
691
Run()692 ErrCode EventRunner::Run()
693 {
694 HILOGD("enter");
695 if (deposit_ && runningMode_ == Mode::DEFAULT) {
696 HILOGE("Do not call, if event runner is deposited");
697 return EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
698 }
699
700 // Avoid more than one thread to start this runner.
701 if (running_.exchange(true)) {
702 HILOGW("Already running");
703 return EVENT_HANDLER_ERR_RUNNER_ALREADY;
704 }
705
706 runnerId_ += "_" + std::to_string(getproctid());
707 if (deposit_ && runningMode_ == Mode::NO_WAIT) {
708 // Start new thread for NO_WAIT Mode
709 StartRunningForNoWait();
710 } else {
711 // Entry event loop.
712 innerRunner_->Run();
713 }
714
715 running_.store(false);
716 return ERR_OK;
717 }
718
Stop()719 ErrCode EventRunner::Stop()
720 {
721 HILOGD("enter");
722 if (deposit_) {
723 EH_LOGE_LIMIT("Stop: Do not call, if event runner is deposited");
724 return EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
725 }
726
727 if (running_.load()) {
728 innerRunner_->Stop();
729 } else {
730 HILOGW("Stop: Already stopped");
731 }
732
733 return ERR_OK;
734 }
735
Dump(Dumper & dumper)736 void EventRunner::Dump(Dumper &dumper)
737 {
738 if (!IsRunning()) {
739 dumper.Dump(dumper.GetTag() + " Event runner is not running" + LINE_SEPARATOR);
740 return;
741 }
742
743 if (queue_ == nullptr) {
744 dumper.Dump(dumper.GetTag() + " Queue is nullLINE_SEPARATOR" + LINE_SEPARATOR);
745 return;
746 }
747
748 dumper.Dump(dumper.GetTag() + " Event runner (" + "Thread name = " + innerRunner_->GetThreadName() +
749 ", Thread ID = " + std::to_string(GetKernelThreadId()) + ") is running" + LINE_SEPARATOR);
750 queue_->Dump(dumper);
751 }
752
DumpRunnerInfo(std::string & runnerInfo)753 void EventRunner::DumpRunnerInfo(std::string& runnerInfo)
754 {
755 if (!IsRunning()) {
756 runnerInfo = " Event runner is not running" + LINE_SEPARATOR;
757 }
758
759 if (queue_ == nullptr) {
760 runnerInfo = " Queue is null" + LINE_SEPARATOR;
761 return;
762 }
763
764 std::string queueInfo;
765 queue_->DumpQueueInfo(queueInfo);
766 runnerInfo += queueInfo;
767 }
768
SetLogger(const std::shared_ptr<Logger> & logger)769 void EventRunner::SetLogger(const std::shared_ptr<Logger> &logger)
770 {
771 innerRunner_->SetLogger(logger);
772 }
773
GetCurrentEventQueue()774 std::shared_ptr<EventQueue> EventRunner::GetCurrentEventQueue()
775 {
776 #ifdef FFRT_USAGE_ENABLE
777 if (ffrt_this_task_get_id()) {
778 auto handler = ffrt_get_current_queue_eventhandler();
779 if (handler == nullptr) {
780 HILOGW("Current handler is null.");
781 return nullptr;
782 }
783 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
784 return sharedHandler->GetEventRunner()->GetEventQueue();
785 } else {
786 auto runner = EventRunner::Current();
787 if (!runner) {
788 HILOGE("current runner is nullptr");
789 return nullptr;
790 }
791 return runner->queue_;
792 }
793 #else
794 auto runner = EventRunner::Current();
795 if (!runner) {
796 HILOGE("current runner is nullptr");
797 return nullptr;
798 }
799 return runner->queue_;
800 #endif
801 }
802
GetThreadId()803 uint64_t EventRunner::GetThreadId()
804 {
805 std::thread::id tid = innerRunner_->GetThreadId();
806 std::stringstream buf;
807 buf << tid;
808 std::string stid = buf.str();
809 return std::stoull(stid);
810 }
811
GetKernelThreadId()812 uint64_t EventRunner::GetKernelThreadId()
813 {
814 return innerRunner_->GetKernelThreadId();
815 }
816
IsCurrentRunnerThread()817 bool EventRunner::IsCurrentRunnerThread()
818 {
819 #ifdef FFRT_USAGE_ENABLE
820 if (ffrt_this_task_get_id()) {
821 auto handler = ffrt_get_current_queue_eventhandler();
822 if (handler == nullptr) {
823 HILOGW("Current handler is null.");
824 return false;
825 }
826 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
827 return queue_ == sharedHandler->GetEventRunner()->GetEventQueue();
828 } else {
829 return std::this_thread::get_id() == innerRunner_->GetThreadId();
830 }
831 #else
832 return std::this_thread::get_id() == innerRunner_->GetThreadId();
833 #endif
834 }
835
GetMainEventRunner()836 std::shared_ptr<EventRunner> EventRunner::GetMainEventRunner()
837 {
838 if (!mainRunner_) {
839 mainRunner_ = Create(false);
840 if (!mainRunner_) {
841 HILOGE("mainRunner_ create fail");
842 }
843 }
844
845 return mainRunner_;
846 }
847
IsAppMainThread()848 bool EventRunner::IsAppMainThread()
849 {
850 static int pid = -1;
851 static int uid = -1;
852
853 if (pid == -1) {
854 pid = getpid();
855 }
856 if (uid == -1) {
857 uid = getuid();
858 }
859 if (pid == gettid() && uid >= MIN_APP_UID) {
860 return true;
861 }
862 return false;
863 }
864
SetMainLooperWatcher(const DistributeBeginTime begin,const DistributeEndTime end)865 void EventRunner::SetMainLooperWatcher(const DistributeBeginTime begin,
866 const DistributeEndTime end)
867 {
868 if ((begin != nullptr && end != nullptr) || (begin == nullptr && end == nullptr)) {
869 distributeBegin_ = begin;
870 distributeEnd_ = end;
871 } else {
872 HILOGE("SetMainLooperWatcher Error, invaild parameter");
873 }
874 }
875 } // namespace AppExecFwk
876 } // namespace OHOS
877