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