• 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_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