xref: /aosp_15_r20/art/runtime/scoped_thread_state_change-inl.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2012 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include <android-base/logging.h>
23*795d594fSAndroid Build Coastguard Worker 
24*795d594fSAndroid Build Coastguard Worker #include "base/casts.h"
25*795d594fSAndroid Build Coastguard Worker #include "base/mutex.h"
26*795d594fSAndroid Build Coastguard Worker #include "jni/jni_env_ext-inl.h"
27*795d594fSAndroid Build Coastguard Worker #include "obj_ptr-inl.h"
28*795d594fSAndroid Build Coastguard Worker #include "runtime.h"
29*795d594fSAndroid Build Coastguard Worker #include "thread-inl.h"
30*795d594fSAndroid Build Coastguard Worker 
31*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
32*795d594fSAndroid Build Coastguard Worker 
ScopedThreadStateChange(Thread * self,ThreadState new_thread_state)33*795d594fSAndroid Build Coastguard Worker inline ScopedThreadStateChange::ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
34*795d594fSAndroid Build Coastguard Worker     : self_(self), thread_state_(new_thread_state), expected_has_no_thread_(false) {
35*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(self_ == nullptr)) {
36*795d594fSAndroid Build Coastguard Worker     // Value chosen arbitrarily and won't be used in the destructor since thread_ == null.
37*795d594fSAndroid Build Coastguard Worker     old_thread_state_ = ThreadState::kTerminated;
38*795d594fSAndroid Build Coastguard Worker     Runtime* runtime = Runtime::Current();
39*795d594fSAndroid Build Coastguard Worker     CHECK(runtime == nullptr || !runtime->IsStarted() || runtime->IsShuttingDown(self_));
40*795d594fSAndroid Build Coastguard Worker   } else {
41*795d594fSAndroid Build Coastguard Worker     DCHECK_EQ(self, Thread::Current());
42*795d594fSAndroid Build Coastguard Worker     // Read state without locks, ok as state is effectively thread local and we're not interested
43*795d594fSAndroid Build Coastguard Worker     // in the suspend count (this will be handled in the runnable transitions).
44*795d594fSAndroid Build Coastguard Worker     old_thread_state_ = self->GetState();
45*795d594fSAndroid Build Coastguard Worker     if (old_thread_state_ != new_thread_state) {
46*795d594fSAndroid Build Coastguard Worker       if (new_thread_state == ThreadState::kRunnable) {
47*795d594fSAndroid Build Coastguard Worker         self_->TransitionFromSuspendedToRunnable();
48*795d594fSAndroid Build Coastguard Worker       } else if (old_thread_state_ == ThreadState::kRunnable) {
49*795d594fSAndroid Build Coastguard Worker         self_->TransitionFromRunnableToSuspended(new_thread_state);
50*795d594fSAndroid Build Coastguard Worker       } else {
51*795d594fSAndroid Build Coastguard Worker         // A transition between suspended states.
52*795d594fSAndroid Build Coastguard Worker         self_->SetState(new_thread_state);
53*795d594fSAndroid Build Coastguard Worker       }
54*795d594fSAndroid Build Coastguard Worker     }
55*795d594fSAndroid Build Coastguard Worker   }
56*795d594fSAndroid Build Coastguard Worker }
57*795d594fSAndroid Build Coastguard Worker 
~ScopedThreadStateChange()58*795d594fSAndroid Build Coastguard Worker inline ScopedThreadStateChange::~ScopedThreadStateChange() {
59*795d594fSAndroid Build Coastguard Worker   if (UNLIKELY(self_ == nullptr)) {
60*795d594fSAndroid Build Coastguard Worker     ScopedThreadChangeDestructorCheck();
61*795d594fSAndroid Build Coastguard Worker   } else {
62*795d594fSAndroid Build Coastguard Worker     if (old_thread_state_ != thread_state_) {
63*795d594fSAndroid Build Coastguard Worker       if (old_thread_state_ == ThreadState::kRunnable) {
64*795d594fSAndroid Build Coastguard Worker         self_->TransitionFromSuspendedToRunnable();
65*795d594fSAndroid Build Coastguard Worker       } else if (thread_state_ == ThreadState::kRunnable) {
66*795d594fSAndroid Build Coastguard Worker         self_->TransitionFromRunnableToSuspended(old_thread_state_);
67*795d594fSAndroid Build Coastguard Worker       } else {
68*795d594fSAndroid Build Coastguard Worker         // A transition between suspended states.
69*795d594fSAndroid Build Coastguard Worker         self_->SetState(old_thread_state_);
70*795d594fSAndroid Build Coastguard Worker       }
71*795d594fSAndroid Build Coastguard Worker     }
72*795d594fSAndroid Build Coastguard Worker   }
73*795d594fSAndroid Build Coastguard Worker }
74*795d594fSAndroid Build Coastguard Worker 
75*795d594fSAndroid Build Coastguard Worker template<typename T>
AddLocalReference(ObjPtr<mirror::Object> obj)76*795d594fSAndroid Build Coastguard Worker inline T ScopedObjectAccessAlreadyRunnable::AddLocalReference(ObjPtr<mirror::Object> obj) const {
77*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertSharedHeld(Self());
78*795d594fSAndroid Build Coastguard Worker   if (kIsDebugBuild) {
79*795d594fSAndroid Build Coastguard Worker     CHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
80*795d594fSAndroid Build Coastguard Worker     DCheckObjIsNotClearedJniWeakGlobal(obj);
81*795d594fSAndroid Build Coastguard Worker   }
82*795d594fSAndroid Build Coastguard Worker   return obj == nullptr ? nullptr : Env()->AddLocalReference<T>(obj);
83*795d594fSAndroid Build Coastguard Worker }
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker template<typename T>
Decode(jobject obj)86*795d594fSAndroid Build Coastguard Worker inline ObjPtr<T> ScopedObjectAccessAlreadyRunnable::Decode(jobject obj) const {
87*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertSharedHeld(Self());
88*795d594fSAndroid Build Coastguard Worker   DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
89*795d594fSAndroid Build Coastguard Worker   return ObjPtr<T>::DownCast(Self()->DecodeJObject(obj));
90*795d594fSAndroid Build Coastguard Worker }
91*795d594fSAndroid Build Coastguard Worker 
IsRunnable()92*795d594fSAndroid Build Coastguard Worker inline bool ScopedObjectAccessAlreadyRunnable::IsRunnable() const {
93*795d594fSAndroid Build Coastguard Worker   return self_->GetState() == ThreadState::kRunnable;
94*795d594fSAndroid Build Coastguard Worker }
95*795d594fSAndroid Build Coastguard Worker 
ScopedObjectAccessAlreadyRunnable(JNIEnv * env)96*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
97*795d594fSAndroid Build Coastguard Worker     : self_(Thread::ForEnv(env)), env_(down_cast<JNIEnvExt*>(env)), vm_(env_->GetVm()) {}
98*795d594fSAndroid Build Coastguard Worker 
ScopedObjectAccessAlreadyRunnable(Thread * self)99*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccessAlreadyRunnable::ScopedObjectAccessAlreadyRunnable(Thread* self)
100*795d594fSAndroid Build Coastguard Worker     : self_(self),
101*795d594fSAndroid Build Coastguard Worker       env_(down_cast<JNIEnvExt*>(self->GetJniEnv())),
102*795d594fSAndroid Build Coastguard Worker       vm_(env_ != nullptr ? env_->GetVm() : nullptr) {}
103*795d594fSAndroid Build Coastguard Worker 
ScopedObjectAccessUnchecked(JNIEnv * env)104*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccessUnchecked::ScopedObjectAccessUnchecked(JNIEnv* env)
105*795d594fSAndroid Build Coastguard Worker     : ScopedObjectAccessAlreadyRunnable(env), tsc_(Self(), ThreadState::kRunnable) {
106*795d594fSAndroid Build Coastguard Worker   Self()->VerifyStack();
107*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertSharedHeld(Self());
108*795d594fSAndroid Build Coastguard Worker }
109*795d594fSAndroid Build Coastguard Worker 
ScopedObjectAccessUnchecked(Thread * self)110*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccessUnchecked::ScopedObjectAccessUnchecked(Thread* self)
111*795d594fSAndroid Build Coastguard Worker     : ScopedObjectAccessAlreadyRunnable(self), tsc_(self, ThreadState::kRunnable) {
112*795d594fSAndroid Build Coastguard Worker   Self()->VerifyStack();
113*795d594fSAndroid Build Coastguard Worker   Locks::mutator_lock_->AssertSharedHeld(Self());
114*795d594fSAndroid Build Coastguard Worker }
115*795d594fSAndroid Build Coastguard Worker 
ScopedObjectAccess(JNIEnv * env)116*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccess::ScopedObjectAccess(JNIEnv* env) : ScopedObjectAccessUnchecked(env) {}
ScopedObjectAccess(Thread * self)117*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccess::ScopedObjectAccess(Thread* self) : ScopedObjectAccessUnchecked(self) {}
~ScopedObjectAccess()118*795d594fSAndroid Build Coastguard Worker inline ScopedObjectAccess::~ScopedObjectAccess() {}
119*795d594fSAndroid Build Coastguard Worker 
ScopedThreadSuspension(Thread * self,ThreadState suspended_state)120*795d594fSAndroid Build Coastguard Worker inline ScopedThreadSuspension::ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
121*795d594fSAndroid Build Coastguard Worker     : self_(self), suspended_state_(suspended_state) {
122*795d594fSAndroid Build Coastguard Worker   DCHECK(self_ != nullptr);
123*795d594fSAndroid Build Coastguard Worker   self_->TransitionFromRunnableToSuspended(suspended_state);
124*795d594fSAndroid Build Coastguard Worker }
125*795d594fSAndroid Build Coastguard Worker 
~ScopedThreadSuspension()126*795d594fSAndroid Build Coastguard Worker inline ScopedThreadSuspension::~ScopedThreadSuspension() {
127*795d594fSAndroid Build Coastguard Worker   DCHECK_EQ(self_->GetState(), suspended_state_);
128*795d594fSAndroid Build Coastguard Worker   self_->TransitionFromSuspendedToRunnable();
129*795d594fSAndroid Build Coastguard Worker }
130*795d594fSAndroid Build Coastguard Worker 
131*795d594fSAndroid Build Coastguard Worker }  // namespace art
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_INL_H_
134