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