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 } else {
423 HILOGW("Invalid event handler.");
424 }
425 // Release event manually, otherwise event will be released until next event coming.
426 event.reset();
427 }
428
Attach(std::unique_ptr<std::thread> & thread)429 inline bool Attach(std::unique_ptr<std::thread> &thread)
430 {
431 auto exitThread = [queue = queue_]() { queue->Finish(); };
432
433 return ThreadCollector::GetInstance().Deposit(thread, exitThread);
434 }
435
SetThreadName(const std::string & threadName)436 inline void SetThreadName(const std::string &threadName)
437 {
438 static std::atomic<uint32_t> idGenerator(1);
439
440 if (threadName.empty()) {
441 // Generate a default name
442 threadName_ = "EventRunner#";
443 threadName_ += std::to_string(idGenerator++);
444 } else {
445 threadName_ = threadName;
446 }
447 }
448
SetRunningMode(const Mode runningMode)449 inline void SetRunningMode(const Mode runningMode)
450 {
451 runningMode_ = runningMode;
452 }
453
454 private:
455 DEFINE_EH_HILOG_LABEL("EventRunnerImpl");
456
457 static void CrashCallback(char *buf, size_t len, void *ucontext);
458
SetCurrentEventInfo(const InnerEvent::Pointer & event)459 void SetCurrentEventInfo(const InnerEvent::Pointer &event)
460 {
461 g_currentEventCaller = event->GetCaller();
462 if (event->HasTask()) {
463 g_currentEventName = event->GetTaskName();
464 } else {
465 InnerEvent::EventId eventId = event->GetInnerEventIdEx();
466 if (eventId.index() == TYPE_U32_INDEX) {
467 g_currentEventName = std::to_string(std::get<uint32_t>(eventId));
468 } else {
469 g_currentEventName = std::get<std::string>(eventId);
470 }
471 }
472 }
473
ClearCurrentEventInfo()474 inline void ClearCurrentEventInfo()
475 {
476 g_currentEventCaller = {};
477 g_currentEventName.clear();
478 }
479 };
480 } // unnamed namespace
481
CrashCallback(char * buf,size_t len,void * ucontext)482 void EventRunnerImpl::CrashCallback(char *buf, size_t len, void *ucontext)
483 {
484 if (len < CRASH_BUF_MIN_LEN) {
485 return;
486 }
487 if (memset_s(buf, len, 0x00, len) != EOK) {
488 HILOGE("memset_s failed");
489 return;
490 }
491
492 if (!g_currentEventName.empty()) {
493 const char* file = g_currentEventCaller.file_.c_str();
494 const char* func = g_currentEventCaller.func_.c_str();
495 const char* eventName = g_currentEventName.c_str();
496 int line = g_currentEventCaller.line_;
497 if (snprintf_s(buf, len, len - 1, "Current Event Caller info: [%s(%s:%d)]. EventName is '%s'",
498 file, func, line, eventName) < 0) {
499 HILOGE("snprintf_s failed");
500 return;
501 }
502 return;
503 }
504
505 if (memcpy_s(buf, len - 1, g_crashEmptyDumpInfo, len - 1) != EOK) {
506 HILOGE("memcpy_s failed");
507 return;
508 }
509 }
510
EventInnerRunner(const std::shared_ptr<EventRunner> & runner)511 EventInnerRunner::EventInnerRunner(const std::shared_ptr<EventRunner> &runner)
512 : queue_(nullptr), owner_(runner), logger_(nullptr), threadName_(""), threadId_()
513 {
514 HILOGD("enter");
515 }
516
GetCurrentEventRunner()517 std::shared_ptr<EventRunner> EventInnerRunner::GetCurrentEventRunner()
518 {
519 const std::weak_ptr<EventRunner> &wp = currentEventRunner;
520 return wp.lock();
521 }
522
523 ThreadLocalData<std::weak_ptr<EventRunner>> EventInnerRunner::currentEventRunner;
524
525 namespace {
526 volatile bool ThreadCollector::avatarEnabled_ = false;
527
528 /*
529 * All event runners are relied on 'currentEventRunner', so make sure destruction of 'currentEventRunner'
530 * should after all event runners finished. All event runners finished in destruction of 'ThreadCollector::Avatar',
531 * so instance of 'ThreadCollector::Avatar' MUST defined after 'currentEventRunner'.
532 */
533 ThreadCollector::Avatar ThreadCollector::avatar_;
534 } // unnamed namespace
535
536 std::shared_ptr<EventRunner> EventRunner::mainRunner_;
537 EventRunner::DistributeBeginTime EventRunner::distributeBegin_ = nullptr;
538 EventRunner::DistributeEndTime EventRunner::distributeEnd_ = nullptr;
539 EventRunner::CallbackTime EventRunner::distributeCallback_ = nullptr;
540
Create(bool inNewThread,Mode mode)541 std::shared_ptr<EventRunner> EventRunner::Create(bool inNewThread, Mode mode)
542 {
543 HILOGD("inNewThread is %{public}d", inNewThread);
544 if (inNewThread) {
545 EH_LOGI_LIMIT("EventRunner created");
546 return Create(std::string(), mode, ThreadMode::NEW_THREAD);
547 }
548
549 // Constructor of 'EventRunner' is private, could not use 'std::make_shared' to construct it.
550 std::shared_ptr<EventRunner> sp(new (std::nothrow) EventRunner(false, mode));
551 if (sp == nullptr) {
552 HILOGI("Failed to create EventRunner Instance");
553 return nullptr;
554 }
555 auto innerRunner = std::make_shared<EventRunnerImpl>(sp);
556 innerRunner->SetRunningMode(mode);
557 sp->innerRunner_ = innerRunner;
558 sp->queue_ = innerRunner->GetEventQueue();
559 sp->threadMode_ = ThreadMode::NEW_THREAD;
560 sp->queue_->SetIoWaiter(false);
561 return sp;
562 }
563
Create(bool inNewThread,ThreadMode threadMode)564 std::shared_ptr<EventRunner> EventRunner::Create(bool inNewThread, ThreadMode threadMode)
565 {
566 HILOGD("inNewThread is %{public}d %{public}d", inNewThread, threadMode);
567 if (inNewThread) {
568 EH_LOGI_LIMIT("EventRunner created");
569 return Create(std::string(), Mode::DEFAULT, threadMode);
570 }
571
572 // Constructor of 'EventRunner' is private, could not use 'std::make_shared' to construct it.
573 std::shared_ptr<EventRunner> sp(new (std::nothrow) EventRunner(false, Mode::DEFAULT));
574 if (sp == nullptr) {
575 HILOGI("Failed to create EventRunner Instance");
576 return nullptr;
577 }
578 auto innerRunner = std::make_shared<EventRunnerImpl>(sp);
579 innerRunner->SetRunningMode(Mode::DEFAULT);
580 sp->innerRunner_ = innerRunner;
581 sp->queue_ = innerRunner->GetEventQueue();
582 sp->threadMode_ = ThreadMode::NEW_THREAD;
583 sp->queue_->SetIoWaiter(false);
584 return sp;
585 }
586
Create(const std::string & threadName,Mode mode,ThreadMode threadMode)587 std::shared_ptr<EventRunner> EventRunner::Create(const std::string &threadName, Mode mode, ThreadMode threadMode)
588 {
589 HILOGD("threadName is %{public}s %{public}d %{public}d", threadName.c_str(), mode, threadMode);
590 // Constructor of 'EventRunner' is private, could not use 'std::make_shared' to construct it.
591 std::shared_ptr<EventRunner> sp(new EventRunner(true, mode));
592 auto innerRunner = std::make_shared<EventRunnerImpl>(sp);
593 innerRunner->SetRunningMode(mode);
594 sp->innerRunner_ = innerRunner;
595 innerRunner->SetThreadName(threadName);
596
597 #ifdef FFRT_USAGE_ENABLE
598 if (threadMode == ThreadMode::FFRT && mode == Mode::DEFAULT) {
599 sp->threadMode_ = ThreadMode::FFRT;
600 sp->queue_ = std::make_shared<EventQueueFFRT>();
601 sp->queue_->SetIoWaiter(true);
602 } else {
603 sp->threadMode_ = ThreadMode::NEW_THREAD;
604 sp->queue_ = innerRunner->GetEventQueue();
605 sp->queue_->SetIoWaiter(false);
606 }
607 if (threadMode == ThreadMode::FFRT || mode == Mode::NO_WAIT) {
608 return sp;
609 }
610 #else
611 sp->threadMode_ = ThreadMode::NEW_THREAD;
612 sp->queue_ = innerRunner->GetEventQueue();
613 sp->queue_->SetIoWaiter(false);
614 if (mode == Mode::NO_WAIT) {
615 return sp;
616 }
617 #endif
618
619 // Start new thread
620 auto thread =
621 std::make_unique<std::thread>(EventRunnerImpl::ThreadMain, std::weak_ptr<EventRunnerImpl>(innerRunner));
622 if (!innerRunner->Attach(thread)) {
623 HILOGW("Failed to attach thread, maybe process is exiting");
624 innerRunner->Stop();
625 thread->join();
626 }
627
628 return sp;
629 }
630
Current()631 std::shared_ptr<EventRunner> EventRunner::Current()
632 {
633 #ifdef FFRT_USAGE_ENABLE
634 if (ffrt_this_task_get_id()) {
635 auto handler = ffrt_get_current_queue_eventhandler();
636 if (handler == nullptr) {
637 HILOGW("Current handler is null.");
638 return nullptr;
639 }
640 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
641 return sharedHandler->GetEventRunner();
642 } else {
643 auto runner = EventInnerRunner::GetCurrentEventRunner();
644 if (runner) {
645 return runner;
646 }
647 return nullptr;
648 }
649 #else
650 auto runner = EventInnerRunner::GetCurrentEventRunner();
651 if (runner) {
652 return runner;
653 }
654 return nullptr;
655 #endif
656 }
657
EventRunner(bool deposit,Mode runningMode)658 EventRunner::EventRunner(bool deposit, Mode runningMode) : deposit_(deposit), runningMode_(runningMode)
659 {
660 runnerId_ = std::to_string(GetTimeStamp());
661 HILOGD("deposit_ is %{public}d %{public}d", deposit_, runningMode_);
662 }
663
GetRunnerThreadName() const664 std::string EventRunner::GetRunnerThreadName() const
665 {
666 return innerRunner_->GetThreadName();
667 }
668
~EventRunner()669 EventRunner::~EventRunner()
670 {
671 EH_LOGI_LIMIT("~EventRunner deposit_ is %{public}d %{public}s", deposit_, runnerId_.c_str());
672 if (deposit_ && innerRunner_ != nullptr) {
673 innerRunner_->Stop();
674 }
675 }
676
StartRunningForNoWait()677 void EventRunner::StartRunningForNoWait()
678 {
679 auto innerRunner = std::static_pointer_cast<EventRunnerImpl>(innerRunner_);
680 auto thread =
681 std::make_unique<std::thread>(EventRunnerImpl::ThreadMain, std::weak_ptr<EventRunnerImpl>(innerRunner));
682 if (!innerRunner->Attach(thread)) {
683 HILOGW("Failed to attach thread for no wait, maybe process is exiting");
684 innerRunner->Stop();
685 thread->join();
686 }
687 }
688
Run()689 ErrCode EventRunner::Run()
690 {
691 HILOGD("enter");
692 if (deposit_ && runningMode_ == Mode::DEFAULT) {
693 HILOGE("Do not call, if event runner is deposited");
694 return EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
695 }
696
697 // Avoid more than one thread to start this runner.
698 if (running_.exchange(true)) {
699 HILOGW("Already running");
700 return EVENT_HANDLER_ERR_RUNNER_ALREADY;
701 }
702
703 runnerId_ += "_" + std::to_string(getproctid());
704 if (deposit_ && runningMode_ == Mode::NO_WAIT) {
705 // Start new thread for NO_WAIT Mode
706 StartRunningForNoWait();
707 } else {
708 // Entry event loop.
709 innerRunner_->Run();
710 }
711
712 running_.store(false);
713 return ERR_OK;
714 }
715
Stop()716 ErrCode EventRunner::Stop()
717 {
718 HILOGD("enter");
719 if (deposit_) {
720 EH_LOGE_LIMIT("Stop: Do not call, if event runner is deposited");
721 return EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
722 }
723
724 if (running_.load()) {
725 innerRunner_->Stop();
726 } else {
727 HILOGW("Stop: Already stopped");
728 }
729
730 return ERR_OK;
731 }
732
Dump(Dumper & dumper)733 void EventRunner::Dump(Dumper &dumper)
734 {
735 if (!IsRunning()) {
736 dumper.Dump(dumper.GetTag() + " Event runner is not running" + std::string(LINE_SEPARATOR));
737 return;
738 }
739
740 if (queue_ == nullptr) {
741 dumper.Dump(dumper.GetTag() + " Queue is nullLINE_SEPARATOR" + std::string(LINE_SEPARATOR));
742 return;
743 }
744
745 dumper.Dump(dumper.GetTag() + " Event runner (" + "Thread name = " + innerRunner_->GetThreadName() +
746 ", Thread ID = " + std::to_string(GetKernelThreadId()) + ") is running" + std::string(LINE_SEPARATOR));
747 queue_->Dump(dumper);
748 }
749
DumpRunnerInfo(std::string & runnerInfo)750 void EventRunner::DumpRunnerInfo(std::string& runnerInfo)
751 {
752 if (!IsRunning()) {
753 runnerInfo = " Event runner is not running" + std::string(LINE_SEPARATOR);
754 }
755
756 if (queue_ == nullptr) {
757 runnerInfo = " Queue is null" + std::string(LINE_SEPARATOR);
758 return;
759 }
760
761 std::string queueInfo;
762 queue_->DumpQueueInfo(queueInfo);
763 runnerInfo += queueInfo;
764 }
765
SetLogger(const std::shared_ptr<Logger> & logger)766 void EventRunner::SetLogger(const std::shared_ptr<Logger> &logger)
767 {
768 innerRunner_->SetLogger(logger);
769 }
770
GetCurrentEventQueue()771 std::shared_ptr<EventQueue> EventRunner::GetCurrentEventQueue()
772 {
773 #ifdef FFRT_USAGE_ENABLE
774 if (ffrt_this_task_get_id()) {
775 auto handler = ffrt_get_current_queue_eventhandler();
776 if (handler == nullptr) {
777 HILOGW("Current handler is null.");
778 return nullptr;
779 }
780 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
781 return sharedHandler->GetEventRunner()->GetEventQueue();
782 } else {
783 auto runner = EventRunner::Current();
784 if (!runner) {
785 HILOGE("current runner is nullptr");
786 return nullptr;
787 }
788 return runner->queue_;
789 }
790 #else
791 auto runner = EventRunner::Current();
792 if (!runner) {
793 HILOGE("current runner is nullptr");
794 return nullptr;
795 }
796 return runner->queue_;
797 #endif
798 }
799
GetThreadId()800 uint64_t EventRunner::GetThreadId()
801 {
802 std::thread::id tid = innerRunner_->GetThreadId();
803 std::stringstream buf;
804 buf << tid;
805 std::string stid = buf.str();
806 return std::stoull(stid);
807 }
808
GetKernelThreadId()809 uint64_t EventRunner::GetKernelThreadId()
810 {
811 return innerRunner_->GetKernelThreadId();
812 }
813
IsCurrentRunnerThread()814 bool EventRunner::IsCurrentRunnerThread()
815 {
816 #ifdef FFRT_USAGE_ENABLE
817 if (ffrt_this_task_get_id()) {
818 auto handler = ffrt_get_current_queue_eventhandler();
819 if (handler == nullptr) {
820 HILOGW("Current handler is null.");
821 return false;
822 }
823 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
824 return queue_ == sharedHandler->GetEventRunner()->GetEventQueue();
825 } else {
826 return std::this_thread::get_id() == innerRunner_->GetThreadId();
827 }
828 #else
829 return std::this_thread::get_id() == innerRunner_->GetThreadId();
830 #endif
831 }
832
GetMainEventRunner()833 std::shared_ptr<EventRunner> EventRunner::GetMainEventRunner()
834 {
835 if (!mainRunner_) {
836 mainRunner_ = Create(false);
837 if (!mainRunner_) {
838 HILOGE("mainRunner_ create fail");
839 }
840 }
841
842 return mainRunner_;
843 }
844
IsAppMainThread()845 bool EventRunner::IsAppMainThread()
846 {
847 static int pid = -1;
848 static int uid = -1;
849
850 if (pid == -1) {
851 pid = getpid();
852 }
853 if (uid == -1) {
854 uid = getuid();
855 }
856 if (pid == gettid() && uid >= MIN_APP_UID) {
857 return true;
858 }
859 return false;
860 }
861
SetMainLooperWatcher(const DistributeBeginTime begin,const DistributeEndTime end)862 void EventRunner::SetMainLooperWatcher(const DistributeBeginTime begin,
863 const DistributeEndTime end)
864 {
865 if ((begin != nullptr && end != nullptr) || (begin == nullptr && end == nullptr)) {
866 distributeBegin_ = begin;
867 distributeEnd_ = end;
868 } else {
869 HILOGE("SetMainLooperWatcher Error, invaild parameter");
870 }
871 }
872 } // namespace AppExecFwk
873 } // namespace OHOS
874