1 /**
2 * Copyright (c) 2023-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 "runtime/mem/gc/g1/update_remset_task_queue.h"
17
18 #include "libpandabase/taskmanager/task_scheduler.h"
19 #include "runtime/include/language_config.h"
20 #include "runtime/mem/gc/g1/g1-gc.h"
21
22 namespace ark::mem {
23
24 template <class LanguageConfig>
UpdateRemsetTaskQueue(G1GC<LanguageConfig> * gc,GCG1BarrierSet::ThreadLocalCardQueues * queue,os::memory::Mutex * queueLock,size_t regionSize,bool updateConcurrent,size_t minConcurrentCardsToProcess,size_t hotCardsProcessingFrequency)25 UpdateRemsetTaskQueue<LanguageConfig>::UpdateRemsetTaskQueue(G1GC<LanguageConfig> *gc,
26 GCG1BarrierSet::ThreadLocalCardQueues *queue,
27 os::memory::Mutex *queueLock, size_t regionSize,
28 bool updateConcurrent, size_t minConcurrentCardsToProcess,
29 size_t hotCardsProcessingFrequency)
30 : UpdateRemsetWorker<LanguageConfig>(gc, queue, queueLock, regionSize, updateConcurrent,
31 minConcurrentCardsToProcess, hotCardsProcessingFrequency)
32 {
33 taskRunner_ = [this]() {
34 os::memory::LockHolder lh(this->updateRemsetLock_);
35 taskRunnerWaiterId_ = taskmanager::INVALID_WAITER_ID;
36 ASSERT(this->hasTaskInTaskmanager_);
37
38 auto iterationFlag = this->GetFlag();
39 if (iterationFlag == UpdateRemsetWorker<LanguageConfig>::UpdateRemsetWorkerFlags::IS_STOP_WORKER) {
40 this->hasTaskInTaskmanager_ = false;
41 return;
42 }
43
44 if (iterationFlag == UpdateRemsetWorker<LanguageConfig>::UpdateRemsetWorkerFlags::IS_PAUSED_BY_GC_THREAD ||
45 iterationFlag == UpdateRemsetWorker<LanguageConfig>::UpdateRemsetWorkerFlags::IS_INVALIDATE_REGIONS) {
46 this->AddToWaitList();
47 return;
48 }
49
50 ASSERT(!this->pausedByGcThread_);
51 auto processedCards = this->ProcessAllCards();
52 if (processedCards < this->GetMinConcurrentCardsToProcess()) {
53 // need to add to wait list with timeout
54 this->AddToWaitListWithTimeout();
55 return;
56 }
57
58 // After cards processing add new cards processing task to task manager
59 this->hasTaskInTaskmanager_ = false;
60 this->StartProcessCards();
61 };
62 }
63
64 template <class LanguageConfig>
65 UpdateRemsetTaskQueue<LanguageConfig>::~UpdateRemsetTaskQueue() = default;
66
67 template <class LanguageConfig>
StartProcessCards()68 void UpdateRemsetTaskQueue<LanguageConfig>::StartProcessCards()
69 {
70 // If we already have process cards task in task manager then no need to add a new task
71 if (hasTaskInTaskmanager_) {
72 return;
73 }
74 ASSERT(taskRunner_);
75 auto processCardsTask = taskmanager::Task::Create(UPDATE_REMSET_TASK_PROPERTIES, taskRunner_);
76 hasTaskInTaskmanager_ = true;
77 this->GetGC()->GetWorkersTaskQueue()->AddTask(std::move(processCardsTask));
78 }
79
80 template <class LanguageConfig>
ContinueProcessCards()81 void UpdateRemsetTaskQueue<LanguageConfig>::ContinueProcessCards()
82 {
83 if (taskRunnerWaiterId_ != taskmanager::INVALID_WAITER_ID) {
84 taskmanager::TaskScheduler::GetTaskScheduler()->SignalWaitList(taskRunnerWaiterId_);
85 } else {
86 StartProcessCards();
87 }
88 }
89
90 template <class LanguageConfig>
CreateWorkerImpl()91 void UpdateRemsetTaskQueue<LanguageConfig>::CreateWorkerImpl()
92 {
93 os::memory::LockHolder lh(this->updateRemsetLock_);
94 ASSERT(!hasTaskInTaskmanager_);
95 StartProcessCards();
96 }
97
98 template <class LanguageConfig>
DestroyWorkerImpl()99 void UpdateRemsetTaskQueue<LanguageConfig>::DestroyWorkerImpl()
100 {
101 taskmanager::TaskScheduler::GetTaskScheduler()->WaitForFinishAllTasksWithProperties(UPDATE_REMSET_TASK_PROPERTIES);
102 [[maybe_unused]] os::memory::LockHolder lh(this->updateRemsetLock_);
103 ASSERT(!hasTaskInTaskmanager_);
104 }
105
106 template <class LanguageConfig>
AddToWaitList()107 void UpdateRemsetTaskQueue<LanguageConfig>::AddToWaitList()
108 {
109 ASSERT(taskRunner_);
110 auto processCardsTask = taskmanager::Task::Create(UPDATE_REMSET_TASK_PROPERTIES, taskRunner_);
111 taskRunnerWaiterId_ =
112 taskmanager::TaskScheduler::GetTaskScheduler()->AddTaskToWaitList(std::move(processCardsTask));
113 }
114
115 template <class LanguageConfig>
AddToWaitListWithTimeout()116 void UpdateRemsetTaskQueue<LanguageConfig>::AddToWaitListWithTimeout()
117 {
118 ASSERT(taskRunner_);
119 auto processCardsTask = taskmanager::Task::Create(UPDATE_REMSET_TASK_PROPERTIES, taskRunner_);
120 static constexpr uint64_t TIMEOUT_MS = 1U;
121 taskRunnerWaiterId_ = taskmanager::TaskScheduler::GetTaskScheduler()->AddTaskToWaitListWithTimeout(
122 std::move(processCardsTask), TIMEOUT_MS);
123 }
124
125 TEMPLATE_CLASS_LANGUAGE_CONFIG(UpdateRemsetTaskQueue);
126 } // namespace ark::mem
127