• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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