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