1693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers/* 2693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * Copyright (C) 2011 The Android Open Source Project 3693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * 4693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * Licensed under the Apache License, Version 2.0 (the "License"); 5693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * you may not use this file except in compliance with the License. 6693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * You may obtain a copy of the License at 7693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * 8693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * http://www.apache.org/licenses/LICENSE-2.0 9693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * 10693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * Unless required by applicable law or agreed to in writing, software 11693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * distributed under the License is distributed on an "AS IS" BASIS, 12693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * See the License for the specific language governing permissions and 14693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers * limitations under the License. 15693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers */ 16693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 17fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#ifndef ART_RUNTIME_THREAD_INL_H_ 18fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#define ART_RUNTIME_THREAD_INL_H_ 19693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 20693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "thread.h" 21693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 2239b378ca3b4b6dc6da1651b84ee4289cd9bff0f8Andreas Gampe#include "base/aborting.h" 231eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers#include "base/casts.h" 24693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers#include "base/mutex-inl.h" 25d49012909625c3bf87bf51138fe79315ce1b1bdcAndreas Gampe#include "base/time_utils.h" 2668d8b42ddec39ec0174162d90d4abaa004d1983eIan Rogers#include "jni_env_ext.h" 27513061a792b22c417c938d31c19581390709561cAndreas Gampe#include "managed_stack-inl.h" 28c73cb64585f301c8bb3b03a0684f6baead99b7acAndreas Gampe#include "obj_ptr.h" 29b486a98aadc95d80548953410cf23edba62259faAndreas Gampe#include "thread-current-inl.h" 303cf225386e8129dcbe32b289279ecb87ec255318Mathieu Chartier#include "thread_pool.h" 31693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 32693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogersnamespace art { 33693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 341eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers// Quickly access the current thread from a JNIEnv. 351eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogersstatic inline Thread* ThreadForEnv(JNIEnv* env) { 361eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers JNIEnvExt* full_env(down_cast<JNIEnvExt*>(env)); 3755256cb60e11d4fac71affb4b9760a2931a3598dIan Rogers return full_env->GetSelf(); 381eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers} 391eb512d33f94d1dd7ea38263307ba0f7a0dfa653Ian Rogers 407b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogersinline void Thread::AllowThreadSuspension() { 417b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers DCHECK_EQ(Thread::Current(), this); 427b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers if (UNLIKELY(TestAllFlags())) { 437b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers CheckSuspend(); 447b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers } 45a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartier // Invalidate the current thread's object pointers (ObjPtr) to catch possible moving GC bugs due 46a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartier // to missing handles. 473f7f03ce9a102a23961753753b5aa500226b0581Mathieu Chartier PoisonObjectPointers(); 487b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers} 497b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers 507b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogersinline void Thread::CheckSuspend() { 517b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers DCHECK_EQ(Thread::Current(), this); 527b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers for (;;) { 537b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers if (ReadFlag(kCheckpointRequest)) { 547b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers RunCheckpointFunction(); 557b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers } else if (ReadFlag(kSuspendRequest)) { 567b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers FullSuspendCheck(); 573049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi } else if (ReadFlag(kEmptyCheckpointRequest)) { 583049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi RunEmptyCheckpoint(); 593049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi } else { 603049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi break; 613049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi } 623049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi } 633049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi} 643049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi 65a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchiinline void Thread::CheckEmptyCheckpointFromWeakRefAccess(BaseMutex* cond_var_mutex) { 66a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi Thread* self = Thread::Current(); 67a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi DCHECK_EQ(self, this); 68a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi for (;;) { 69a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi if (ReadFlag(kEmptyCheckpointRequest)) { 70a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi RunEmptyCheckpoint(); 71a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi // Check we hold only an expected mutex when accessing weak ref. 72a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi if (kIsDebugBuild) { 73a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi for (int i = kLockLevelCount - 1; i >= 0; --i) { 74a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi BaseMutex* held_mutex = self->GetHeldMutex(static_cast<LockLevel>(i)); 75a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi if (held_mutex != nullptr && 76a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi held_mutex != Locks::mutator_lock_ && 77a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi held_mutex != cond_var_mutex) { 788a433246d0f26f1f8519925ee6fc5cee8fbd0788Hiroshi Yamauchi CHECK(Locks::IsExpectedOnWeakRefAccess(held_mutex)) 79a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi << "Holding unexpected mutex " << held_mutex->GetName() 80a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi << " when accessing weak ref"; 81a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi } 82a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi } 83a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi } 84a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi } else { 85a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi break; 86a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi } 87a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi } 88a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi} 89a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchi 90a222404a5832ab16786931576d52825d08eed3caHiroshi Yamauchiinline void Thread::CheckEmptyCheckpointFromMutex() { 913049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi DCHECK_EQ(Thread::Current(), this); 923049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi for (;;) { 933049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi if (ReadFlag(kEmptyCheckpointRequest)) { 943049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi RunEmptyCheckpoint(); 957b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers } else { 967b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers break; 977b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers } 987b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers } 997b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers} 1007b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers 101c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogersinline ThreadState Thread::SetState(ThreadState new_state) { 102eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Should only be used to change between suspended states. 103eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Cannot use this code to change into or from Runnable as changing to Runnable should 104eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // fail if old_state_and_flags.suspend_request is true and changing from Runnable might 105eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // miss passing an active suspend barrier. 106c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogers DCHECK_NE(new_state, kRunnable); 107ef048f6f968abd59fa7fa89413a6eb85c959beafAndreas Gampe if (kIsDebugBuild && this != Thread::Current()) { 108ef048f6f968abd59fa7fa89413a6eb85c959beafAndreas Gampe std::string name; 109ef048f6f968abd59fa7fa89413a6eb85c959beafAndreas Gampe GetThreadName(name); 110ef048f6f968abd59fa7fa89413a6eb85c959beafAndreas Gampe LOG(FATAL) << "Thread \"" << name << "\"(" << this << " != Thread::Current()=" 111ef048f6f968abd59fa7fa89413a6eb85c959beafAndreas Gampe << Thread::Current() << ") changing state to " << new_state; 112ef048f6f968abd59fa7fa89413a6eb85c959beafAndreas Gampe } 11359cde534aa295bad7de29472b3cce9576d7996a8Chris Dearman union StateAndFlags old_state_and_flags; 114dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers old_state_and_flags.as_int = tls32_.state_and_flags.as_int; 115eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li CHECK_NE(old_state_and_flags.as_struct.state, kRunnable); 116dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers tls32_.state_and_flags.as_struct.state = new_state; 117c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogers return static_cast<ThreadState>(old_state_and_flags.as_struct.state); 118c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogers} 119c0fa3ad44a84b7f658d16a717027bf95abc85db6Ian Rogers 12010b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartierinline bool Thread::IsThreadSuspensionAllowable() const { 12110b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier if (tls32_.no_thread_suspension != 0) { 12210b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier return false; 12310b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier } 12410b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier for (int i = kLockLevelCount - 1; i >= 0; --i) { 12588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light if (i != kMutatorLock && 12688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light i != kUserCodeSuspensionLock && 12788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light GetHeldMutex(static_cast<LockLevel>(i)) != nullptr) { 12810b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier return false; 12910b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier } 13010b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier } 13188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // Thread autoanalysis isn't able to understand that the GetHeldMutex(...) or AssertHeld means we 13288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // have the mutex meaning we need to do this hack. 13388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light auto is_suspending_for_user_code = [this]() NO_THREAD_SAFETY_ANALYSIS { 13488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light return tls32_.user_code_suspend_count != 0; 13588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light }; 13688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light if (GetHeldMutex(kUserCodeSuspensionLock) != nullptr && is_suspending_for_user_code()) { 13788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light return false; 13888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light } 13910b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier return true; 14010b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier} 14110b218d32c0006aab747a53a9867d982cde9c938Mathieu Chartier 142693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogersinline void Thread::AssertThreadSuspensionIsAllowable(bool check_locks) const { 143f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers if (kIsDebugBuild) { 144db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray if (gAborting == 0) { 145db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray CHECK_EQ(0u, tls32_.no_thread_suspension) << tlsPtr_.last_no_thread_suspension_cause; 146db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray } 147f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers if (check_locks) { 148f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers bool bad_mutexes_held = false; 149f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers for (int i = kLockLevelCount - 1; i >= 0; --i) { 15088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // We expect no locks except the mutator_lock_. User code suspension lock is OK as long as 15188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // we aren't going to be held suspended due to SuspendReason::kForUserCode. 15288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light if (i != kMutatorLock && i != kUserCodeSuspensionLock) { 153f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers BaseMutex* held_mutex = GetHeldMutex(static_cast<LockLevel>(i)); 1542cebb24bfc3247d3e9be138a3350106737455918Mathieu Chartier if (held_mutex != nullptr) { 155f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers LOG(ERROR) << "holding \"" << held_mutex->GetName() 156f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers << "\" at point where thread suspension is expected"; 157f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers bad_mutexes_held = true; 158f3d874c60ee3ada19ce26a5c4e532312b6f3a9e9Ian Rogers } 159693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers } 160693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers } 16188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // Make sure that if we hold the user_code_suspension_lock_ we aren't suspending due to 16288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // user_code_suspend_count which would prevent the thread from ever waking up. Thread 16388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // autoanalysis isn't able to understand that the GetHeldMutex(...) or AssertHeld means we 16488fd720b6799184c8ad61e766a6d37af33ed30efAlex Light // have the mutex meaning we need to do this hack. 16588fd720b6799184c8ad61e766a6d37af33ed30efAlex Light auto is_suspending_for_user_code = [this]() NO_THREAD_SAFETY_ANALYSIS { 16688fd720b6799184c8ad61e766a6d37af33ed30efAlex Light return tls32_.user_code_suspend_count != 0; 16788fd720b6799184c8ad61e766a6d37af33ed30efAlex Light }; 16888fd720b6799184c8ad61e766a6d37af33ed30efAlex Light if (GetHeldMutex(kUserCodeSuspensionLock) != nullptr && is_suspending_for_user_code()) { 16988fd720b6799184c8ad61e766a6d37af33ed30efAlex Light LOG(ERROR) << "suspending due to user-code while holding \"" 17088fd720b6799184c8ad61e766a6d37af33ed30efAlex Light << Locks::user_code_suspension_lock_->GetName() << "\"! Thread would never " 17188fd720b6799184c8ad61e766a6d37af33ed30efAlex Light << "wake up."; 17288fd720b6799184c8ad61e766a6d37af33ed30efAlex Light bad_mutexes_held = true; 17388fd720b6799184c8ad61e766a6d37af33ed30efAlex Light } 174db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray if (gAborting == 0) { 175db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray CHECK(!bad_mutexes_held); 176db978719dbcb73fc6acfd193561445c4462786b8Nicolas Geoffray } 177693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers } 178693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers } 179693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers} 180693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 1818ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartierinline void Thread::TransitionToSuspendedAndRunCheckpoints(ThreadState new_state) { 182693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_NE(new_state, kRunnable); 183693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_EQ(GetState(), kRunnable); 184693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers union StateAndFlags old_state_and_flags; 185693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers union StateAndFlags new_state_and_flags; 1860f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison while (true) { 187dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers old_state_and_flags.as_int = tls32_.state_and_flags.as_int; 188d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers if (UNLIKELY((old_state_and_flags.as_struct.flags & kCheckpointRequest) != 0)) { 189d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers RunCheckpointFunction(); 190d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers continue; 191d9c4fc94fa618617f94e1de9af5f034549100753Ian Rogers } 1923049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi if (UNLIKELY((old_state_and_flags.as_struct.flags & kEmptyCheckpointRequest) != 0)) { 1933049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi RunEmptyCheckpoint(); 1943049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi continue; 1953049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi } 1960f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison // Change the state but keep the current flags (kCheckpointRequest is clear). 1970f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison DCHECK_EQ((old_state_and_flags.as_struct.flags & kCheckpointRequest), 0); 1983049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi DCHECK_EQ((old_state_and_flags.as_struct.flags & kEmptyCheckpointRequest), 0); 1990f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison new_state_and_flags.as_struct.flags = old_state_and_flags.as_struct.flags; 200693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers new_state_and_flags.as_struct.state = new_state; 201b8e087e0dfd619df90cbb56534478a60bc859ebfIan Rogers 202eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // CAS the value with a memory ordering. 203b8e087e0dfd619df90cbb56534478a60bc859ebfIan Rogers bool done = 2044557b3858a66aa20e42bce937e1f0620aad880a2Orion Hodson tls32_.state_and_flags.as_atomic_int.CompareAndSetWeakRelease(old_state_and_flags.as_int, 205b8e087e0dfd619df90cbb56534478a60bc859ebfIan Rogers new_state_and_flags.as_int); 206b8e087e0dfd619df90cbb56534478a60bc859ebfIan Rogers if (LIKELY(done)) { 2070f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison break; 2080f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison } 2090f5f6bbc3a0bb125875f28ad61584001989a7f10Dave Allison } 2108ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier} 211eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li 2128ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartierinline void Thread::PassActiveSuspendBarriers() { 213eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li while (true) { 214eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li uint16_t current_flags = tls32_.state_and_flags.as_struct.flags; 2153049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi if (LIKELY((current_flags & 2163049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi (kCheckpointRequest | kEmptyCheckpointRequest | kActiveSuspendBarrier)) == 0)) { 217eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li break; 218eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } else if ((current_flags & kActiveSuspendBarrier) != 0) { 219eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li PassActiveSuspendBarriers(this); 220eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } else { 221eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Impossible 2228ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier LOG(FATAL) << "Fatal, thread transitioned into suspended without running the checkpoint"; 223eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } 224eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } 225693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers} 226693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 2278ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartierinline void Thread::TransitionFromRunnableToSuspended(ThreadState new_state) { 2288ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier AssertThreadSuspensionIsAllowable(); 2293398c7874e002beaa6c2b2fadf183e7d1ddad23aMathieu Chartier PoisonObjectPointersIfDebug(); 2308ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier DCHECK_EQ(this, Thread::Current()); 2318ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier // Change to non-runnable state, thereby appearing suspended to the system. 2328ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier TransitionToSuspendedAndRunCheckpoints(new_state); 2338ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier // Mark the release of the share of the mutator_lock_. 2348ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier Locks::mutator_lock_->TransitionFromRunnableToSuspended(this); 2358ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier // Once suspended - check the active suspend barrier flag 2368ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier PassActiveSuspendBarriers(); 2378ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier} 2388ac9c91cfa2408cf8d27bcf12785a60923aab775Mathieu Chartier 239693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogersinline ThreadState Thread::TransitionFromSuspendedToRunnable() { 24059cde534aa295bad7de29472b3cce9576d7996a8Chris Dearman union StateAndFlags old_state_and_flags; 241dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers old_state_and_flags.as_int = tls32_.state_and_flags.as_int; 242693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers int16_t old_state = old_state_and_flags.as_struct.state; 243693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_NE(static_cast<ThreadState>(old_state), kRunnable); 244693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers do { 245693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers Locks::mutator_lock_->AssertNotHeld(this); // Otherwise we starve GC.. 246dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers old_state_and_flags.as_int = tls32_.state_and_flags.as_int; 247693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_EQ(old_state_and_flags.as_struct.state, old_state); 248eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li if (LIKELY(old_state_and_flags.as_struct.flags == 0)) { 249eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Optimize for the return from native code case - this is the fast path. 250eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Atomically change from suspended to runnable if no suspend request pending. 251eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li union StateAndFlags new_state_and_flags; 252eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li new_state_and_flags.as_int = old_state_and_flags.as_int; 253eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li new_state_and_flags.as_struct.state = kRunnable; 254eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // CAS the value with a memory barrier. 2554557b3858a66aa20e42bce937e1f0620aad880a2Orion Hodson if (LIKELY(tls32_.state_and_flags.as_atomic_int.CompareAndSetWeakAcquire( 256eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li old_state_and_flags.as_int, 257eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li new_state_and_flags.as_int))) { 258eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Mark the acquisition of a share of the mutator_lock_. 259eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li Locks::mutator_lock_->TransitionFromSuspendedToRunnable(this); 260eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li break; 261eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } 262eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } else if ((old_state_and_flags.as_struct.flags & kActiveSuspendBarrier) != 0) { 263eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li PassActiveSuspendBarriers(this); 2643049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi } else if ((old_state_and_flags.as_struct.flags & 2653049324f4ef71b5d7a3de49bd77c75f07dbf8f3aHiroshi Yamauchi (kCheckpointRequest | kEmptyCheckpointRequest)) != 0) { 266eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Impossible 267dabdccc816309ff29b39d13696c58c8543450739Mathieu Chartier LOG(FATAL) << "Transitioning to runnable with checkpoint flag, " 268dabdccc816309ff29b39d13696c58c8543450739Mathieu Chartier << " flags=" << old_state_and_flags.as_struct.flags 269dabdccc816309ff29b39d13696c58c8543450739Mathieu Chartier << " state=" << old_state_and_flags.as_struct.state; 270eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } else if ((old_state_and_flags.as_struct.flags & kSuspendRequest) != 0) { 271693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers // Wait while our suspend count is non-zero. 2729f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray 2739f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray // We pass null to the MutexLock as we may be in a situation where the 2749f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray // runtime is shutting down. Guarding ourselves from that situation 2759f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray // requires to take the shutdown lock, which is undesirable here. 2769f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray Thread* thread_to_pass = nullptr; 2779f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray if (kIsDebugBuild && !IsDaemon()) { 2789f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray // We know we can make our debug locking checks on non-daemon threads, 2799f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray // so re-enable them on debug builds. 2809f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray thread_to_pass = this; 2819f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray } 2829f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray MutexLock mu(thread_to_pass, *Locks::thread_suspend_count_lock_); 283ee23582af60b36f982de2ad16f485a61f35ae817Hiroshi Yamauchi ScopedTransitioningToRunnable scoped_transitioning_to_runnable(this); 284dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers old_state_and_flags.as_int = tls32_.state_and_flags.as_int; 285693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_EQ(old_state_and_flags.as_struct.state, old_state); 286693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers while ((old_state_and_flags.as_struct.flags & kSuspendRequest) != 0) { 287693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers // Re-check when Thread::resume_cond_ is notified. 2889f5f8ac136d88de546f70f0ac2438610150ff401Nicolas Geoffray Thread::resume_cond_->Wait(thread_to_pass); 289dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers old_state_and_flags.as_int = tls32_.state_and_flags.as_int; 290693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_EQ(old_state_and_flags.as_struct.state, old_state); 291693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers } 292693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers DCHECK_EQ(GetSuspendCount(), 0); 293693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers } 294719d1a33f6569864f529e5a3fff59e7bca97aad0Ian Rogers } while (true); 295eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li // Run the flip function, if set. 296eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li Closure* flip_func = GetFlipFunction(); 297eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li if (flip_func != nullptr) { 298eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li flip_func->Run(this); 299eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li } 300eac4424b3420c280f97ff2f815b5dedd8dac9801Yu Li return static_cast<ThreadState>(old_state); 301693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers} 302693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 303e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartierinline mirror::Object* Thread::AllocTlab(size_t bytes) { 304e6da9af8dfe0a3e3fbc2be700554f6478380e7b9Mathieu Chartier DCHECK_GE(TlabSize(), bytes); 305dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ++tlsPtr_.thread_local_objects; 306dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers mirror::Object* ret = reinterpret_cast<mirror::Object*>(tlsPtr_.thread_local_pos); 307dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers tlsPtr_.thread_local_pos += bytes; 308692fafd9778141fa6ef0048c9569abd7ee0253bfMathieu Chartier return ret; 309692fafd9778141fa6ef0048c9569abd7ee0253bfMathieu Chartier} 310692fafd9778141fa6ef0048c9569abd7ee0253bfMathieu Chartier 311f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchiinline bool Thread::PushOnThreadLocalAllocationStack(mirror::Object* obj) { 312dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers DCHECK_LE(tlsPtr_.thread_local_alloc_stack_top, tlsPtr_.thread_local_alloc_stack_end); 313dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers if (tlsPtr_.thread_local_alloc_stack_top < tlsPtr_.thread_local_alloc_stack_end) { 314f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi // There's room. 31513735955f39b3b304c37d2b2840663c131262c18Ian Rogers DCHECK_LE(reinterpret_cast<uint8_t*>(tlsPtr_.thread_local_alloc_stack_top) + 316cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartier sizeof(StackReference<mirror::Object>), 31713735955f39b3b304c37d2b2840663c131262c18Ian Rogers reinterpret_cast<uint8_t*>(tlsPtr_.thread_local_alloc_stack_end)); 318cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartier DCHECK(tlsPtr_.thread_local_alloc_stack_top->AsMirrorPtr() == nullptr); 319cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartier tlsPtr_.thread_local_alloc_stack_top->Assign(obj); 320dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers ++tlsPtr_.thread_local_alloc_stack_top; 321f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi return true; 322f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi } 323f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi return false; 324f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi} 325f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi 326cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartierinline void Thread::SetThreadLocalAllocationStack(StackReference<mirror::Object>* start, 327cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartier StackReference<mirror::Object>* end) { 328f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi DCHECK(Thread::Current() == this) << "Should be called by self"; 329f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi DCHECK(start != nullptr); 330f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi DCHECK(end != nullptr); 331cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartier DCHECK_ALIGNED(start, sizeof(StackReference<mirror::Object>)); 332cb535da36915f9d10bec3880b46f1de1f7a69f22Mathieu Chartier DCHECK_ALIGNED(end, sizeof(StackReference<mirror::Object>)); 333f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi DCHECK_LT(start, end); 334dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers tlsPtr_.thread_local_alloc_stack_end = end; 335dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers tlsPtr_.thread_local_alloc_stack_top = start; 336f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi} 337f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi 338f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchiinline void Thread::RevokeThreadLocalAllocationStack() { 339f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi if (kIsDebugBuild) { 340f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi // Note: self is not necessarily equal to this thread since thread may be suspended. 341f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi Thread* self = Thread::Current(); 342f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi DCHECK(this == self || IsSuspended() || GetState() == kWaitingPerformingGc) 343f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi << GetState() << " thread " << this << " self " << self; 344f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi } 345dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers tlsPtr_.thread_local_alloc_stack_end = nullptr; 346dd7624d2b9e599d57762d12031b10b89defc9807Ian Rogers tlsPtr_.thread_local_alloc_stack_top = nullptr; 347f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi} 348f5b0e20b5b31f5f5465784adcf2a204dcd69c7fdHiroshi Yamauchi 349a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartierinline void Thread::PoisonObjectPointersIfDebug() { 350c73cb64585f301c8bb3b03a0684f6baead99b7acAndreas Gampe if (kObjPtrPoisoning) { 351a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartier Thread::Current()->PoisonObjectPointers(); 352a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartier } 353a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartier} 354a59d9b228b1eda3bf71a81b6201ec64e26086c23Mathieu Chartier 35502e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchiinline bool Thread::ModifySuspendCount(Thread* self, 35602e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi int delta, 35702e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi AtomicInteger* suspend_barrier, 35846f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light SuspendReason reason) { 35902e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi if (delta > 0 && ((kUseReadBarrier && this != self) || suspend_barrier != nullptr)) { 36002e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // When delta > 0 (requesting a suspend), ModifySuspendCountInternal() may fail either if 36102e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // active_suspend_barriers is full or we are in the middle of a thread flip. Retry in a loop. 36202e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi while (true) { 36346f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light if (LIKELY(ModifySuspendCountInternal(self, delta, suspend_barrier, reason))) { 36402e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi return true; 36502e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi } else { 36602e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // Failure means the list of active_suspend_barriers is full or we are in the middle of a 36702e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // thread flip, we should release the thread_suspend_count_lock_ (to avoid deadlock) and 36802e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // wait till the target thread has executed or Thread::PassActiveSuspendBarriers() or the 36902e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // flip function. Note that we could not simply wait for the thread to change to a suspended 37002e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // state, because it might need to run checkpoint function before the state change or 37102e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // resumes from the resume_cond_, which also needs thread_suspend_count_lock_. 37202e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // 37302e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // The list of active_suspend_barriers is very unlikely to be full since more than 37402e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // kMaxSuspendBarriers threads need to execute SuspendAllInternal() simultaneously, and 37502e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi // target thread stays in kRunnable in the mean time. 37602e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi Locks::thread_suspend_count_lock_->ExclusiveUnlock(self); 37702e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi NanoSleep(100000); 37802e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi Locks::thread_suspend_count_lock_->ExclusiveLock(self); 37902e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi } 38002e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi } 38102e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi } else { 38246f9340f2a055a8fdfebbfbb739c697c20d83e7cAlex Light return ModifySuspendCountInternal(self, delta, suspend_barrier, reason); 38302e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi } 38402e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi} 38502e7f1a46d8dbb277d045182cd1fa4b058d55162Hiroshi Yamauchi 386513061a792b22c417c938d31c19581390709561cAndreas Gampeinline ShadowFrame* Thread::PushShadowFrame(ShadowFrame* new_top_frame) { 387513061a792b22c417c938d31c19581390709561cAndreas Gampe return tlsPtr_.managed_stack.PushShadowFrame(new_top_frame); 388513061a792b22c417c938d31c19581390709561cAndreas Gampe} 389513061a792b22c417c938d31c19581390709561cAndreas Gampe 390513061a792b22c417c938d31c19581390709561cAndreas Gampeinline ShadowFrame* Thread::PopShadowFrame() { 391513061a792b22c417c938d31c19581390709561cAndreas Gampe return tlsPtr_.managed_stack.PopShadowFrame(); 392513061a792b22c417c938d31c19581390709561cAndreas Gampe} 393513061a792b22c417c938d31c19581390709561cAndreas Gampe 394693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers} // namespace art 395693ff61274cd2c9b8eb7e68c370f84a911b8ca52Ian Rogers 396fc0e3219edc9a5bf81b166e82fd5db2796eb6a0dBrian Carlstrom#endif // ART_RUNTIME_THREAD_INL_H_ 397