1 /**
2 * Copyright (c) 2021-2024 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 <utility>
17
18 #include "libpandabase/os/cpu_affinity.h"
19 #include "runtime/mem/gc/gc.h"
20 #include "runtime/mem/gc/workers/gc_workers_thread_pool.h"
21
22 namespace ark::mem {
23
Init()24 bool GCWorkersProcessor::Init()
25 {
26 return gcThreadsPools_->GetGC()->InitWorker(&workerData_);
27 }
28
Destroy()29 bool GCWorkersProcessor::Destroy()
30 {
31 gcThreadsPools_->GetGC()->DestroyWorker(workerData_);
32 return true;
33 }
34
Process(GCWorkersTask && task)35 bool GCWorkersProcessor::Process(GCWorkersTask &&task)
36 {
37 gcThreadsPools_->RunGCWorkersTask(&task, workerData_);
38 return true;
39 }
40
GCWorkersThreadPool(GC * gc,size_t threadsCount)41 GCWorkersThreadPool::GCWorkersThreadPool(GC *gc, size_t threadsCount)
42 : GCWorkersTaskPool(gc), internalAllocator_(gc->GetInternalAllocator()), threadsCount_(threadsCount)
43 {
44 ASSERT(gc->GetPandaVm() != nullptr);
45 queue_ = internalAllocator_->New<GCWorkersQueueSimple>(internalAllocator_, QUEUE_SIZE_MAX_SIZE);
46 workerIface_ = internalAllocator_->New<GCWorkersCreationInterface>(gc->GetPandaVm());
47 threadPool_ = internalAllocator_->New<ThreadPool<GCWorkersTask, GCWorkersProcessor, GCWorkersThreadPool *>>(
48 internalAllocator_, queue_, this, threadsCount, "GC_WORKER",
49 static_cast<WorkerCreationInterface *>(workerIface_));
50 }
51
TryAddTask(GCWorkersTask && task)52 bool GCWorkersThreadPool::TryAddTask(GCWorkersTask &&task)
53 {
54 return threadPool_->TryPutTask(std::forward<GCWorkersTask &&>(task));
55 }
56
SetAffinity(GCWorkersProcessor * proc,size_t gcThreadsCount)57 static void SetAffinity(GCWorkersProcessor *proc, size_t gcThreadsCount)
58 {
59 // For first GC, GC-workers can be not started
60 if (UNLIKELY(!proc->IsStarted())) {
61 return;
62 }
63 const auto &bestAndMiddle = os::CpuAffinityManager::GetBestAndMiddleCpuSet();
64 if (gcThreadsCount < bestAndMiddle.Count()) {
65 os::CpuAffinityManager::SetAffinityForThread(proc->GetTid(), bestAndMiddle);
66 }
67 }
68
UnsetAffinity(GCWorkersProcessor * proc,size_t data)69 static void UnsetAffinity(GCWorkersProcessor *proc, [[maybe_unused]] size_t data)
70 {
71 os::CpuAffinityManager::SetAffinityForThread(proc->GetTid(), os::CpuPower::WEAK);
72 }
73
SetAffinityForGCWorkers()74 void GCWorkersThreadPool::SetAffinityForGCWorkers()
75 {
76 // Total GC threads count = GC Thread + GC workers
77 threadPool_->EnumerateProcs(SetAffinity, threadsCount_ + 1U);
78 }
79
UnsetAffinityForGCWorkers()80 void GCWorkersThreadPool::UnsetAffinityForGCWorkers()
81 {
82 threadPool_->EnumerateProcs(UnsetAffinity, 0U);
83 }
84
~GCWorkersThreadPool()85 GCWorkersThreadPool::~GCWorkersThreadPool()
86 {
87 internalAllocator_->Delete(threadPool_);
88 internalAllocator_->Delete(workerIface_);
89 queue_->Finalize();
90 internalAllocator_->Delete(queue_);
91 }
92
RunInCurrentThread()93 void GCWorkersThreadPool::RunInCurrentThread()
94 {
95 threadPool_->Help();
96 }
97
98 } // namespace ark::mem
99