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 #include "common_interfaces/thread/thread_holder-inl.h" 17 18 #include "common_components/common_runtime/hooks.h" 19 #include "common_components/mutator/mutator.h" 20 #include "common_components/mutator/thread_local.h" 21 #include "common_interfaces/base_runtime.h" 22 #include "common_interfaces/thread/base_thread.h" 23 #include "common_interfaces/thread/thread_holder_manager.h" 24 #include "common_interfaces/thread/thread_state_transition.h" 25 26 namespace common { 27 thread_local ThreadHolder *currentThreadHolder = nullptr; 28 CreateAndRegisterNewThreadHolder(void * vm)29ThreadHolder *ThreadHolder::CreateAndRegisterNewThreadHolder(void *vm) 30 { 31 if (ThreadLocal::IsArkProcessor()) { 32 LOG_COMMON(FATAL) << "CreateAndRegisterNewThreadHolder fail"; 33 return nullptr; 34 } 35 Mutator* mutator = Mutator::NewMutator(); 36 CHECK_CC(mutator != nullptr); 37 mutator->SetEcmaVMPtr(vm); 38 ThreadHolder *holder = mutator->GetThreadHolder(); 39 BaseRuntime::GetInstance()->GetThreadHolderManager().RegisterThreadHolder(holder); 40 return holder; 41 } 42 ReleaseAllocBuffer()43void ThreadHolder::ReleaseAllocBuffer() 44 { 45 ThreadManagedScope scope(this); 46 if (allocBuffer_) { 47 auto buf = reinterpret_cast<AllocationBuffer*>(allocBuffer_); 48 if (buf->DecreaseRefCount()) { 49 buf->Unregister(); 50 delete buf; 51 } 52 allocBuffer_ = nullptr; 53 } 54 } 55 DestroyThreadHolder(ThreadHolder * holder)56void ThreadHolder::DestroyThreadHolder(ThreadHolder *holder) 57 { 58 holder->ReleaseAllocBuffer(); 59 holder->TransferToNative(); 60 BaseRuntime::GetInstance()->GetThreadHolderManager().UnregisterThreadHolder(holder); 61 } 62 GetCurrent()63ThreadHolder *ThreadHolder::GetCurrent() 64 { 65 return currentThreadHolder; 66 } 67 SetCurrent(ThreadHolder * holder)68void ThreadHolder::SetCurrent(ThreadHolder *holder) 69 { 70 currentThreadHolder = holder; 71 } 72 RegisterJSThread(JSThread * jsThread)73void ThreadHolder::RegisterJSThread(JSThread *jsThread) 74 { 75 DCHECK_CC(!IsInRunningState()); 76 TransferToRunning(); 77 DCHECK_CC(jsThread_ == nullptr); 78 jsThread_ = jsThread; 79 mutatorBase_->RegisterJSThread(jsThread); 80 SynchronizeGCPhaseToJSThread(jsThread, mutatorBase_->GetMutatorPhase()); 81 TransferToNative(); 82 } 83 UnregisterJSThread(JSThread * jsThread)84void ThreadHolder::UnregisterJSThread(JSThread *jsThread) 85 { 86 DCHECK_CC(!IsInRunningState()); 87 TransferToRunning(); 88 DCHECK_CC(jsThread_ == jsThread); 89 jsThread_ = nullptr; 90 mutatorBase_->UnregisterJSThread(); 91 if (coroutines_.empty()) { 92 ThreadHolder::DestroyThreadHolder(this); 93 } 94 } 95 RegisterCoroutine(Coroutine * coroutine)96void ThreadHolder::RegisterCoroutine(Coroutine *coroutine) 97 { 98 DCHECK_CC(!IsInRunningState()); 99 TransferToRunning(); 100 DCHECK_CC(coroutines_.find(coroutine) == coroutines_.end()); 101 coroutines_.insert(coroutine); 102 TransferToNative(); 103 } 104 UnregisterCoroutine(Coroutine * coroutine)105void ThreadHolder::UnregisterCoroutine(Coroutine *coroutine) 106 { 107 DCHECK_CC(!IsInRunningState()); 108 TransferToRunning(); 109 DCHECK_CC(coroutines_.find(coroutine) != coroutines_.end()); 110 coroutines_.erase(coroutine); 111 if (coroutines_.empty() && jsThread_ == nullptr) { 112 ThreadHolder::DestroyThreadHolder(this); 113 } 114 } 115 TryBindMutator()116bool ThreadHolder::TryBindMutator() 117 { 118 if (ThreadLocal::IsArkProcessor()) { 119 return false; 120 } 121 122 BaseRuntime::GetInstance()->GetThreadHolderManager().BindMutator(this); 123 allocBuffer_ = ThreadLocal::GetAllocBuffer(); 124 reinterpret_cast<AllocationBuffer*>(allocBuffer_)->IncreaseRefCount(); 125 DCHECK_CC(allocBuffer_ != nullptr); 126 return true; 127 } 128 BindMutator()129void ThreadHolder::BindMutator() 130 { 131 if (!TryBindMutator()) { 132 LOG_COMMON(FATAL) << "BindMutator fail"; 133 return; 134 } 135 } 136 UnbindMutator()137void ThreadHolder::UnbindMutator() 138 { 139 allocBuffer_ = nullptr; 140 BaseRuntime::GetInstance()->GetThreadHolderManager().UnbindMutator(this); 141 } 142 WaitSuspension()143void ThreadHolder::WaitSuspension() 144 { 145 mutatorBase_->HandleSuspensionRequest(); 146 } 147 VisitAllThreads(CommonRootVisitor visitor)148void ThreadHolder::VisitAllThreads(CommonRootVisitor visitor) 149 { 150 if (jsThread_ != nullptr) { 151 VisitJSThread(jsThread_, visitor); 152 } 153 for ([[maybe_unused]] auto *coroutine : coroutines_) { 154 // Depending on the integrated so 155 } 156 } 157 TryBindMutatorScope(ThreadHolder * holder)158ThreadHolder::TryBindMutatorScope::TryBindMutatorScope(ThreadHolder *holder) : holder_(nullptr) 159 { 160 if (holder->TryBindMutator()) { 161 holder_ = holder; 162 } 163 } 164 ~TryBindMutatorScope()165ThreadHolder::TryBindMutatorScope::~TryBindMutatorScope() 166 { 167 if (holder_ != nullptr) { 168 holder_->ReleaseAllocBuffer(); 169 holder_->UnbindMutator(); 170 holder_ = nullptr; 171 } 172 } 173 } // namespace common 174