• 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 #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)29 ThreadHolder *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()43 void 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)56 void ThreadHolder::DestroyThreadHolder(ThreadHolder *holder)
57 {
58     holder->ReleaseAllocBuffer();
59     holder->TransferToNative();
60     BaseRuntime::GetInstance()->GetThreadHolderManager().UnregisterThreadHolder(holder);
61 }
62 
GetCurrent()63 ThreadHolder *ThreadHolder::GetCurrent()
64 {
65     return currentThreadHolder;
66 }
67 
SetCurrent(ThreadHolder * holder)68 void ThreadHolder::SetCurrent(ThreadHolder *holder)
69 {
70     currentThreadHolder = holder;
71 }
72 
RegisterJSThread(JSThread * jsThread)73 void 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)84 void 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)96 void 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)105 void 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()116 bool 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()129 void ThreadHolder::BindMutator()
130 {
131     if (!TryBindMutator()) {
132         LOG_COMMON(FATAL) << "BindMutator fail";
133         return;
134     }
135 }
136 
UnbindMutator()137 void ThreadHolder::UnbindMutator()
138 {
139     allocBuffer_ = nullptr;
140     BaseRuntime::GetInstance()->GetThreadHolderManager().UnbindMutator(this);
141 }
142 
WaitSuspension()143 void ThreadHolder::WaitSuspension()
144 {
145     mutatorBase_->HandleSuspensionRequest();
146 }
147 
VisitAllThreads(CommonRootVisitor visitor)148 void 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)158 ThreadHolder::TryBindMutatorScope::TryBindMutatorScope(ThreadHolder *holder) : holder_(nullptr)
159 {
160     if (holder->TryBindMutator()) {
161         holder_ = holder;
162     }
163 }
164 
~TryBindMutatorScope()165 ThreadHolder::TryBindMutatorScope::~TryBindMutatorScope()
166 {
167     if (holder_ != nullptr) {
168         holder_->ReleaseAllocBuffer();
169         holder_->UnbindMutator();
170         holder_ = nullptr;
171     }
172 }
173 } // namespace common
174