blob: 0c42c5ae8d7c3c9871b34ad06ebe6d7fa11410db [file] [log] [blame]
Ian Rogers00f7d0e2012-07-19 15:28:27 -07001/*
Mathieu Chartier0795f232016-09-27 18:43:30 -07002 * Copyright (C) 2016 The Android Open Source Project
Ian Rogers00f7d0e2012-07-19 15:28:27 -07003 *
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
Brian Carlstromfc0e3212013-07-17 14:40:12 -070017#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
18#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_
Ian Rogers00f7d0e2012-07-19 15:28:27 -070019
Andreas Gampec15a2f42017-04-21 12:09:39 -070020#include "jni.h"
21
22#include "base/macros.h"
23#include "base/mutex.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070024#include "base/value_object.h"
Mathieu Chartier0795f232016-09-27 18:43:30 -070025#include "thread_state.h"
Ian Rogers00f7d0e2012-07-19 15:28:27 -070026
27namespace art {
28
Andreas Gampec15a2f42017-04-21 12:09:39 -070029class JavaVMExt;
Ian Rogers55256cb2017-12-21 17:07:11 -080030class JNIEnvExt;
Andreas Gampec73cb642017-02-22 10:11:30 -080031template<class MirrorType> class ObjPtr;
Andreas Gampec15a2f42017-04-21 12:09:39 -070032class Thread;
33
34namespace mirror {
35class Object;
36} // namespace mirror
Mathieu Chartier0795f232016-09-27 18:43:30 -070037
Ian Rogers00f7d0e2012-07-19 15:28:27 -070038// Scoped change into and out of a particular state. Handles Runnable transitions that require
39// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and
Mathieu Chartiereb8167a2014-05-07 15:43:14 -070040// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects,
Ian Rogers00f7d0e2012-07-19 15:28:27 -070041// the unchecked variant doesn't aid annotalysis.
Mathieu Chartierf1d666e2015-09-03 16:13:34 -070042class ScopedThreadStateChange : public ValueObject {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070043 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -070044 ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state)
45 REQUIRES(!Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070046
Mathieu Chartier0795f232016-09-27 18:43:30 -070047 ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070048
Mathieu Chartier0795f232016-09-27 18:43:30 -070049 ALWAYS_INLINE Thread* Self() const {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070050 return self_;
51 }
52
53 protected:
54 // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*.
Mathieu Chartier0795f232016-09-27 18:43:30 -070055 ScopedThreadStateChange() {}
Ian Rogers00f7d0e2012-07-19 15:28:27 -070056
Mathieu Chartier0795f232016-09-27 18:43:30 -070057 Thread* const self_ = nullptr;
58 const ThreadState thread_state_ = kTerminated;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070059
60 private:
Mathieu Chartier0795f232016-09-27 18:43:30 -070061 ThreadState old_thread_state_ = kTerminated;
62 const bool expected_has_no_thread_ = true;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070063
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070064 friend class ScopedObjectAccessUnchecked;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070065 DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
66};
67
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070068// Assumes we are already runnable.
Mathieu Chartierf1d666e2015-09-03 16:13:34 -070069class ScopedObjectAccessAlreadyRunnable : public ValueObject {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070070 public:
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070071 Thread* Self() const {
72 return self_;
Ian Rogersc0fa3ad2013-02-05 00:11:55 -080073 }
74
Ian Rogers00f7d0e2012-07-19 15:28:27 -070075 JNIEnvExt* Env() const {
76 return env_;
77 }
78
79 JavaVMExt* Vm() const {
80 return vm_;
81 }
82
Andreas Gampec15a2f42017-04-21 12:09:39 -070083 bool ForceCopy() const;
Ian Rogers68d8b422014-07-17 11:09:10 -070084
Ian Rogers00f7d0e2012-07-19 15:28:27 -070085 /*
86 * Add a local reference for an object to the indirect reference table associated with the
87 * current stack frame. When the native function returns, the reference will be discarded.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070088 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -070089 * We need to allow the same reference to be added multiple times, and cope with nullptr.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070090 *
Elliott Hughes9dcd45c2013-07-29 14:40:52 -070091 * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
Ian Rogers00f7d0e2012-07-19 15:28:27 -070092 * it's best if we don't grab a mutex.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070093 */
94 template<typename T>
Mathieu Chartier8778c522016-10-04 19:06:30 -070095 T AddLocalReference(ObjPtr<mirror::Object> obj) const
Mathieu Chartier0795f232016-09-27 18:43:30 -070096 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070097
Andreas Gampec73cb642017-02-22 10:11:30 -080098 template<typename T>
99 ObjPtr<T> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700100
Mathieu Chartier0795f232016-09-27 18:43:30 -0700101 ALWAYS_INLINE bool IsRunnable() const;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700102
103 protected:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700104 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
105 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700106
Mathieu Chartier0795f232016-09-27 18:43:30 -0700107 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
108 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700109
110 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
111 // change into Runnable or acquire a share on the mutator_lock_.
Andreas Gampec15a2f42017-04-21 12:09:39 -0700112 // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast,
113 // as it prevents forward declaration of JavaVMExt.
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700114 explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
Andreas Gampec15a2f42017-04-21 12:09:39 -0700115 : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700116
117 // Here purely to force inlining.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700118 ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700119
Andreas Gampec15a2f42017-04-21 12:09:39 -0700120 static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj)
121 REQUIRES_SHARED(Locks::mutator_lock_);
122
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700123 // Self thread, can be null.
124 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700125 // The full JNIEnv.
126 JNIEnvExt* const env_;
127 // The full JavaVM.
128 JavaVMExt* const vm_;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700129};
130
131// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
132//
133// This class performs the necessary thread state switching to and from Runnable and lets us
134// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
135// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
136// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
137// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
138// is also manipulating the Object.
139//
140// The destructor transitions back to the previous thread state, typically Native. In this state
141// GC and thread suspension may occur.
142//
143// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
144// the mutator_lock_ will be acquired on construction.
145class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
146 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700147 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
148 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700149
Mathieu Chartier0795f232016-09-27 18:43:30 -0700150 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
151 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700152
Mingyao Yang01b47b02017-02-03 12:09:57 -0800153 ALWAYS_INLINE ~ScopedObjectAccessUnchecked() REQUIRES(!Locks::thread_suspend_count_lock_) {}
154
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700155 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
156 // change into Runnable or acquire a share on the mutator_lock_.
157 explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
158 : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
159
160 private:
161 // The scoped thread state change makes sure that we are runnable and restores the thread state
162 // in the destructor.
163 const ScopedThreadStateChange tsc_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700164
165 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
166};
167
168// Annotalysis helping variant of the above.
169class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
170 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700171 ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
Mathieu Chartier90443472015-07-16 20:32:27 -0700172 REQUIRES(!Locks::thread_suspend_count_lock_)
Andreas Gampe90b936d2017-01-31 08:58:55 -0800173 SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700174
Mathieu Chartier0795f232016-09-27 18:43:30 -0700175 ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -0700176 REQUIRES(!Locks::thread_suspend_count_lock_)
Andreas Gampe90b936d2017-01-31 08:58:55 -0800177 SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700178
Mathieu Chartier0795f232016-09-27 18:43:30 -0700179 // Base class will release share of lock. Invoked after this destructor.
Andreas Gampe90b936d2017-01-31 08:58:55 -0800180 ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700181
182 private:
183 // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
184 // routines operating with just a VM are sound, they are not, but when you have just a VM
185 // you cannot call the unsound routines.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700186 explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700187 : ScopedObjectAccessUnchecked(vm) {}
188
189 friend class ScopedCheck;
190 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
191};
192
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700193// Annotalysis helper for going to a suspended state from runnable.
194class ScopedThreadSuspension : public ValueObject {
195 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700196 ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700197 REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700198 UNLOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700199
Mathieu Chartier0795f232016-09-27 18:43:30 -0700200 ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700201
202 private:
203 Thread* const self_;
204 const ThreadState suspended_state_;
205 DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
206};
207
208
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700209} // namespace art
210
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700211#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_