thread.h revision a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2
10e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved. 20e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 30e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#ifndef ART_SRC_THREAD_H_ 40e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#define ART_SRC_THREAD_H_ 50e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 6b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <pthread.h> 7b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <list> 8b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 9578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "globals.h" 10578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "jni_internal.h" 11578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "logging.h" 12578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "macros.h" 13578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "offsets.h" 14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 150e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 16b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include "jni.h" 17b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 180e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapironamespace art { 190e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 20a40f9bc48afe3a9d38be2fa298fece13ed82ba28Brian Carlstromclass Method; 210e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Object; 22b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass Runtime; 23b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass StackHandleBlock; 240e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread; 25b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList; 260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Mutex { 280e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public: 290e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro virtual ~Mutex() {} 300e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 31b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Lock(); 320e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 33b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro bool TryLock(); 340e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 35b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Unlock(); 360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 370e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro const char* GetName() { return name_; } 380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Thread* GetOwner() { return owner_; } 400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 41b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro static Mutex* Create(const char* name); 42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public: // TODO: protected 440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro explicit Mutex(const char* name) : name_(name), owner_(NULL) {} 450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro void SetOwner(Thread* thread) { owner_ = thread; } 470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private: 490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro const char* name_; 500e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 510e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Thread* owner_; 520e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 53b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro pthread_mutex_t lock_impl_; 54b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 550e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro DISALLOW_COPY_AND_ASSIGN(Mutex); 560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}; 570e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 580e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass MutexLock { 590e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public: 600e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro explicit MutexLock(Mutex *mu) : mu_(mu) { 610e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro mu_->Lock(); 620e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 630e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro ~MutexLock() { mu_->Unlock(); } 640e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private: 650e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Mutex* const mu_; 660e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro DISALLOW_COPY_AND_ASSIGN(MutexLock); 670e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}; 680e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 69b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// Stack handle blocks are allocated within the bridge frame between managed 70b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers// and native code. 71b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersclass StackHandleBlock { 72b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers public: 73b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Number of references contained within this SHB 74b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers size_t NumberOfReferences() { 75b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return number_of_references_; 76b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 77b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 78b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Link to previous SHB or NULL 79b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers StackHandleBlock* Link() { 80b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return link_; 81b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 82b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 83b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Offset of length within SHB, used by generated code 84b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers static size_t NumberOfReferencesOffset() { 85b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return OFFSETOF_MEMBER(StackHandleBlock, number_of_references_); 86b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 87b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Offset of link within SHB, used by generated code 89b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers static size_t LinkOffset() { 90b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return OFFSETOF_MEMBER(StackHandleBlock, link_); 91b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 92b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 93b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers private: 94b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers StackHandleBlock() {} 95b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 96b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers size_t number_of_references_; 97b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers StackHandleBlock* link_; 98b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 99b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers DISALLOW_COPY_AND_ASSIGN(StackHandleBlock); 100b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 101b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 1020e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiroclass Thread { 1030e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro public: 104b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro enum State { 105b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kUnknown = -1, 106b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kNew, 107b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kRunnable, 108b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kBlocked, 109b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kWaiting, 110b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kTimedWaiting, 111b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers kNative, 112b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro kTerminated, 113b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro }; 114b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 11561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static const size_t kDefaultStackSize = 64 * KB; 11661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 11761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro // Creates a new thread. 11861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static Thread* Create(size_t stack_size); 11961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 12061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro // Creates a new thread from the calling thread. 12161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static Thread* Attach(); 122b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 123b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro static Thread* Current() { 124d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro void* thread = pthread_getspecific(Thread::pthread_key_self_); 125d0e7e777c412071a911dd2c008b20b7d879fd392Carl Shapiro return reinterpret_cast<Thread*>(thread); 1260e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 1270e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 128b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro uint32_t GetId() const { 129b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return id_; 130b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 131b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 132b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro pid_t GetNativeId() const { 133b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return native_id_; 1340e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 1350e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1360e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro bool IsExceptionPending() const { 137b20a554613609dc372073d2ebd9fbc3925a429f5Elliott Hughes return exception_ != NULL; 1380e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 1390e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1400e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Object* GetException() const { 1410e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro return exception_; 1420e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 1430e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 1440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro void SetException(Object* new_exception) { 1450e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro CHECK(new_exception != NULL); 1460e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro // TODO: CHECK(exception_ == NULL); 1470e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro exception_ = new_exception; // TODO 1480e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 1490e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 150a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes void ThrowNewException(const char* exception_class_name, const char* fmt, ...) 151a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes __attribute__ ((format(printf, 3, 4))); 152a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 1530e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro void ClearException() { 1540e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro exception_ = NULL; 1550e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro } 1560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 15745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Offset of exception within Thread, used by generated code 15845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers static ThreadOffset ExceptionOffset() { 15945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_)); 16045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 16145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 162b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void SetName(const char* name); 163b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 164b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Suspend(); 165b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 166b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro bool IsSuspended(); 167b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 168b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Resume(); 169b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 170b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro static bool Init(); 171b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 17269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro Runtime* GetRuntime() const { 17369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro return runtime_; 17469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro } 17569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro 176330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes State GetState() const { 177b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return state_; 178b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 179b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 180b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void SetState(State new_state) { 181b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro state_ = new_state; 182b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 183b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 18445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers static ThreadOffset SuspendCountOffset() { 18545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_)); 18645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 18745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 188b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Offset of state within Thread, used by generated code 189b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers static ThreadOffset StateOffset() { 190b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, state_)); 191b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 192b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 193b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // JNI methods 19440ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes JNIEnv* GetJniEnv() const { 195b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return jni_env_; 196b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 197b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 198b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Offset of JNI environment within Thread, used by generated code 199b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers static ThreadOffset JniEnvOffset() { 200b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_)); 201b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 202b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 20345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Offset of top of managed stack address, used by generated code 20445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers static ThreadOffset TopOfManagedStackOffset() { 20545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_)); 20645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 20745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 208b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Offset of top stack handle block within Thread, used by generated code 209b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers static ThreadOffset TopShbOffset() { 210b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_)); 211b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 212b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 213b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Number of references allocated in StackHandleBlocks on this thread 214b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers size_t NumShbHandles() { 215b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers size_t count = 0; 216b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) { 217b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers count += cur->NumberOfReferences(); 218b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 219b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return count; 220b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 221b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 22245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Offset of exception_entry_point_ within Thread, used by generated code 22345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers static ThreadOffset ExceptionEntryPointOffset() { 22445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_)); 22545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 22645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 22745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void RegisterExceptionEntryPoint(void (*handler)(Method**)) { 22845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers exception_entry_point_ = handler; 22945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 23045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 23145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Offset of suspend_count_entry_point_ within Thread, used by generated code 23245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers static ThreadOffset SuspendCountEntryPointOffset() { 23345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_)); 23445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 23545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 23645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) { 23745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers suspend_count_entry_point_ = handler; 23845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers } 23945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 24045a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Increasing the suspend count, will cause the thread to run to safepoint 24145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void IncrementSuspendCount() { suspend_count_++; } 24245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void DecrementSuspendCount() { suspend_count_--; } 24345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 2440e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro private: 24540ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes Thread() 246330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes : id_(1234), 247330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes top_shb_(NULL), 248330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes jni_env_(NULL), 249330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes exception_(NULL), 250330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes suspend_count_(0) { 251df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers } 25269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro 253df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers ~Thread() { 254df20fe0c097073f75f22d16e72fd3636a31d3ca1Ian Rogers delete jni_env_; 255b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 2560e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 257b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers void InitCpu(); 258b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 25969759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // Managed thread id. 26069759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro uint32_t id_; 261b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 26245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Top of the managed stack, written out prior to the state transition from 26345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // kRunnable to kNative. Uses include to give the starting point for scanning 26445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // a managed stack when a thread is in native code. 26545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void* top_of_managed_stack_; 26645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 267b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Top of linked list of stack handle blocks or NULL for none 268b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers StackHandleBlock* top_shb_; 269b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 270b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers // Every thread may have an associated JNI environment 27140ef99eb9dd91c2fa549f40973964529c927bb3cElliott Hughes JNIEnv* jni_env_; 272b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 273b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro State state_; 274b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 27569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // Native (kernel) thread id. 276b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro pid_t native_id_; 277b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 27869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // Native thread handle. 27961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro pthread_t handle_; 2800e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 28169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // Initialized to "this". On certain architectures (such as x86) reading 28269759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // off of Thread::Current is easy but getting the address of Thread::Current 28369759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // is hard. This field can be read off of Thread::Current to give the address. 28469759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro Thread* self_; 28569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro 28669759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro Runtime* runtime_; 28769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro 28869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // The pending exception or NULL. 2890e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro Object* exception_; 2900e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 29145a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // A non-zero value is used to tell the current thread to enter a safe point 29245a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // at the next poll. 29345a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers int suspend_count_; 29445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 29569759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // The inclusive base of the control stack. 29661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro byte* stack_base_; 29769759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro 29869759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // The exclusive limit of the control stack. 29961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro byte* stack_limit_; 30061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 30169759eaa6fd4386f1e6d8748052ad221087b3476Carl Shapiro // TLS key used to retrieve the VM thread object. 302b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro static pthread_key_t pthread_key_self_; 303b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 30445a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Entry point called when exception_ is set 30545a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void (*exception_entry_point_)(Method** frame); 30645a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 30745a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers // Entry point called when suspend_count_ is non-zero 30845a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers void (*suspend_count_entry_point_)(Method** frame); 30945a76cb99104a222d6a9bd768a084893dcb7cf30Ian Rogers 3100e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro DISALLOW_COPY_AND_ASSIGN(Thread); 3110e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro}; 312330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread); 313b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state); 3140e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 315b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadList { 316b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public: 31761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static const int kMaxId = 0xFFFF; 31861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static const int kInvalidId = 0; 31961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static const int kMainId = 1; 32061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 32161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro static ThreadList* Create(); 322b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 32361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro ~ThreadList(); 324b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 325b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Register(Thread* thread); 326b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 327b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Unregister(Thread* thread); 328b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 329b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Lock() { 330b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_->Lock(); 331b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 332b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 333b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro void Unlock() { 334b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_->Unlock(); 335b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro }; 336b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 337b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private: 338b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro ThreadList(); 339b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 340b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro std::list<Thread*> list_; 341b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 342b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro Mutex* lock_; 343b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 344b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro DISALLOW_COPY_AND_ASSIGN(ThreadList); 345b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}; 346b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 347b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiroclass ThreadListLock { 348b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro public: 349b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro ThreadListLock(ThreadList* thread_list, Thread* current_thread) 350b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro : thread_list_(thread_list) { 351b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (current_thread == NULL) { // try to get it from TLS 352b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro current_thread = Thread::Current(); 353b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 354b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro Thread::State old_state; 355b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (current_thread != NULL) { 356b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro old_state = current_thread->GetState(); 357b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro current_thread->SetState(Thread::kWaiting); // TODO: VMWAIT 358b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } else { 359b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // happens during VM shutdown 360b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro old_state = Thread::kUnknown; // TODO: something else 361b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 362b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro thread_list_->Lock(); 363b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (current_thread != NULL) { 364b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro current_thread->SetState(old_state); 365b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 366b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 367b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 368b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro ~ThreadListLock() { 369b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro thread_list_->Unlock(); 370b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 371b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 372b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro private: 373b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro ThreadList* thread_list_; 374b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 375b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro DISALLOW_COPY_AND_ASSIGN(ThreadListLock); 376b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro}; 377b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 3780e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro} // namespace art 3790e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro 3800e5d75d5ca2b8a44fab0c862276a466cbab39859Carl Shapiro#endif // ART_SRC_THREAD_H_ 381