xref: /aosp_15_r20/art/runtime/scoped_thread_state_change.h (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2016 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_H_
18*795d594fSAndroid Build Coastguard Worker #define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "jni.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/locks.h"
23*795d594fSAndroid Build Coastguard Worker #include "base/macros.h"
24*795d594fSAndroid Build Coastguard Worker #include "base/value_object.h"
25*795d594fSAndroid Build Coastguard Worker #include "thread_state.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker namespace art HIDDEN {
28*795d594fSAndroid Build Coastguard Worker 
29*795d594fSAndroid Build Coastguard Worker class JavaVMExt;
30*795d594fSAndroid Build Coastguard Worker class JNIEnvExt;
31*795d594fSAndroid Build Coastguard Worker template<class MirrorType> class ObjPtr;
32*795d594fSAndroid Build Coastguard Worker class Thread;
33*795d594fSAndroid Build Coastguard Worker 
34*795d594fSAndroid Build Coastguard Worker namespace mirror {
35*795d594fSAndroid Build Coastguard Worker class Object;
36*795d594fSAndroid Build Coastguard Worker }  // namespace mirror
37*795d594fSAndroid Build Coastguard Worker 
38*795d594fSAndroid Build Coastguard Worker // Scoped change into and out of a particular state. Handles Runnable transitions that require
39*795d594fSAndroid Build Coastguard Worker // more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
40*795d594fSAndroid Build Coastguard Worker // ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
41*795d594fSAndroid Build Coastguard Worker // the unchecked variant doesn't aid annotalysis.
42*795d594fSAndroid Build Coastguard Worker class ScopedThreadStateChange : public ValueObject {
43*795d594fSAndroid Build Coastguard Worker  public:
44*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
45*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_);
46*795d594fSAndroid Build Coastguard Worker 
47*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_);
48*795d594fSAndroid Build Coastguard Worker 
Self()49*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE Thread* Self() const {
50*795d594fSAndroid Build Coastguard Worker     return self_;
51*795d594fSAndroid Build Coastguard Worker   }
52*795d594fSAndroid Build Coastguard Worker 
53*795d594fSAndroid Build Coastguard Worker  protected:
54*795d594fSAndroid Build Coastguard Worker   // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
ScopedThreadStateChange()55*795d594fSAndroid Build Coastguard Worker   ScopedThreadStateChange() {}
56*795d594fSAndroid Build Coastguard Worker 
57*795d594fSAndroid Build Coastguard Worker   Thread* const self_ = nullptr;
58*795d594fSAndroid Build Coastguard Worker   const ThreadState thread_state_ = ThreadState::kTerminated;
59*795d594fSAndroid Build Coastguard Worker 
60*795d594fSAndroid Build Coastguard Worker  private:
61*795d594fSAndroid Build Coastguard Worker   EXPORT void ScopedThreadChangeDestructorCheck();
62*795d594fSAndroid Build Coastguard Worker 
63*795d594fSAndroid Build Coastguard Worker   ThreadState old_thread_state_ = ThreadState::kTerminated;
64*795d594fSAndroid Build Coastguard Worker   const bool expected_has_no_thread_ = true;
65*795d594fSAndroid Build Coastguard Worker 
66*795d594fSAndroid Build Coastguard Worker   friend class ScopedObjectAccessUnchecked;
67*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
68*795d594fSAndroid Build Coastguard Worker };
69*795d594fSAndroid Build Coastguard Worker 
70*795d594fSAndroid Build Coastguard Worker // Assumes we are already runnable.
71*795d594fSAndroid Build Coastguard Worker class ScopedObjectAccessAlreadyRunnable : public ValueObject {
72*795d594fSAndroid Build Coastguard Worker  public:
Self()73*795d594fSAndroid Build Coastguard Worker   Thread* Self() const {
74*795d594fSAndroid Build Coastguard Worker     return self_;
75*795d594fSAndroid Build Coastguard Worker   }
76*795d594fSAndroid Build Coastguard Worker 
Env()77*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* Env() const {
78*795d594fSAndroid Build Coastguard Worker     return env_;
79*795d594fSAndroid Build Coastguard Worker   }
80*795d594fSAndroid Build Coastguard Worker 
Vm()81*795d594fSAndroid Build Coastguard Worker   JavaVMExt* Vm() const {
82*795d594fSAndroid Build Coastguard Worker     return vm_;
83*795d594fSAndroid Build Coastguard Worker   }
84*795d594fSAndroid Build Coastguard Worker 
85*795d594fSAndroid Build Coastguard Worker   bool ForceCopy() const;
86*795d594fSAndroid Build Coastguard Worker 
87*795d594fSAndroid Build Coastguard Worker   /*
88*795d594fSAndroid Build Coastguard Worker    * Add a local reference for an object to the indirect reference table associated with the
89*795d594fSAndroid Build Coastguard Worker    * current stack frame.  When the native function returns, the reference will be discarded.
90*795d594fSAndroid Build Coastguard Worker    *
91*795d594fSAndroid Build Coastguard Worker    * We need to allow the same reference to be added multiple times, and cope with nullptr.
92*795d594fSAndroid Build Coastguard Worker    *
93*795d594fSAndroid Build Coastguard Worker    * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
94*795d594fSAndroid Build Coastguard Worker    * it's best if we don't grab a mutex.
95*795d594fSAndroid Build Coastguard Worker    */
96*795d594fSAndroid Build Coastguard Worker   template<typename T>
97*795d594fSAndroid Build Coastguard Worker   T AddLocalReference(ObjPtr<mirror::Object> obj) const
98*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   template<typename T>
101*795d594fSAndroid Build Coastguard Worker   ObjPtr<T> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
102*795d594fSAndroid Build Coastguard Worker 
103*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE bool IsRunnable() const;
104*795d594fSAndroid Build Coastguard Worker 
105*795d594fSAndroid Build Coastguard Worker  protected:
106*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
107*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_);
108*795d594fSAndroid Build Coastguard Worker 
109*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
110*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_);
111*795d594fSAndroid Build Coastguard Worker 
112*795d594fSAndroid Build Coastguard Worker   // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
113*795d594fSAndroid Build Coastguard Worker   // change into Runnable or acquire a share on the mutator_lock_.
114*795d594fSAndroid Build Coastguard Worker   // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast,
115*795d594fSAndroid Build Coastguard Worker   //       as it prevents forward declaration of JavaVMExt.
ScopedObjectAccessAlreadyRunnable(JavaVM * vm)116*795d594fSAndroid Build Coastguard Worker   explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
117*795d594fSAndroid Build Coastguard Worker       : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {}
118*795d594fSAndroid Build Coastguard Worker 
119*795d594fSAndroid Build Coastguard Worker   // Here purely to force inlining.
~ScopedObjectAccessAlreadyRunnable()120*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
121*795d594fSAndroid Build Coastguard Worker 
122*795d594fSAndroid Build Coastguard Worker   static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj)
123*795d594fSAndroid Build Coastguard Worker       REQUIRES_SHARED(Locks::mutator_lock_);
124*795d594fSAndroid Build Coastguard Worker 
125*795d594fSAndroid Build Coastguard Worker   // Self thread, can be null.
126*795d594fSAndroid Build Coastguard Worker   Thread* const self_;
127*795d594fSAndroid Build Coastguard Worker   // The full JNIEnv.
128*795d594fSAndroid Build Coastguard Worker   JNIEnvExt* const env_;
129*795d594fSAndroid Build Coastguard Worker   // The full JavaVM.
130*795d594fSAndroid Build Coastguard Worker   JavaVMExt* const vm_;
131*795d594fSAndroid Build Coastguard Worker };
132*795d594fSAndroid Build Coastguard Worker 
133*795d594fSAndroid Build Coastguard Worker // Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
134*795d594fSAndroid Build Coastguard Worker //
135*795d594fSAndroid Build Coastguard Worker // This class performs the necessary thread state switching to and from Runnable and lets us
136*795d594fSAndroid Build Coastguard Worker // amortize the cost of working out the current thread. Additionally it lets us check (and repair)
137*795d594fSAndroid Build Coastguard Worker // apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
138*795d594fSAndroid Build Coastguard Worker // into jobjects via methods of this class. Performing this here enforces the Runnable thread state
139*795d594fSAndroid Build Coastguard Worker // for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
140*795d594fSAndroid Build Coastguard Worker // is also manipulating the Object.
141*795d594fSAndroid Build Coastguard Worker //
142*795d594fSAndroid Build Coastguard Worker // The destructor transitions back to the previous thread state, typically Native. In this state
143*795d594fSAndroid Build Coastguard Worker // GC and thread suspension may occur.
144*795d594fSAndroid Build Coastguard Worker //
145*795d594fSAndroid Build Coastguard Worker // For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
146*795d594fSAndroid Build Coastguard Worker // the mutator_lock_ will be acquired on construction.
147*795d594fSAndroid Build Coastguard Worker class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
148*795d594fSAndroid Build Coastguard Worker  public:
149*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
150*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_);
151*795d594fSAndroid Build Coastguard Worker 
152*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
153*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_);
154*795d594fSAndroid Build Coastguard Worker 
~ScopedObjectAccessUnchecked()155*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ~ScopedObjectAccessUnchecked() REQUIRES(!Locks::thread_suspend_count_lock_) {}
156*795d594fSAndroid Build Coastguard Worker 
157*795d594fSAndroid Build Coastguard Worker   // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
158*795d594fSAndroid Build Coastguard Worker   // change into Runnable or acquire a share on the mutator_lock_.
ScopedObjectAccessUnchecked(JavaVM * vm)159*795d594fSAndroid Build Coastguard Worker   explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
160*795d594fSAndroid Build Coastguard Worker       : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
161*795d594fSAndroid Build Coastguard Worker 
162*795d594fSAndroid Build Coastguard Worker  private:
163*795d594fSAndroid Build Coastguard Worker   // The scoped thread state change makes sure that we are runnable and restores the thread state
164*795d594fSAndroid Build Coastguard Worker   // in the destructor.
165*795d594fSAndroid Build Coastguard Worker   const ScopedThreadStateChange tsc_;
166*795d594fSAndroid Build Coastguard Worker 
167*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
168*795d594fSAndroid Build Coastguard Worker };
169*795d594fSAndroid Build Coastguard Worker 
170*795d594fSAndroid Build Coastguard Worker // Annotalysis helping variant of the above.
171*795d594fSAndroid Build Coastguard Worker class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
172*795d594fSAndroid Build Coastguard Worker  public:
173*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
174*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_)
175*795d594fSAndroid Build Coastguard Worker       SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
176*795d594fSAndroid Build Coastguard Worker 
177*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
178*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_)
179*795d594fSAndroid Build Coastguard Worker       SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
180*795d594fSAndroid Build Coastguard Worker 
181*795d594fSAndroid Build Coastguard Worker   // Base class will release share of lock. Invoked after this destructor.
182*795d594fSAndroid Build Coastguard Worker   ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE;
183*795d594fSAndroid Build Coastguard Worker 
184*795d594fSAndroid Build Coastguard Worker  private:
185*795d594fSAndroid Build Coastguard Worker   // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
186*795d594fSAndroid Build Coastguard Worker   //       routines operating with just a VM are sound, they are not, but when you have just a VM
187*795d594fSAndroid Build Coastguard Worker   //       you cannot call the unsound routines.
ScopedObjectAccess(JavaVM * vm)188*795d594fSAndroid Build Coastguard Worker   explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
189*795d594fSAndroid Build Coastguard Worker       : ScopedObjectAccessUnchecked(vm) {}
190*795d594fSAndroid Build Coastguard Worker 
191*795d594fSAndroid Build Coastguard Worker   friend class ScopedCheck;
192*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
193*795d594fSAndroid Build Coastguard Worker };
194*795d594fSAndroid Build Coastguard Worker 
195*795d594fSAndroid Build Coastguard Worker // Annotalysis helper for going to a suspended state from runnable.
196*795d594fSAndroid Build Coastguard Worker class ScopedThreadSuspension : public ValueObject {
197*795d594fSAndroid Build Coastguard Worker  public:
198*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
199*795d594fSAndroid Build Coastguard Worker       REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
200*795d594fSAndroid Build Coastguard Worker       UNLOCK_FUNCTION(Locks::mutator_lock_);
201*795d594fSAndroid Build Coastguard Worker 
202*795d594fSAndroid Build Coastguard Worker   ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
203*795d594fSAndroid Build Coastguard Worker 
204*795d594fSAndroid Build Coastguard Worker  private:
205*795d594fSAndroid Build Coastguard Worker   Thread* const self_;
206*795d594fSAndroid Build Coastguard Worker   const ThreadState suspended_state_;
207*795d594fSAndroid Build Coastguard Worker   DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
208*795d594fSAndroid Build Coastguard Worker };
209*795d594fSAndroid Build Coastguard Worker 
210*795d594fSAndroid Build Coastguard Worker }  // namespace art
211*795d594fSAndroid Build Coastguard Worker 
212*795d594fSAndroid Build Coastguard Worker #endif  // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
213