100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers/* 20795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier * Copyright (C) 2016 The Android Open Source Project 300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * 400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * you may not use this file except in compliance with the License. 600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * You may obtain a copy of the License at 700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * 800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * http://www.apache.org/licenses/LICENSE-2.0 900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * 1000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * Unless required by applicable law or agreed to in writing, software 1100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * distributed under the License is distributed on an "AS IS" BASIS, 1200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * See the License for the specific language governing permissions and 1400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * limitations under the License. 1500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers */ 1600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_ 18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_ 1900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 20c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "jni.h" 21c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe 22c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "base/macros.h" 23c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe#include "base/mutex.h" 240795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "base/value_object.h" 250795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "thread_state.h" 2600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 2700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersnamespace art { 2800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 29c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampeclass JavaVMExt; 3055256cb60e11d4fac71affb4b9760a2931a3598dIan Rogersclass JNIEnvExt; 31c73cb64585f301c8bb3b03a0684f6baead99b7acAndreas Gampetemplate<class MirrorType> class ObjPtr; 32c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampeclass Thread; 33c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe 34c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampenamespace mirror { 35c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampeclass Object; 36c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe} // namespace mirror 370795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier 3800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Scoped change into and out of a particular state. Handles Runnable transitions that require 3900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// more complicated suspension checking. The subclasses ScopedObjectAccessUnchecked and 40eb8167a4f4d27fce0530f6724ab8032610cd146bMathieu Chartier// ScopedObjectAccess are used to handle the change into Runnable to Get direct access to objects, 4100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// the unchecked variant doesn't aid annotalysis. 42f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartierclass ScopedThreadStateChange : public ValueObject { 4300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 440795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE ScopedThreadStateChange(Thread* self, ThreadState new_thread_state) 450795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_); 4600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 470795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE ~ScopedThreadStateChange() REQUIRES(!Locks::thread_suspend_count_lock_); 4800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 490795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE Thread* Self() const { 5000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return self_; 5100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 5200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 5300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers protected: 5400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // Constructor used by ScopedJniThreadState for an unattached thread that has access to the VM*. 550795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ScopedThreadStateChange() {} 5600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 570795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier Thread* const self_ = nullptr; 580795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier const ThreadState thread_state_ = kTerminated; 5900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 6000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 610795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ThreadState old_thread_state_ = kTerminated; 620795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier const bool expected_has_no_thread_ = true; 6300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 642b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier friend class ScopedObjectAccessUnchecked; 6500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ScopedThreadStateChange); 6600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 6700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 682b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// Assumes we are already runnable. 69f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartierclass ScopedObjectAccessAlreadyRunnable : public ValueObject { 7000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 712b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier Thread* Self() const { 722b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier return self_; 73c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogers } 74c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogers 7500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JNIEnvExt* Env() const { 7600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return env_; 7700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 7800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 7900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JavaVMExt* Vm() const { 8000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return vm_; 8100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers } 8200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 83c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe bool ForceCopy() const; 8468d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers 8500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers /* 8600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * Add a local reference for an object to the indirect reference table associated with the 8700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * current stack frame. When the native function returns, the reference will be discarded. 8800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * 892cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier * We need to allow the same reference to be added multiple times, and cope with nullptr. 9000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * 919dcd45c60c691524bd8ef7d6f65075d9ee3e5554Elliott Hughes * This will be called on otherwise unreferenced objects. We cannot do GC allocations here, and 9200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers * it's best if we don't grab a mutex. 9300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers */ 9400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers template<typename T> 958778c521de4f686118549ef7b20ae497e53b9e93Mathieu Chartier T AddLocalReference(ObjPtr<mirror::Object> obj) const 960795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier REQUIRES_SHARED(Locks::mutator_lock_); 9700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 98c73cb64585f301c8bb3b03a0684f6baead99b7acAndreas Gampe template<typename T> 99c73cb64585f301c8bb3b03a0684f6baead99b7acAndreas Gampe ObjPtr<T> Decode(jobject obj) const REQUIRES_SHARED(Locks::mutator_lock_); 10000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 1010795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE bool IsRunnable() const; 1022b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1032b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier protected: 1040795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(JNIEnv* env) 1050795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_); 1062b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1070795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedObjectAccessAlreadyRunnable(Thread* self) 1080795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_); 1092b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1102b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't 1112b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // change into Runnable or acquire a share on the mutator_lock_. 112c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe // Note: The reinterpret_cast is backed by a static_assert in the cc file. Avoid a down_cast, 113c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe // as it prevents forward declaration of JavaVMExt. 1142b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier explicit ScopedObjectAccessAlreadyRunnable(JavaVM* vm) 115c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe : self_(nullptr), env_(nullptr), vm_(reinterpret_cast<JavaVMExt*>(vm)) {} 1162b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1172b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // Here purely to force inlining. 1180795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE ~ScopedObjectAccessAlreadyRunnable() {} 1192b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 120c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe static void DCheckObjIsNotClearedJniWeakGlobal(ObjPtr<mirror::Object> obj) 121c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe REQUIRES_SHARED(Locks::mutator_lock_); 122c15a2f4f45661a7f5f542e406282c146ea1a968dAndreas Gampe 1232b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // Self thread, can be null. 1242b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier Thread* const self_; 12500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // The full JNIEnv. 12600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JNIEnvExt* const env_; 12700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // The full JavaVM. 12800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers JavaVMExt* const vm_; 1292b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier}; 1302b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1312b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// Entry/exit processing for transitions from Native to Runnable (ie within JNI functions). 1322b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// 1332b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// This class performs the necessary thread state switching to and from Runnable and lets us 1342b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// amortize the cost of working out the current thread. Additionally it lets us check (and repair) 1352b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// apps that are using a JNIEnv on the wrong thread. The class also decodes and encodes Objects 1362b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// into jobjects via methods of this class. Performing this here enforces the Runnable thread state 1372b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// for use of Object, thereby inhibiting the Object being modified by GC whilst native or VM code 1382b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// is also manipulating the Object. 1392b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// 1402b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// The destructor transitions back to the previous thread state, typically Native. In this state 1412b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// GC and thread suspension may occur. 1422b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// 1432b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// For annotalysis the subclass ScopedObjectAccess (below) makes it explicit that a shared of 1442b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier// the mutator_lock_ will be acquired on construction. 1452b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartierclass ScopedObjectAccessUnchecked : public ScopedObjectAccessAlreadyRunnable { 1462b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier public: 1470795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(JNIEnv* env) 1480795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_); 1492b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1500795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedObjectAccessUnchecked(Thread* self) 1510795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_); 1522b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 15301b47b046b01ec68696f8ff61b5326cdd3af348eMingyao Yang ALWAYS_INLINE ~ScopedObjectAccessUnchecked() REQUIRES(!Locks::thread_suspend_count_lock_) {} 15401b47b046b01ec68696f8ff61b5326cdd3af348eMingyao Yang 1552b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // Used when we want a scoped JNI thread state but have no thread/JNIEnv. Consequently doesn't 1562b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // change into Runnable or acquire a share on the mutator_lock_. 1572b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier explicit ScopedObjectAccessUnchecked(JavaVM* vm) ALWAYS_INLINE 1582b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier : ScopedObjectAccessAlreadyRunnable(vm), tsc_() {} 1592b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier 1602b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier private: 1612b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // The scoped thread state change makes sure that we are runnable and restores the thread state 1622b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier // in the destructor. 1632b7c4d196c8abe32f4ca633534917da9de53c359Mathieu Chartier const ScopedThreadStateChange tsc_; 16400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccessUnchecked); 16600f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 16700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 16800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers// Annotalysis helping variant of the above. 16900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogersclass ScopedObjectAccess : public ScopedObjectAccessUnchecked { 17000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers public: 1710795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedObjectAccess(JNIEnv* env) 17290443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_) 17390b936ddda63139ff46a6755c3b83ad6e4ab4ac5Andreas Gampe SHARED_LOCK_FUNCTION(Locks::mutator_lock_); 17400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 1750795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedObjectAccess(Thread* self) 17690443477f9a0061581c420775ce3b7eeae7468bcMathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_) 17790b936ddda63139ff46a6755c3b83ad6e4ab4ac5Andreas Gampe SHARED_LOCK_FUNCTION(Locks::mutator_lock_); 17800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 1790795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier // Base class will release share of lock. Invoked after this destructor. 18090b936ddda63139ff46a6755c3b83ad6e4ab4ac5Andreas Gampe ~ScopedObjectAccess() UNLOCK_FUNCTION(Locks::mutator_lock_) ALWAYS_INLINE; 18100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 18200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers private: 18300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // TODO: remove this constructor. It is used by check JNI's ScopedCheck to make it believe that 18400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // routines operating with just a VM are sound, they are not, but when you have just a VM 18500f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers // you cannot call the unsound routines. 1860795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier explicit ScopedObjectAccess(JavaVM* vm) SHARED_LOCK_FUNCTION(Locks::mutator_lock_) 18700f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers : ScopedObjectAccessUnchecked(vm) {} 18800f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 18900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers friend class ScopedCheck; 19000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers DISALLOW_COPY_AND_ASSIGN(ScopedObjectAccess); 19100f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers}; 19200f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 193f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier// Annotalysis helper for going to a suspended state from runnable. 194f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartierclass ScopedThreadSuspension : public ValueObject { 195f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier public: 1960795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE explicit ScopedThreadSuspension(Thread* self, ThreadState suspended_state) 197f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier REQUIRES(!Locks::thread_suspend_count_lock_, !Roles::uninterruptible_) 1980795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier UNLOCK_FUNCTION(Locks::mutator_lock_); 199f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier 2000795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ALWAYS_INLINE ~ScopedThreadSuspension() SHARED_LOCK_FUNCTION(Locks::mutator_lock_); 201f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier 202f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier private: 203f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier Thread* const self_; 204f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier const ThreadState suspended_state_; 205f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier DISALLOW_COPY_AND_ASSIGN(ScopedThreadSuspension); 206f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier}; 207f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier 208f1d666e1b48f8070ef1177fce156c08827f08eb8Mathieu Chartier 20900f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers} // namespace art 21000f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers 211fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif // ART_RUNTIME_SCOPED_THREAD_STATE_CHANGE_H_ 212