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