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 HILOGD("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 HILOGD("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 HILOGW("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 return nullptr;
641 }
642 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
643 return sharedHandler->GetEventRunner();
644 } else {
645 auto runner = EventInnerRunner::GetCurrentEventRunner();
646 if (runner) {
647 return runner;
648 }
649 return nullptr;
650 }
651 #else
652 auto runner = EventInnerRunner::GetCurrentEventRunner();
653 if (runner) {
654 return runner;
655 }
656 return nullptr;
657 #endif
658 }
659
EventRunner(bool deposit,Mode runningMode)660 EventRunner::EventRunner(bool deposit, Mode runningMode) : deposit_(deposit), runningMode_(runningMode)
661 {
662 runnerId_ = std::to_string(GetTimeStamp());
663 HILOGD("deposit_ is %{public}d %{public}d", deposit_, runningMode_);
664 }
665
GetRunnerThreadName() const666 std::string EventRunner::GetRunnerThreadName() const
667 {
668 return innerRunner_->GetThreadName();
669 }
670
~EventRunner()671 EventRunner::~EventRunner()
672 {
673 HILOGI("~EventRunner deposit_ is %{public}d %{public}s", deposit_, runnerId_.c_str());
674 if (deposit_ && innerRunner_ != nullptr) {
675 innerRunner_->Stop();
676 }
677 }
678
StartRunningForNoWait()679 void EventRunner::StartRunningForNoWait()
680 {
681 auto innerRunner = std::static_pointer_cast<EventRunnerImpl>(innerRunner_);
682 auto thread =
683 std::make_unique<std::thread>(EventRunnerImpl::ThreadMain, std::weak_ptr<EventRunnerImpl>(innerRunner));
684 if (!innerRunner->Attach(thread)) {
685 HILOGW("Failed to attach thread for no wait, maybe process is exiting");
686 innerRunner->Stop();
687 thread->join();
688 }
689 }
690
Run()691 ErrCode EventRunner::Run()
692 {
693 HILOGD("enter");
694 if (deposit_ && runningMode_ == Mode::DEFAULT) {
695 HILOGD("Do not call, if event runner is deposited");
696 return EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
697 }
698
699 // Avoid more than one thread to start this runner.
700 if (running_.exchange(true)) {
701 HILOGD("Already running");
702 return EVENT_HANDLER_ERR_RUNNER_ALREADY;
703 }
704
705 runnerId_ += "_" + std::to_string(getproctid());
706 if (deposit_ && runningMode_ == Mode::NO_WAIT) {
707 // Start new thread for NO_WAIT Mode
708 StartRunningForNoWait();
709 } else {
710 // Entry event loop.
711 innerRunner_->Run();
712 }
713
714 running_.store(false);
715 return ERR_OK;
716 }
717
Stop()718 ErrCode EventRunner::Stop()
719 {
720 HILOGD("enter");
721 if (deposit_) {
722 HILOGD("Stop: Do not call, if event runner is deposited");
723 return EVENT_HANDLER_ERR_RUNNER_NO_PERMIT;
724 }
725
726 if (running_.load()) {
727 innerRunner_->Stop();
728 } else {
729 HILOGD("Stop: Already stopped");
730 }
731
732 return ERR_OK;
733 }
734
Dump(Dumper & dumper)735 void EventRunner::Dump(Dumper &dumper)
736 {
737 if (!IsRunning()) {
738 dumper.Dump(dumper.GetTag() + " Event runner is not running" + LINE_SEPARATOR);
739 return;
740 }
741
742 if (queue_ == nullptr) {
743 dumper.Dump(dumper.GetTag() + " Queue is nullLINE_SEPARATOR" + LINE_SEPARATOR);
744 return;
745 }
746
747 dumper.Dump(dumper.GetTag() + " Event runner (" + "Thread name = " + innerRunner_->GetThreadName() +
748 ", Thread ID = " + std::to_string(GetKernelThreadId()) + ") is running" + LINE_SEPARATOR);
749 queue_->Dump(dumper);
750 }
751
DumpRunnerInfo(std::string & runnerInfo)752 void EventRunner::DumpRunnerInfo(std::string& runnerInfo)
753 {
754 if (!IsRunning()) {
755 runnerInfo = " Event runner is not running" + LINE_SEPARATOR;
756 }
757
758 if (queue_ == nullptr) {
759 runnerInfo = " Queue is null" + LINE_SEPARATOR;
760 return;
761 }
762
763 std::string queueInfo;
764 queue_->DumpQueueInfo(queueInfo);
765 runnerInfo += queueInfo;
766 }
767
SetLogger(const std::shared_ptr<Logger> & logger)768 void EventRunner::SetLogger(const std::shared_ptr<Logger> &logger)
769 {
770 innerRunner_->SetLogger(logger);
771 }
772
GetCurrentEventQueue()773 std::shared_ptr<EventQueue> EventRunner::GetCurrentEventQueue()
774 {
775 #ifdef FFRT_USAGE_ENABLE
776 if (ffrt_this_task_get_id()) {
777 auto handler = ffrt_get_current_queue_eventhandler();
778 if (handler == nullptr) {
779 return nullptr;
780 }
781 auto sharedHandler = *(reinterpret_cast<std::shared_ptr<EventHandler>*>(handler));
782 return sharedHandler->GetEventRunner()->GetEventQueue();
783 } else {
784 auto runner = EventRunner::Current();
785 if (!runner) {
786 HILOGE("current runner is nullptr");
787 return nullptr;
788 }
789 return runner->queue_;
790 }
791 #else
792 auto runner = EventRunner::Current();
793 if (!runner) {
794 HILOGE("current runner is nullptr");
795 return nullptr;
796 }
797 return runner->queue_;
798 #endif
799 }
800
GetThreadId()801 uint64_t EventRunner::GetThreadId()
802 {
803 std::thread::id tid = innerRunner_->GetThreadId();
804 std::stringstream buf;
805 buf << tid;
806 std::string stid = buf.str();
807 return std::stoull(stid);
808 }
809
GetKernelThreadId()810 uint64_t EventRunner::GetKernelThreadId()
811 {
812 return innerRunner_->GetKernelThreadId();
813 }
814
IsCurrentRunnerThread()815 bool EventRunner::IsCurrentRunnerThread()
816 {
817 #ifdef FFRT_USAGE_ENABLE
818 if (ffrt_this_task_get_id()) {
819 auto handler = ffrt_get_current_queue_eventhandler();
820 if (handler == nullptr) {
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