blob: 08cb5b4689e739b0b8b03bdfec534b6135b6f20f [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
Andreas Gampe7fbc4a52018-11-28 08:26:47 -080022#include "base/locks.h"
Andreas Gampec15a2f42017-04-21 12:09:39 -070023#include "base/macros.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:
Andreas Gampe1b0fcf42019-07-23 16:39:21 -070061 void ScopedThreadChangeDestructorCheck();
62
Mathieu Chartier0795f232016-09-27 18:43:30 -070063 ThreadState old_thread_state_ = kTerminated;
64 const bool expected_has_no_thread_ = true;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070065
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070066 friend class ScopedObjectAccessUnchecked;
Ian Rogers00f7d0e2012-07-19 15:28:27 -070067 DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange);
68};
69
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070070// Assumes we are already runnable.
Mathieu Chartierf1d666e2015-09-03 16:13:34 -070071class ScopedObjectAccessAlreadyRunnable : public ValueObject {
Ian Rogers00f7d0e2012-07-19 15:28:27 -070072 public:
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -070073 Thread* Self() const {
74 return self_;
Ian Rogersc0fa3ad2013-02-05 00:11:55 -080075 }
76
Ian Rogers00f7d0e2012-07-19 15:28:27 -070077 JNIEnvExt* Env() const {
78 return env_;
79 }
80
81 JavaVMExt* Vm() const {
82 return vm_;
83 }
84
Andreas Gampec15a2f42017-04-21 12:09:39 -070085 bool ForceCopy() const;
Ian Rogers68d8b422014-07-17 11:09:10 -070086
Ian Rogers00f7d0e2012-07-19 15:28:27 -070087 /*
88 * Add a local reference for an object to the indirect reference table associated with the
89 * current stack frame. When the native function returns, the reference will be discarded.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070090 *
Mathieu Chartier2cebb242015-04-21 16:50:40 -070091 * We need to allow the same reference to be added multiple times, and cope with nullptr.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070092 *
Elliott Hughes9dcd45c2013-07-29 14:40:52 -070093 * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and
Ian Rogers00f7d0e2012-07-19 15:28:27 -070094 * it's best if we don't grab a mutex.
Ian Rogers00f7d0e2012-07-19 15:28:27 -070095 */
96 template<typename T>
Mathieu Chartier8778c522016-10-04 19:06:30 -070097 T AddLocalReference(ObjPtr<mirror::Object> obj) const
Mathieu Chartier0795f232016-09-27 18:43:30 -070098 REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -070099
Andreas Gampec73cb642017-02-22 10:11:30 -0800100 template<typename T>
101 ObjPtr<T> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700102
Mathieu Chartier0795f232016-09-27 18:43:30 -0700103 ALWAYS_INLINE bool IsRunnable() const;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700104
105 protected:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700106 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env)
107 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700108
Mathieu Chartier0795f232016-09-27 18:43:30 -0700109 ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self)
110 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700111
112 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
113 // change into Runnable or acquire a share on the mutator_lock_.
Andreas Gampec15a2f42017-04-21 12:09:39 -0700114 // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast,
115 // as it prevents forward declaration of JavaVMExt.
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700116 explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm)
Andreas Gampec15a2f42017-04-21 12:09:39 -0700117 : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700118
119 // Here purely to force inlining.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700120 ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {}
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700121
Andreas Gampec15a2f42017-04-21 12:09:39 -0700122 static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj)
123 REQUIRES_SHARED(Locks::mutator_lock_);
124
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700125 // Self thread, can be null.
126 Thread* const self_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700127 // The full JNIEnv.
128 JNIEnvExt* const env_;
129 // The full JavaVM.
130 JavaVMExt* const vm_;
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700131};
132
133// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions).
134//
135// This class performs the necessary thread state switching to and from Runnable and lets us
136// amortize the cost of working out the current thread. Additionally it lets us check (and repair)
137// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects
138// into jobjects via methods of this class. Performing this here enforces the Runnable thread state
139// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code
140// is also manipulating the Object.
141//
142// The destructor transitions back to the previous thread state, typically Native. In this state
143// GC and thread suspension may occur.
144//
145// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of
146// the mutator_lock_ will be acquired on construction.
147class ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable {
148 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700149 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env)
150 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700151
Mathieu Chartier0795f232016-09-27 18:43:30 -0700152 ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self)
153 REQUIRES(!Locks::thread_suspend_count_lock_);
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700154
Mingyao Yang01b47b02017-02-03 12:09:57 -0800155 ALWAYS_INLINE ~ScopedObjectAccessUnchecked() REQUIRES(!Locks::thread_suspend_count_lock_) {}
156
Mathieu Chartier2b7c4d12014-05-19 10:52:16 -0700157 // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't
158 // change into Runnable or acquire a share on the mutator_lock_.
159 explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE
160 : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {}
161
162 private:
163 // The scoped thread state change makes sure that we are runnable and restores the thread state
164 // in the destructor.
165 const ScopedThreadStateChange tsc_;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700166
167 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked);
168};
169
170// Annotalysis helping variant of the above.
171class ScopedObjectAccess : public ScopedObjectAccessUnchecked {
172 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700173 ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env)
Mathieu Chartier90443472015-07-16 20:32:27 -0700174 REQUIRES(!Locks::thread_suspend_count_lock_)
Andreas Gampe90b936d2017-01-31 08:58:55 -0800175 SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700176
Mathieu Chartier0795f232016-09-27 18:43:30 -0700177 ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self)
Mathieu Chartier90443472015-07-16 20:32:27 -0700178 REQUIRES(!Locks::thread_suspend_count_lock_)
Andreas Gampe90b936d2017-01-31 08:58:55 -0800179 SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700180
Mathieu Chartier0795f232016-09-27 18:43:30 -0700181 // Base class will release share of lock. Invoked after this destructor.
Andreas Gampe90b936d2017-01-31 08:58:55 -0800182 ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE;
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700183
184 private:
185 // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that
186 // routines operating with just a VM are sound, they are not, but when you have just a VM
187 // you cannot call the unsound routines.
Mathieu Chartier0795f232016-09-27 18:43:30 -0700188 explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_)
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700189 : ScopedObjectAccessUnchecked(vm) {}
190
191 friend class ScopedCheck;
192 DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess);
193};
194
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700195// Annotalysis helper for going to a suspended state from runnable.
196class ScopedThreadSuspension : public ValueObject {
197 public:
Mathieu Chartier0795f232016-09-27 18:43:30 -0700198 ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state)
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700199 REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_)
Mathieu Chartier0795f232016-09-27 18:43:30 -0700200 UNLOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700201
Mathieu Chartier0795f232016-09-27 18:43:30 -0700202 ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_);
Mathieu Chartierf1d666e2015-09-03 16:13:34 -0700203
204 private:
205 Thread* const self_;
206 const ThreadState suspended_state_;
207 DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension);
208};
209
210
Ian Rogers00f7d0e2012-07-19 15:28:27 -0700211} // namespace art
212
Brian Carlstromfc0e3212013-07-17 14:40:12 -0700213#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_