1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
18 #define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
19 
20 #include "base/casts.h"
21 #include "jni_internal-inl.h"
22 #include "read_barrier.h"
23 #include "thread-inl.h"
24 #include "verify_object.h"
25 
26 namespace art {
27 
28 // Scoped change into and out of a particular state. Handles Runnable transitions that require
29 // more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
30 // ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
31 // the unchecked variant doesn't aid annotalysis.
32 class ScopedThreadStateChange {
33  public:
ScopedThreadStateChange(Thread * self,ThreadState new_thread_state)34   ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
35       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE
36       : self_(self), thread_state_(new_thread_state), expected_has_no_thread_(false) {
37     if (UNLIKELY(self_ == NULL)) {
38       // Value chosen arbitrarily and won't be used in the destructor since thread_ == NULL.
39       old_thread_state_ = kTerminated;
40       Runtime* runtime = Runtime::Current();
41       CHECK(runtime == NULL || !runtime->IsStarted() || runtime->IsShuttingDown(self_));
42     } else {
43       DCHECK_EQ(self, Thread::Current());
44       // Read state without locks, ok as state is effectively thread local and we're not interested
45       // in the suspend count (this will be handled in the runnable transitions).
46       old_thread_state_ = self->GetState();
47       if (old_thread_state_ != new_thread_state) {
48         if (new_thread_state == kRunnable) {
49           self_->TransitionFromSuspendedToRunnable();
50         } else if (old_thread_state_ == kRunnable) {
51           self_->TransitionFromRunnableToSuspended(new_thread_state);
52         } else {
53           // A suspended transition to another effectively suspended transition, ok to use Unsafe.
54           self_->SetState(new_thread_state);
55         }
56       }
57     }
58   }
59 
LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)60   ~ScopedThreadStateChange() LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE {
61     if (UNLIKELY(self_ == NULL)) {
62       if (!expected_has_no_thread_) {
63         Runtime* runtime = Runtime::Current();
64         bool shutting_down = (runtime == NULL) || runtime->IsShuttingDown(nullptr);
65         CHECK(shutting_down);
66       }
67     } else {
68       if (old_thread_state_ != thread_state_) {
69         if (old_thread_state_ == kRunnable) {
70           self_->TransitionFromSuspendedToRunnable();
71         } else if (thread_state_ == kRunnable) {
72           self_->TransitionFromRunnableToSuspended(old_thread_state_);
73         } else {
74           // A suspended transition to another effectively suspended transition, ok to use Unsafe.
75           self_->SetState(old_thread_state_);
76         }
77       }
78     }
79   }
80 
Self()81   Thread* Self() const {
82     return self_;
83   }
84 
85  protected:
86   // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
ScopedThreadStateChange()87   ScopedThreadStateChange()
88       : self_(NULL), thread_state_(kTerminated), old_thread_state_(kTerminated),
89         expected_has_no_thread_(true) {}
90 
91   Thread* const self_;
92   const ThreadState thread_state_;
93 
94  private:
95   ThreadState old_thread_state_;
96   const bool expected_has_no_thread_;
97 
98   friend class ScopedObjectAccessUnchecked;
99   DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
100 };
101 
102 // Assumes we are already runnable.
103 class ScopedObjectAccessAlreadyRunnable {
104  public:
Self()105   Thread* Self() const {
106     return self_;
107   }
108 
Env()109   JNIEnvExt* Env() const {
110     return env_;
111   }
112 
Vm()113   JavaVMExt* Vm() const {
114     return vm_;
115   }
116 
117   /*
118    * Add a local reference for an object to the indirect reference table associated with the
119    * current stack frame.  When the native function returns, the reference will be discarded.
120    *
121    * We need to allow the same reference to be added multiple times, and cope with NULL.
122    *
123    * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
124    * it's best if we don't grab a mutex.
125    */
126   template<typename T>
AddLocalReference(mirror::Object * obj)127   T AddLocalReference(mirror::Object* obj) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
128     Locks::mutator_lock_->AssertSharedHeld(Self());
129     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
130     if (obj == NULL) {
131       return NULL;
132     }
133     DCHECK_NE((reinterpret_cast<uintptr_t>(obj) & 0xffff0000), 0xebad0000);
134     return Env()->AddLocalReference<T>(obj);
135   }
136 
137   template<typename T>
Decode(jobject obj)138   T Decode(jobject obj) const
139       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
140     Locks::mutator_lock_->AssertSharedHeld(Self());
141     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
142     return down_cast<T>(Self()->DecodeJObject(obj));
143   }
144 
DecodeField(jfieldID fid)145   mirror::ArtField* DecodeField(jfieldID fid) const
146       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
147     Locks::mutator_lock_->AssertSharedHeld(Self());
148     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
149     CHECK(!kMovingFields);
150     mirror::ArtField* field = reinterpret_cast<mirror::ArtField*>(fid);
151     return ReadBarrier::BarrierForRoot<mirror::ArtField, kWithReadBarrier>(&field);
152   }
153 
EncodeField(mirror::ArtField * field)154   jfieldID EncodeField(mirror::ArtField* field) const
155       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
156     Locks::mutator_lock_->AssertSharedHeld(Self());
157     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
158     CHECK(!kMovingFields);
159     return reinterpret_cast<jfieldID>(field);
160   }
161 
DecodeMethod(jmethodID mid)162   mirror::ArtMethod* DecodeMethod(jmethodID mid) const
163       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
164     Locks::mutator_lock_->AssertSharedHeld(Self());
165     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
166     CHECK(!kMovingMethods);
167     mirror::ArtMethod* method = reinterpret_cast<mirror::ArtMethod*>(mid);
168     return ReadBarrier::BarrierForRoot<mirror::ArtMethod, kWithReadBarrier>(&method);
169   }
170 
EncodeMethod(mirror::ArtMethod * method)171   jmethodID EncodeMethod(mirror::ArtMethod* method) const
172       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
173     Locks::mutator_lock_->AssertSharedHeld(Self());
174     DCHECK(IsRunnable());  // Don't work with raw objects in non-runnable states.
175     CHECK(!kMovingMethods);
176     return reinterpret_cast<jmethodID>(method);
177   }
178 
IsRunnable()179   bool IsRunnable() const {
180     return self_->GetState() == kRunnable;
181   }
182 
183  protected:
ScopedObjectAccessAlreadyRunnable(JNIEnv * env)184   explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
185       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE
186       : self_(ThreadForEnv(env)), env_(down_cast<JNIEnvExt*>(env)), vm_(env_->vm) {
187   }
188 
ScopedObjectAccessAlreadyRunnable(Thread * self)189   explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
190       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE
191       : self_(self), env_(down_cast<JNIEnvExt*>(self->GetJniEnv())),
192         vm_(env_ != nullptr ? env_->vm : nullptr) {
193   }
194 
195   // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
196   // change into Runnable or acquire a share on the mutator_lock_.
ScopedObjectAccessAlreadyRunnable(JavaVM * vm)197   explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
198       : self_(nullptr), env_(nullptr), vm_(down_cast<JavaVMExt*>(vm)) {}
199 
200   // Here purely to force inlining.
~ScopedObjectAccessAlreadyRunnable()201   ~ScopedObjectAccessAlreadyRunnable() ALWAYS_INLINE {
202   }
203 
204   // Self thread, can be null.
205   Thread* const self_;
206   // The full JNIEnv.
207   JNIEnvExt* const env_;
208   // The full JavaVM.
209   JavaVMExt* const vm_;
210 };
211 
212 // Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
213 //
214 // This class performs the necessary thread state switching to and from Runnable and lets us
215 // amortize the cost of working out the current thread. Additionally it lets us check (and repair)
216 // apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
217 // into jobjects via methods of this class. Performing this here enforces the Runnable thread state
218 // for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
219 // is also manipulating the Object.
220 //
221 // The destructor transitions back to the previous thread state, typically Native. In this state
222 // GC and thread suspension may occur.
223 //
224 // For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
225 // the mutator_lock_ will be acquired on construction.
226 class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
227  public:
ScopedObjectAccessUnchecked(JNIEnv * env)228   explicit ScopedObjectAccessUnchecked(JNIEnv* env)
229       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE
230       : ScopedObjectAccessAlreadyRunnable(env), tsc_(Self(), kRunnable) {
231     Self()->VerifyStack();
232     Locks::mutator_lock_->AssertSharedHeld(Self());
233   }
234 
ScopedObjectAccessUnchecked(Thread * self)235   explicit ScopedObjectAccessUnchecked(Thread* self)
236       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_) ALWAYS_INLINE
237       : ScopedObjectAccessAlreadyRunnable(self), tsc_(self, kRunnable) {
238     Self()->VerifyStack();
239     Locks::mutator_lock_->AssertSharedHeld(Self());
240   }
241 
242   // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
243   // change into Runnable or acquire a share on the mutator_lock_.
ScopedObjectAccessUnchecked(JavaVM * vm)244   explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
245       : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
246 
247  private:
248   // The scoped thread state change makes sure that we are runnable and restores the thread state
249   // in the destructor.
250   const ScopedThreadStateChange tsc_;
251 
252   DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
253 };
254 
255 // Annotalysis helping variant of the above.
256 class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
257  public:
ScopedObjectAccess(JNIEnv * env)258   explicit ScopedObjectAccess(JNIEnv* env)
259       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
260       SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
261       : ScopedObjectAccessUnchecked(env) {
262   }
263 
ScopedObjectAccess(Thread * self)264   explicit ScopedObjectAccess(Thread* self)
265       LOCKS_EXCLUDED(Locks::thread_suspend_count_lock_)
266       SHARED_LOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE
267       : ScopedObjectAccessUnchecked(self) {
268   }
269 
UNLOCK_FUNCTION(Locks::mutator_lock_)270   ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE {
271     // Base class will release share of lock. Invoked after this destructor.
272   }
273 
274  private:
275   // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
276   //       routines operating with just a VM are sound, they are not, but when you have just a VM
277   //       you cannot call the unsound routines.
ScopedObjectAccess(JavaVM * vm)278   explicit ScopedObjectAccess(JavaVM* vm)
279       SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
280       : ScopedObjectAccessUnchecked(vm) {}
281 
282   friend class ScopedCheck;
283   DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
284 };
285 
286 }  // namespace art
287 
288 #endif  // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
289