thread.cc revision 55df06be4369f5d8ab5eb61a5d22809255171036
1b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro// Copyright 2011 Google Inc. All Rights Reserved. 2b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 3578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "thread.h" 4b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 5b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <pthread.h> 6b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers#include <sys/mman.h> 7b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <algorithm> 8eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes#include <cerrno> 9b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro#include <list> 10b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 11a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "class_linker.h" 12408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers#include "heap.h" 13c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h" 14a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "object.h" 15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 16578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "utils.h" 175433072f589b61413e042eddf76e8190a048f71dbuzbee#include "runtime_support.h" 18b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 19b557353b22c728eecbd1c68593b482622c7782a8Carl Shapironamespace art { 20b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 21e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes/* desktop Linux needs a little help with gettid() */ 22e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#if !defined(HAVE_ANDROID_OS) 23e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#define __KERNEL__ 24e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes# include <linux/unistd.h> 25e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#ifdef _syscall0 26e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes_syscall0(pid_t, gettid) 27e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#else 28e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughespid_t gettid() { return syscall(__NR_gettid);} 29e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#endif 30e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#undef __KERNEL__ 31e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes#endif 32e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 33b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiropthread_key_t Thread::pthread_key_self_; 34b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 353ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid Thread::InitFunctionPointers() { 365433072f589b61413e042eddf76e8190a048f71dbuzbee#if defined(__arm__) 375433072f589b61413e042eddf76e8190a048f71dbuzbee pShlLong = art_shl_long; 385433072f589b61413e042eddf76e8190a048f71dbuzbee pShrLong = art_shr_long; 395433072f589b61413e042eddf76e8190a048f71dbuzbee pUshrLong = art_ushr_long; 405433072f589b61413e042eddf76e8190a048f71dbuzbee#endif 413ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee pArtAllocArrayByClass = Array::Alloc; 423ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee pMemcpy = memcpy; 433ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee#if 0 443ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee//void* (Thread::*pMemcpy)(void*, const void*, size_t) /* = memcpy*/ ; 453ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pI2f)(int); 463ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pF2iz)(float); 473ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pD2f)(double); 483ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pF2d)(float); 493ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pI2d)(int); 503ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pD2iz)(double); 513ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pL2f)(long); 523ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pL2d)(long); 533ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeelong long (Thread::*pArtF2l)(float); 543ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeelong long (Thread::*pArtD2l)(double); 553ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFadd)(float, float); 563ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFsub)(float, float); 573ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFdiv)(float, float); 583ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFmul)(float, float); 593ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeefloat (Thread::*pFmodf)(float, float); 603ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDadd)(double, double); 613ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDsub)(double, double); 623ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDdiv)(double, double); 633ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pDmul)(double, double); 643ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeedouble (Thread::*pFmod)(double, double); 653ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pIdivmod)(int, int); 663ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pIdiv)(int, int); 673ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeelong long (Thread::*pLdivmod)(long long, long long); 683ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtUnlockObject)(struct Thread*, struct Object*); 693ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtCanPutArrayElementNoThrow)(const struct ClassObject*, 703ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee const struct ClassObject*); 713ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pArtInstanceofNonTrivialNoThrow) 723ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee (const struct ClassObject*, const struct ClassObject*); 733ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeeint (Thread::*pArtInstanceofNonTrivial) (const struct ClassObject*, 743ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee const struct ClassObject*); 753ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeestruct Method* (Thread::*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t, 763ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee const struct Method*, struct DvmDex*); 773ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*); 783ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid (Thread::*pArtLockObjectNoThrow)(struct Thread*, struct Object*); 793ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeestruct Object* (Thread::*pArtAllocObjectNoThrow)(struct ClassObject*, int); 803ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeevoid (Thread::*pArtThrowException)(struct Thread*, struct Object*); 813ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbeebool (Thread::*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*); 823ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee#endif 833ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee} 843ea4ec5629613013ad9b0d7a69abdb94491ac46fbuzbee 85b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroMutex* Mutex::Create(const char* name) { 86b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro Mutex* mu = new Mutex(name); 87b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_init(&mu->lock_impl_, NULL); 88b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers CHECK_EQ(0, result); 89b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return mu; 90b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 91b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 92b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Lock() { 93b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_lock(&lock_impl_); 94b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 95b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro SetOwner(Thread::Current()); 96b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 97b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 98b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirobool Mutex::TryLock() { 99b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_lock(&lock_impl_); 100b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (result == EBUSY) { 101b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 102b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } else { 103b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 104b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro SetOwner(Thread::Current()); 105b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return true; 106b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 107b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 108b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 109b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Unlock() { 110b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK(GetOwner() == Thread::Current()); 111b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_unlock(&lock_impl_); 112b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 113f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes SetOwner(NULL); 114b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 115b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 1161a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid Frame::Next() { 1171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 118d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetFrameSizeInBytes(); 1191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao sp_ = reinterpret_cast<const Method**>(next_sp); 1201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 1211a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 12255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liaouintptr_t Frame::GetPC() const { 1231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* pc_addr = reinterpret_cast<byte*>(sp_) + 124d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetReturnPcOffsetInBytes(); 12555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao return *reinterpret_cast<uintptr_t*>(pc_addr); 1261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 1271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 1281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaoconst Method* Frame::NextMethod() const { 1291a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 130d11af152ff36b06883364d9728735ed8162ee306Shih-wei Liao GetMethod()->GetFrameSizeInBytes(); 1311a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return reinterpret_cast<const Method*>(next_sp); 1321a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 1331a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 13461e019d291583029c01b61b93bea750f2b663c37Carl Shapirovoid* ThreadStart(void *arg) { 13553b61314370c49354ed6f8d616d6a9a182410fc1Elliott Hughes UNIMPLEMENTED(FATAL); 136b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return NULL; 137b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 138b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 139b765be0d656c3073402693aeaf64e95a0e49f218Brian CarlstromThread* Thread::Create(const Runtime* runtime) { 140b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom size_t stack_size = runtime->GetStackSize(); 14161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 14261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro Thread* new_thread = new Thread; 143176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers new_thread->InitCpu(); 14461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 14561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro pthread_attr_t attr; 146e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_init(&attr); 147e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 148e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_init failed"; 149e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 15061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 151e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 152e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 153e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed"; 154e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 15561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 156e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_setstacksize(&attr, stack_size); 157e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 158e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_setstacksize(" << stack_size << ") failed"; 159e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 16061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 161e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_create(&new_thread->handle_, &attr, ThreadStart, new_thread); 162e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 163e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_create failed"; 164e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 165e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 166e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes errno = pthread_attr_destroy(&attr); 167e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes if (errno != 0) { 168e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes PLOG(FATAL) << "pthread_attr_destroy failed"; 169e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes } 17061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 17161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return new_thread; 17261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 17361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 174515a5bc89282d6f910cae4d5852bb77124a47825Elliott HughesThread* Thread::Attach(const Runtime* runtime) { 17561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro Thread* thread = new Thread; 176176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers thread->InitCpu(); 17761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 17861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->handle_ = pthread_self(); 17961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 18061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->state_ = kRunnable; 18161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 182a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes errno = pthread_setspecific(Thread::pthread_key_self_, thread); 183a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes if (errno != 0) { 184c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(FATAL) << "pthread_setspecific failed"; 185a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes } 186a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes 1877577075b147fd8fa37ca41e7a32d1124676776ceElliott Hughes thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM()); 188330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 18961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return thread; 19061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 19161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 192e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughespid_t Thread::GetTid() const { 193e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes return gettid(); 194e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes} 195e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes 196b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirostatic void ThreadExitCheck(void* arg) { 197b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro LG << "Thread exit check"; 198b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 199b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 200c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesbool Thread::Startup() { 201b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Allocate a TLS slot. 202c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck); 203c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (errno != 0) { 204eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes PLOG(WARNING) << "pthread_key_create failed"; 205b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 206b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 207b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 208b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Double-check the TLS slot allocation. 209b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (pthread_getspecific(pthread_key_self_) != NULL) { 210eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes LOG(WARNING) << "newly-created pthread TLS slot is not NULL"; 211b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 212b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 213b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 214b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // TODO: initialize other locks and condition variables 215b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 216b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return true; 217b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 218b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 219c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesvoid Thread::Shutdown() { 220c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes errno = pthread_key_delete(Thread::pthread_key_self_); 221c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (errno != 0) { 222c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes PLOG(WARNING) << "pthread_key_delete failed"; 223c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 224c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 225c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 226c1674ed06662420213441ff2b818f2f71f9098dcElliott HughesThread::~Thread() { 227c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes delete jni_env_; 228c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 229c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 230408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogerssize_t Thread::NumSirtReferences() { 231a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t count = 0; 232408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { 233a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers count += cur->NumberOfReferences(); 234a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 235a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return count; 236a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 237a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 238408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogersbool Thread::SirtContains(jobject obj) { 239408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object** sirt_entry = reinterpret_cast<Object**>(obj); 240408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) { 241a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t num_refs = cur->NumberOfReferences(); 242408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // A SIRT should always have a jobject/jclass as a native method is passed 243408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // in a this pointer or a class 244408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers DCHECK_GT(num_refs, 0u); 245408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if ((&cur->References()[0] >= sirt_entry) && 246408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers (sirt_entry <= (&cur->References()[num_refs-1]))) { 247a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return true; 248a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 249a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 250a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return false; 251a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 252a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 253408f79aeb676251ba35667a64e86c20638d7cb0bIan RogersObject* Thread::DecodeJObject(jobject obj) { 254408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // TODO: Only allowed to hold Object* when in the runnable state 255408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // DCHECK(state_ == kRunnable); 256408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (obj == NULL) { 257408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 258408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 259408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRef ref = reinterpret_cast<IndirectRef>(obj); 260408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectRefKind kind = GetIndirectRefKind(ref); 261408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Object* result; 262408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers switch (kind) { 263408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kLocal: 264408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 26569f5bc6759f256a146eefd8a7141d39fcc3b0421Elliott Hughes IndirectReferenceTable& locals = jni_env_->locals; 266408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = locals.Get(ref); 267408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 268408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 269408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kGlobal: 270408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 271408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 272408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& globals = vm->globals; 273408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->globals_lock); 274408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = globals.Get(ref); 275408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 276408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 277408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kWeakGlobal: 278408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers { 279408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers JavaVMExt* vm = Runtime::Current()->GetJavaVM(); 280408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers IndirectReferenceTable& weak_globals = vm->weak_globals; 281408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers MutexLock mu(vm->weak_globals_lock); 282408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = weak_globals.Get(ref); 283408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == kClearedJniWeakGlobal) { 284408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // This is a special case where it's okay to return NULL. 285408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return NULL; 286408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 287408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers break; 288408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 289408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers case kSirtOrInvalid: 290408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers default: 291408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // TODO: make stack indirect reference table lookup more efficient 292408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Check if this is a local reference in the SIRT 293408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (SirtContains(obj)) { 294408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = *reinterpret_cast<Object**>(obj); // Read from SIRT 295408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO 296408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers // Assume an invalid local reference is actually a direct pointer. 297408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = reinterpret_cast<Object*>(obj); 298408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } else { 299408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers LOG(FATAL) << "Invalid indirect reference " << obj; 300408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers result = reinterpret_cast<Object*>(kInvalidIndirectRefObject); 301408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 302408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 303408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 304408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers if (result == NULL) { 305408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": " 306408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers << obj; 307408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers } 308408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers Heap::VerifyObject(result); 309408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers return result; 310408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers} 311408f79aeb676251ba35667a64e86c20638d7cb0bIan Rogers 31255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao// TODO: Replaces trace.method and trace.pc with IntArray nad 31355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao// ObjectArray<Method>. 31455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei LiaoThread::InternalStackTrace* Thread::GetStackTrace(uint16_t length) { 31555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao Frame frame = Thread::Current()->GetTopOfStack(); 31655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao InternalStackTrace *traces = new InternalStackTrace[length]; 31755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao for (uint16_t i = 0; i < length && frame.HasNext(); ++i, frame.Next()) { 31855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao traces[i].method = frame.GetMethod(); 31955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao traces[i].pc = frame.GetPC(); 32055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 32155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao return traces; 32255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 32355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 32455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei LiaoObjectArray<StackTraceElement>* Thread::GetStackTraceElement(uint16_t length, InternalStackTrace *raw_trace) { 32555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 32655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao ObjectArray<StackTraceElement>* java_traces = class_linker->AllocStackTraceElementArray(length); 32755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 32855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao for (uint16_t i = 0; i < length; ++i) { 32955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao // Prepare parameter for StackTraceElement(String cls, String method, String file, int line) 33055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao const Method* method = raw_trace[i].method; 33155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao const Class* klass = method->GetDeclaringClass(); 33255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao const DexFile& dex_file = class_linker->FindDexFile(klass->GetDexCache()); 33355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao String* readable_descriptor = String::AllocFromModifiedUtf8(PrettyDescriptor(klass->GetDescriptor()).c_str()); 33455df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 33555df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao StackTraceElement* obj = 33655df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao StackTraceElement::Alloc(readable_descriptor, 33755df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao method->GetName(), String::AllocFromModifiedUtf8(klass->source_file_), 33855df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao dex_file.GetLineNumFromPC(method, method->ToDexPC(raw_trace[i].pc))); 33955df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao java_traces->Set(i, obj); 34055df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao } 34155df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao return java_traces; 34255df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao} 34355df06be4369f5d8ab5eb61a5d22809255171036Shih-wei Liao 344e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughesvoid Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) { 34537f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes std::string msg; 346a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_list args; 347a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_start(args, fmt); 34837f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes StringAppendV(&msg, fmt, args); 349a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_end(args); 35037f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes 351e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception". 352e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(exception_class_descriptor[0] == 'L'); 353e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes std::string descriptor(exception_class_descriptor + 1); 354e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(descriptor[descriptor.length() - 1] == ';'); 355e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes descriptor.erase(descriptor.length() - 1); 356e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes 357e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes JNIEnv* env = GetJniEnv(); 358e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes jclass exception_class = env->FindClass(descriptor.c_str()); 359e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\""; 360e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes int rc = env->ThrowNew(exception_class, msg.c_str()); 361e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes CHECK_EQ(rc, JNI_OK); 362a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes} 363a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 36479082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughesvoid Thread::ThrowOutOfMemoryError() { 36579082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes UNIMPLEMENTED(FATAL); 36679082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes} 36779082e367845bbd68ec44ef2ddd1be8ef0e1550fElliott Hughes 3681a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei LiaoFrame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) { 3691a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 3701a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DCHECK(class_linker != NULL); 3711a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 3721a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Frame cur_frame = GetTopOfStack(); 3731a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao for (int unwind_depth = 0; ; unwind_depth++) { 3741a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const Method* cur_method = cur_frame.GetMethod(); 3751a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache(); 3761a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile& dex_file = class_linker->FindDexFile(dex_cache); 3771a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 3781a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao void* handler_addr = FindExceptionHandlerInMethod(cur_method, 3791a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao throw_pc, 3801a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao dex_file, 3811a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao class_linker); 3821a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (handler_addr) { 3831a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao *handler_pc = handler_addr; 3841a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return cur_frame; 3851a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 3861a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao // Check if we are at the last frame 3871a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (cur_frame.HasNext()) { 3881a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao cur_frame.Next(); 3891a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 3901a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao // Either at the top of stack or next frame is native. 3911a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao break; 3921a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 3931a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 3941a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 3951a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao *handler_pc = NULL; 3961a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return Frame(); 3971a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 3981a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 3991a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid* Thread::FindExceptionHandlerInMethod(const Method* method, 4001a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao void* throw_pc, 4011a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile& dex_file, 4021a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao ClassLinker* class_linker) { 403e5b0dc83537bf915c6abe4efeae6e501daf75a27Elliott Hughes Throwable* exception_obj = exception_; 4041a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao exception_ = NULL; 4051a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4061a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao intptr_t dex_pc = -1; 4071a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_); 4081a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DexFile::CatchHandlerIterator iter; 4091a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao for (iter = dex_file.dexFindCatchHandler(*code_item, 4101a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc))); 4111a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao !iter.HasNext(); 4121a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao iter.Next()) { 4131a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_)); 4141a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DCHECK(klass != NULL); 4151a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (exception_obj->InstanceOf(klass)) { 4161a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao dex_pc = iter.Get().address_; 4171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao break; 4181a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 4211a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao exception_ = exception_obj; 4221a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (iter.HasNext()) { 4231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return NULL; 4241a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 4251a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return reinterpret_cast<void*>( method->ToNativePC(dex_pc) ); 4261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 4271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 4281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 429b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstatic const char* kStateNames[] = { 430b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "New", 431b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Runnable", 432b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Blocked", 433b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Waiting", 434b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "TimedWaiting", 435b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Native", 436b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Terminated", 437b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 438b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state) { 439b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers if (state >= Thread::kNew && state <= Thread::kTerminated) { 440b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers os << kStateNames[state-Thread::kNew]; 441b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 442b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers os << "State[" << static_cast<int>(state) << "]"; 443b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 444b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return os; 445b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 446b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 447330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread) { 448330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes os << "Thread[" << &thread 449e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",pthread_t=" << thread.GetImpl() 450e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",tid=" << thread.GetTid() 451e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",id=" << thread.GetId() 452e27955ca3ca960928d4dbd6cb79711fce06950b3Elliott Hughes << ",state=" << thread.GetState() << "]"; 453330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes return os; 454330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes} 455330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 45661e019d291583029c01b61b93bea750f2b663c37Carl ShapiroThreadList* ThreadList::Create() { 45761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return new ThreadList; 45861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 45961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 460b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::ThreadList() { 461b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_ = Mutex::Create("ThreadList::Lock"); 462b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 463b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 464b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::~ThreadList() { 465c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes if (Contains(Thread::Current())) { 466c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes Runtime::Current()->DetachCurrentThread(); 467c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes } 468c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 469c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes // All threads should have exited and unregistered when we 470b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // reach this point. This means that all daemon threads had been 471b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // shutdown cleanly. 472c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes // TODO: dump ThreadList if non-empty. 473c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK_EQ(list_.size(), 0U); 474c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 475b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro delete lock_; 476b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_ = NULL; 477b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 478b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 479c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughesbool ThreadList::Contains(Thread* thread) { 480c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes return find(list_.begin(), list_.end(), thread) != list_.end(); 481c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes} 482c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes 483b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Register(Thread* thread) { 484b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro MutexLock mu(lock_); 485c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK(!Contains(thread)); 486b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro list_.push_front(thread); 487b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 488b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 489b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Unregister(Thread* thread) { 490b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro MutexLock mu(lock_); 491c1674ed06662420213441ff2b818f2f71f9098dcElliott Hughes CHECK(Contains(thread)); 492b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro list_.remove(thread); 493b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 494b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 495b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} // namespace 496