1 /**
2 * Copyright (c) 2023-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 "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 hasTaskInTaskmanager_ = true;
76 this->GetGC()->GetWorkersTaskQueue()->AddForegroundTask(taskRunner_);
77 }
78
79 template <class LanguageConfig>
ContinueProcessCards()80 void UpdateRemsetTaskQueue<LanguageConfig>::ContinueProcessCards()
81 {
82 if (taskRunnerWaiterId_ != taskmanager::INVALID_WAITER_ID) {
83 this->GetGC()->GetWorkersTaskQueue()->SignalWaitList(taskRunnerWaiterId_);
84 } else {
85 StartProcessCards();
86 }
87 }
88
89 template <class LanguageConfig>
CreateWorkerImpl()90 void UpdateRemsetTaskQueue<LanguageConfig>::CreateWorkerImpl()
91 {
92 os::memory::LockHolder lh(this->updateRemsetLock_);
93 ASSERT(!hasTaskInTaskmanager_);
94 StartProcessCards();
95 }
96
97 template <class LanguageConfig>
DestroyWorkerImpl()98 void UpdateRemsetTaskQueue<LanguageConfig>::DestroyWorkerImpl()
99 {
100 this->GetGC()->GetWorkersTaskQueue()->WaitForegroundTasks();
101 [[maybe_unused]] os::memory::LockHolder lh(this->updateRemsetLock_);
102 ASSERT(!hasTaskInTaskmanager_);
103 }
104
105 template <class LanguageConfig>
AddToWaitList()106 void UpdateRemsetTaskQueue<LanguageConfig>::AddToWaitList()
107 {
108 ASSERT(taskRunner_);
109 taskRunnerWaiterId_ = this->GetGC()->GetWorkersTaskQueue()->AddForegroundTaskInWaitList(taskRunner_);
110 }
111
112 template <class LanguageConfig>
AddToWaitListWithTimeout()113 void UpdateRemsetTaskQueue<LanguageConfig>::AddToWaitListWithTimeout()
114 {
115 ASSERT(taskRunner_);
116 static constexpr uint64_t TIMEOUT_MS = 1U;
117 taskRunnerWaiterId_ = this->GetGC()->GetWorkersTaskQueue()->AddForegroundTaskInWaitList(taskRunner_, TIMEOUT_MS);
118 }
119
120 TEMPLATE_CLASS_LANGUAGE_CONFIG(UpdateRemsetTaskQueue);
121 } // namespace ark::mem
122