1 /*
2 * Copyright (c) 2021 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 "ecmascript/taskpool/runner.h"
17
18 #ifdef ENABLE_QOS
19 #include "qos.h"
20 #endif
21
22 namespace panda::ecmascript {
Runner(uint32_t threadNum,const std::function<void (os::thread::native_handle_type)> prologueHook,const std::function<void (os::thread::native_handle_type)> epilogueHook)23 Runner::Runner(uint32_t threadNum, const std::function<void(os::thread::native_handle_type)> prologueHook,
24 const std::function<void(os::thread::native_handle_type)> epilogueHook)
25 : totalThreadNum_(threadNum),
26 prologueHook_(prologueHook),
27 epilogueHook_(epilogueHook)
28 {
29 for (uint32_t i = 0; i < threadNum; i++) {
30 // main thread is 0;
31 std::unique_ptr<std::thread> thread = std::make_unique<std::thread>([this, i] {this->Run(i + 1);});
32 threadPool_.emplace_back(std::move(thread));
33 }
34
35 for (uint32_t i = 0; i < runningTask_.size(); i++) {
36 runningTask_[i] = nullptr;
37 }
38 }
39
TerminateTask(int32_t id,TaskType type)40 void Runner::TerminateTask(int32_t id, TaskType type)
41 {
42 taskQueue_.TerminateTask(id, type);
43 LockHolder holder(mtx_);
44 for (uint32_t i = 0; i < runningTask_.size(); i++) {
45 if (runningTask_[i] != nullptr) {
46 if (id != ALL_TASK_ID && id != runningTask_[i]->GetId()) {
47 continue;
48 }
49 if (type != TaskType::ALL && type != runningTask_[i]->GetTaskType()) {
50 continue;
51 }
52 runningTask_[i]->Terminated();
53 }
54 }
55 }
56
TerminateThread()57 void Runner::TerminateThread()
58 {
59 TerminateTask(ALL_TASK_ID, TaskType::ALL);
60 taskQueue_.Terminate();
61
62 LockHolder holder(mtxPool_);
63 uint32_t threadNum = threadPool_.size();
64 for (uint32_t i = 0; i < threadNum; i++) {
65 threadPool_.at(i)->join();
66 }
67 threadPool_.clear();
68 }
69
ForEachTask(const std::function<void (Task *)> & f)70 void Runner::ForEachTask(const std::function<void(Task*)> &f)
71 {
72 taskQueue_.ForEachTask(f);
73 LockHolder holder(mtx_);
74 for (uint32_t i = 0; i < runningTask_.size(); i++) {
75 if (runningTask_[i] != nullptr) {
76 f(runningTask_[i]);
77 }
78 }
79 }
80
SetQosPriority(PriorityMode mode)81 void Runner::SetQosPriority([[maybe_unused]] PriorityMode mode)
82 {
83 #ifdef ENABLE_QOS
84 switch (mode) {
85 case PriorityMode::STW: {
86 for (uint32_t threadId : gcThreadId_) {
87 OHOS::QOS::SetQosForOtherThread(OHOS::QOS::QosLevel::QOS_USER_INTERACTIVE, threadId);
88 }
89 return;
90 }
91 case PriorityMode::FOREGROUND: {
92 for (uint32_t threadId : gcThreadId_) {
93 OHOS::QOS::SetQosForOtherThread(OHOS::QOS::QosLevel::QOS_USER_INITIATED, threadId);
94 }
95 return;
96 }
97 case PriorityMode::BACKGROUND: {
98 for (uint32_t threadId : gcThreadId_) {
99 OHOS::QOS::ResetQosForOtherThread(threadId);
100 }
101 return;
102 }
103 default:
104 UNREACHABLE();
105 break;
106 }
107 #endif
108 }
109
RecordThreadId()110 void Runner::RecordThreadId()
111 {
112 LockHolder holder(mtx_);
113 gcThreadId_.emplace_back(os::thread::GetCurrentThreadId());
114 }
115
SetRunTask(uint32_t threadId,Task * task)116 void Runner::SetRunTask(uint32_t threadId, Task *task)
117 {
118 LockHolder holder(mtx_);
119 runningTask_[threadId] = task;
120 }
121
Run(uint32_t threadId)122 void Runner::Run(uint32_t threadId)
123 {
124 os::thread::native_handle_type thread = os::thread::GetNativeHandle();
125 os::thread::SetThreadName(thread, "OS_GC_Thread");
126 PrologueHook(thread);
127 RecordThreadId();
128 while (std::unique_ptr<Task> task = taskQueue_.PopTask()) {
129 SetRunTask(threadId, task.get());
130 task->Run(threadId);
131 SetRunTask(threadId, nullptr);
132 }
133 EpilogueHook(thread);
134 }
135 } // namespace panda::ecmascript
136