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