• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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 #ifndef COMMON_COMPONENTS_MUTATOR_MUTATOR_MANAGER_H
17 #define COMMON_COMPONENTS_MUTATOR_MUTATOR_MANAGER_H
18 
19 #include <bitset>
20 #include <list>
21 #include <mutex>
22 #include <unordered_set>
23 
24 #include "common_components/base/atomic_spin_lock.h"
25 #include "common_components/base/globals.h"
26 #include "common_components/base/rw_lock.h"
27 #include "common_components/common/page_allocator.h"
28 #include "common_components/mutator/mutator.h"
29 #if defined(__linux__) || defined(PANDA_TARGET_OHOS) || defined(__APPLE__)
30 #include "common_components/mutator/safepoint_page_manager.h"
31 #endif
32 #include "common_components/mutator/thread_local.h"
33 #include "common_components/log/log.h"
34 
35 namespace common {
36 const uint64_t WAIT_LOCK_INTERVAL = 5000; // 5us
37 const uint64_t WAIT_LOCK_TIMEOUT = 30;    // seconds
38 const uint32_t MAX_TIMEOUT_TIMES = 1;
39 const int STW_TIMEOUTS_THREADS_BASE_COUNT = 100;
40 // STW wait base timeout in milliseconds, for every 100 threads, the time is increased by 240000ms.
41 const int STW_TIMEOUTS_BASE_MS = 240000;
42 const uint32_t LOCK_OWNER_NONE = 0;
43 const uint32_t LOCK_OWNER_GC = LOCK_OWNER_NONE + 1;
44 const uint32_t LOCK_OWNER_MUTATOR = LOCK_OWNER_GC + 1;
45 
46 extern bool g_enableGCTimeoutCheck;
47 
48 bool IsRuntimeThread();
49 bool IsGcThread();
50 
51 using MutatorVisitor = std::function<void(Mutator&)>;
52 
53 struct STWParam {
54     const char* stwReason;
55     uint64_t elapsedTimeNs = 0;
56 
GetElapsedNsSTWParam57     uint64_t GetElapsedNs() const { return elapsedTimeNs; }
GetElapsedUsSTWParam58     uint64_t GetElapsedUs() const { return elapsedTimeNs / 1000; }
59 };
60 
61 class MutatorManager {
62 public:
MutatorManager()63     MutatorManager() {}
~MutatorManager()64     ~MutatorManager()
65     {
66 #if defined(__linux__) || defined(PANDA_TARGET_OHOS) || defined(__APPLE__)
67         if (safepointPageManager_ != nullptr) {
68             delete safepointPageManager_;
69             safepointPageManager_ = nullptr;
70         }
71 #endif
72     }
73 
74     MutatorManager(const MutatorManager&) = delete;
75     MutatorManager(MutatorManager&&) = delete;
76     MutatorManager& operator=(const MutatorManager&) = delete;
77     MutatorManager& operator=(MutatorManager&&) = delete;
78 
79     static MutatorManager& Instance() noexcept;
80 
81     void Init();
Fini()82     void Fini() { SatbBuffer::Instance().Fini(); }
83 
84     // Get the mutator list instance
GetMutatorCount()85     size_t GetMutatorCount()
86     {
87         size_t count = 0;
88         auto func = [&count](Mutator&) { count++; };
89         VisitAllMutators(func);
90         return count;
91     }
92 
GetAllMutators(std::vector<Mutator * > & mutators)93     void GetAllMutators(std::vector<Mutator*>& mutators)
94     {
95         auto func = [&mutators](Mutator& mutator) { mutators.emplace_back(&mutator); };
96         VisitAllMutators(func);
97     }
98 
TryAcquireMutatorManagementWLock()99     bool TryAcquireMutatorManagementWLock()
100     {
101         return mutatorManagementRWLock_.TryLockWrite();
102     }
103 
TryAcquireMutatorManagementRLock()104     bool TryAcquireMutatorManagementRLock()
105     {
106         return mutatorManagementRWLock_.TryLockRead();
107     }
108 
109     void AcquireMutatorManagementWLock();
110 
111     bool AcquireMutatorManagementWLockForCpuProfile();
112 
VisitMuatorHelper(void * argPtr,void * handle)113     static void VisitMuatorHelper(void* argPtr, void* handle)
114     {
115         Mutator* mutator = reinterpret_cast<Mutator*>(argPtr);
116         if (mutator != nullptr) {
117             (*reinterpret_cast<MutatorVisitor*>(handle))(*mutator);
118         }
119     }
120 
121     // Visit all mutators, hold mutatorListLock firstly
122     void VisitAllMutators(MutatorVisitor func, bool ignoreFinalizer = false);
123 
124     // Some functions about stw
125     void StopTheWorld(bool syncGCPhase, GCPhase phase);
126     void StartTheWorld() noexcept;
127     void WaitUntilAllStopped();
128     void DumpMutators(uint32_t timeoutTimes);
DemandSuspensionForStw()129     void DemandSuspensionForStw()
130     {
131         VisitAllMutators([](Mutator& mutator) {
132             mutator.SetSafepointActive(true);
133             mutator.SetSuspensionFlag(MutatorBase::SuspensionType::SUSPENSION_FOR_STW);
134         });
135     }
136 
CancelSuspensionAfterStw()137     void CancelSuspensionAfterStw()
138     {
139         VisitAllMutators([](Mutator& mutator) {
140             mutator.SetSafepointActive(false);
141             mutator.ClearSuspensionFlag(MutatorBase::SuspensionType::SUSPENSION_FOR_STW);
142         });
143     }
144 
145     void BindMutator(Mutator& mutator) const;
146     void UnbindMutator(Mutator& mutator) const;
147 
148     bool BindMutatorOnly(Mutator *mutator) const;
149     void UnbindMutatorOnly() const;
150 
151     // Create and initialize the local mutator, then register to mutatorlist.
152     Mutator* CreateMutator();
153 
154     // Delete the thread-local mutator and unregister from mutatorlist before a mutator exit
155     void TransitMutatorToExit();
156 
157     void DestroyMutator(Mutator* mutator);
158 
159     Mutator* CreateRuntimeMutator(ThreadType threadType) __attribute__((noinline));
160     void DestroyRuntimeMutator(ThreadType threadType);
161 
WorldStopped()162     bool WorldStopped() const { return worldStopped_.load(std::memory_order_acquire); }
163 
StwTriggered()164     bool StwTriggered() const { return stwTriggered_.load(); }
165 
LockStopTheWorld()166     void LockStopTheWorld() { stwMutex_.lock(); }
167 
UnlockStopTheWorld()168     void UnlockStopTheWorld() noexcept { stwMutex_.unlock(); }
169 
170     void EnsurePhaseTransition(GCPhase phase, std::list<Mutator*> &undoneMutators);
171     void TransitionAllMutatorsToGCPhase(GCPhase phase);
172 
173     void EnsureCpuProfileFinish(std::list<Mutator*> &undoneMutators);
174 
175     template<class STWFunction>
176     void FlipMutators(STWParam& param, STWFunction&& stwFunction, FlipFunction *flipFunction);
177 #if defined(GCINFO_DEBUG) && GCINFO_DEBUG
178     void DumpForDebug();
179     void DumpAllGcInfos();
180 #endif
181 
GetStwFutexWord()182     __attribute__((always_inline)) inline int* GetStwFutexWord()
183     {
184         return reinterpret_cast<int*>(&suspensionMutatorCount_);
185     }
186 
GetStwFutexWordValue()187     __attribute__((always_inline)) inline int GetStwFutexWordValue() const
188     {
189         return GetSuspensionMutatorCount();
190     }
191 
GetSuspensionMutatorCount()192     __attribute__((always_inline)) inline uint32_t GetSuspensionMutatorCount() const
193     {
194         return suspensionMutatorCount_.load(std::memory_order_acquire);
195     }
196 
SetSuspensionMutatorCount(uint32_t total)197     __attribute__((always_inline)) inline void SetSuspensionMutatorCount(uint32_t total)
198     {
199         suspensionMutatorCount_.store(total, std::memory_order_release);
200     }
201 
202 #if defined(_WIN64) || defined (__APPLE__)
MutatorWait()203     __attribute__((always_inline)) inline void MutatorWait()
204     {
205         std::unique_lock<std::mutex> mutatorsToStopLck(mutatorSuspensionMtx_);
206         mutatorSuspensionCV_.wait(mutatorsToStopLck, [this]() {
207             return GetSuspensionMutatorCount() == 0;
208         });
209     }
210 
WakeAllMutators()211     __attribute__((always_inline)) inline void WakeAllMutators()
212     {
213         std::unique_lock<std::mutex> mutatorsToStopLck(mutatorSuspensionMtx_);
214         mutatorSuspensionCV_.notify_all();
215     }
216 #endif
217 
218 #if not defined (_WIN64)
GetSafepointPageManager()219     const SafepointPageManager* GetSafepointPageManager() const { return safepointPageManager_; }
220 #endif
221 
MutatorManagementRLock()222     void MutatorManagementRLock() { mutatorManagementRWLock_.LockRead(); }
223 
MutatorManagementRUnlock()224     void MutatorManagementRUnlock() { mutatorManagementRWLock_.UnlockRead(); }
225 
MutatorManagementWLock()226     void MutatorManagementWLock() { mutatorManagementRWLock_.LockWrite(); }
227 
MutatorManagementWUnlock()228     void MutatorManagementWUnlock() { mutatorManagementRWLock_.UnlockWrite(); }
229 
230     void DestroyExpiredMutators();
231 
232     bool HasNativeMutator();
233 
234     std::mutex allMutatorListLock_;  /* Mutex guard for allMutatorList */
235     // Manage all mutator during runtime
236     /* Manage all active mutators during runtime */
237     std::list<Mutator*, StdContainerAllocator<Mutator*, MUTATOR_LIST>> allMutatorList_;
238 
239 private:
240     using ExpiredMutatorList = std::list<Mutator*, StdContainerAllocator<Mutator*, MUTATOR_LIST>>;
241     ExpiredMutatorList expiringMutators_;
242     std::mutex expiringMutatorListLock_;
243 
244     // guard mutator set for stop-the-world
245     RwLock mutatorManagementRWLock_;
246 
247     // count of mutators need to be suspended for stw.
248     // this field is also used as futex wait/wakeup word for stw.
249     std::atomic<uint32_t> suspensionMutatorCount_;
250 
251     // Ensure only one thread can doing STW.
252     std::recursive_mutex stwMutex_;
253 #ifndef NDEBUG
254     bool saferegionStateChanged_ = false;
255 #endif
256     // Show current STW state
257     std::atomic<bool> worldStopped_ = { false };
258     std::atomic<bool> stwTriggered_ = { false };
259 #if defined(_WIN64) || defined (__APPLE__)
260     std::condition_variable mutatorSuspensionCV_;
261     std::mutex mutatorSuspensionMtx_;
262 #endif
263 #if not defined (_WIN64)
264     SafepointPageManager* safepointPageManager_ = nullptr;
265 #endif
266     Mutator* nativeMutator_ = nullptr;
267 };
268 
269 // Scoped stop the world.
270 class ScopedStopTheWorld {
271 public:
272     __attribute__((always_inline)) explicit ScopedStopTheWorld(STWParam& param,
273                                                                bool syncGCPhase = false, GCPhase phase = GC_PHASE_IDLE)
stwParam_(param)274         : stwParam_(param)
275     {
276         reason_ = param.stwReason;
277         MutatorManager::Instance().StopTheWorld(syncGCPhase, phase);
278         startTime_ = TimeUtil::NanoSeconds();
279     }
280 
~ScopedStopTheWorld()281     __attribute__((always_inline)) ~ScopedStopTheWorld()
282     {
283         uint64_t elapsedTimeNs = GetElapsedTime();
284         stwParam_.elapsedTimeNs = elapsedTimeNs;
285         VLOG(DEBUG, "%s stw time %zu us", reason_, elapsedTimeNs / 1000); // 1000:nsec per usec
286         MutatorManager::Instance().StartTheWorld();
287     }
288 
GetElapsedTime()289     uint64_t GetElapsedTime() const { return TimeUtil::NanoSeconds() - startTime_; }
290 
291 private:
292     uint64_t startTime_ = 0;
293     const char* reason_ = nullptr;
294     STWParam& stwParam_;
295 };
296 
297 // Scoped lock STW, this prevent other thread STW during the current scope.
298 class ScopedSTWLock {
299 public:
ScopedSTWLock()300     __attribute__((always_inline)) explicit ScopedSTWLock() { MutatorManager::Instance().LockStopTheWorld(); }
301 
~ScopedSTWLock()302     __attribute__((always_inline)) ~ScopedSTWLock() { MutatorManager::Instance().UnlockStopTheWorld(); }
303 };
304 } // namespace common
305 
306 #endif  // COMMON_COMPONENTS_MUTATOR_MUTATOR_MANAGER_H
307