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 22namespace panda::ecmascript { 23Runner::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 40void 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 57void 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 70void 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 81void 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 110void Runner::RecordThreadId() 111{ 112 LockHolder holder(mtx_); 113 gcThreadId_.emplace_back(os::thread::GetCurrentThreadId()); 114} 115 116void Runner::SetRunTask(uint32_t threadId, Task *task) 117{ 118 LockHolder holder(mtx_); 119 runningTask_[threadId] = task; 120} 121 122void 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