thread.cc revision 1a18c8c1c0e4ea1ff06177e93c7ff703376dcee2
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" 12c5f7c91ab89055cffb573fff7e06dbdd860bccedElliott Hughes#include "jni_internal.h" 13a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes#include "object.h" 14578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "runtime.h" 15578bbdc684db8ed68e9fedbc678669d27fa68b6eBrian Carlstrom#include "utils.h" 16b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 17b557353b22c728eecbd1c68593b482622c7782a8Carl Shapironamespace art { 18b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 19b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiropthread_key_t Thread::pthread_key_self_; 20b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 21b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroMutex* Mutex::Create(const char* name) { 22b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro Mutex* mu = new Mutex(name); 23b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_init(&mu->lock_impl_, NULL); 24b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers CHECK_EQ(0, result); 25b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return mu; 26b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 27b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 28b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Lock() { 29b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_lock(&lock_impl_); 30b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 31b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro SetOwner(Thread::Current()); 32b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 33b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 34b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirobool Mutex::TryLock() { 35b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_lock(&lock_impl_); 36b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (result == EBUSY) { 37b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 38b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } else { 39b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 40b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro SetOwner(Thread::Current()); 41b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return true; 42b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 43b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 44b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 45b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid Mutex::Unlock() { 46b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK(GetOwner() == Thread::Current()); 47b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro int result = pthread_mutex_unlock(&lock_impl_); 48b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK_EQ(result, 0); 49f4c21c9f6440c3980c47a297519f758796dbc039Elliott Hughes SetOwner(NULL); 50b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 51b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 521a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid Frame::Next() { 531a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 541a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao GetMethod()->GetFrameSize(); 551a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao sp_ = reinterpret_cast<const Method**>(next_sp); 561a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 571a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 581a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid* Frame::GetPC() const { 591a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* pc_addr = reinterpret_cast<byte*>(sp_) + 601a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao GetMethod()->GetPcOffset(); 611a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return reinterpret_cast<void*>(pc_addr); 621a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 631a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 641a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaoconst Method* Frame::NextMethod() const { 651a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao byte* next_sp = reinterpret_cast<byte*>(sp_) + 661a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao GetMethod()->GetFrameSize(); 671a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return reinterpret_cast<const Method*>(next_sp); 681a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 691a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 7061e019d291583029c01b61b93bea750f2b663c37Carl Shapirovoid* ThreadStart(void *arg) { 7153b61314370c49354ed6f8d616d6a9a182410fc1Elliott Hughes UNIMPLEMENTED(FATAL); 72b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return NULL; 73b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 74b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 75b765be0d656c3073402693aeaf64e95a0e49f218Brian CarlstromThread* Thread::Create(const Runtime* runtime) { 76b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom size_t stack_size = runtime->GetStackSize(); 774a289ed61242964b921434de7d375f46480472a1Brian Carlstrom scoped_ptr<MemMap> stack(MemMap::Map(stack_size, PROT_READ | PROT_WRITE)); 78b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom if (stack == NULL) { 79b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom LOG(FATAL) << "failed to allocate thread stack"; 80b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom // notreached 81b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom return NULL; 8261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro } 8361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 8461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro Thread* new_thread = new Thread; 85176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers new_thread->InitCpu(); 86b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom new_thread->stack_.reset(stack.release()); 87b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom // Since stacks are assumed to grown downward the base is the limit and the limit is the base. 88b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom new_thread->stack_limit_ = stack->GetAddress(); 89b765be0d656c3073402693aeaf64e95a0e49f218Brian Carlstrom new_thread->stack_base_ = stack->GetLimit(); 9061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 9161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro pthread_attr_t attr; 9261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro int result = pthread_attr_init(&attr); 9361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro CHECK_EQ(result, 0); 9461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 9561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 9661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro CHECK_EQ(result, 0); 9761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 9861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro pthread_t handle; 9961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro result = pthread_create(&handle, &attr, ThreadStart, new_thread); 10061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro CHECK_EQ(result, 0); 10161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 10261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro result = pthread_attr_destroy(&attr); 10361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro CHECK_EQ(result, 0); 10461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 10561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return new_thread; 10661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 10761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 108515a5bc89282d6f910cae4d5852bb77124a47825Elliott HughesThread* Thread::Attach(const Runtime* runtime) { 10961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro Thread* thread = new Thread; 110176f59cd8997a0491ea5ccdea8e9dfff85dd32d6Ian Rogers thread->InitCpu(); 11161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->stack_limit_ = reinterpret_cast<byte*>(-1); // TODO: getrlimit 11261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro uintptr_t addr = reinterpret_cast<uintptr_t>(&thread); // TODO: ask pthreads 113b0460eaa2cb131f1dbdd5a7217bd36b9a9f1b995Brian Carlstrom uintptr_t stack_base = RoundUp(addr, kPageSize); 11461e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->stack_base_ = reinterpret_cast<byte*>(stack_base); 11561e019d291583029c01b61b93bea750f2b663c37Carl Shapiro // TODO: set the stack size 11661e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 11761e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->handle_ = pthread_self(); 11861e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 11961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro thread->state_ = kRunnable; 12061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 121a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes errno = pthread_setspecific(Thread::pthread_key_self_, thread); 122a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes if (errno != 0) { 123a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes PLOG(FATAL) << "pthread_setspecific failed"; 124a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes } 125a5780dad67556297c8ca5f2608c53b193e6c4514Elliott Hughes 1260af5543f8ea20c3e655b2d748a1b7dcf283792feElliott Hughes JavaVMExt* vm = runtime->GetJavaVM(); 127515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes CHECK(vm != NULL); 128515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes bool check_jni = vm->check_jni; 129515a5bc89282d6f910cae4d5852bb77124a47825Elliott Hughes thread->jni_env_ = reinterpret_cast<JNIEnv*>(new JNIEnvExt(thread, check_jni)); 130330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 13161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return thread; 13261e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 13361e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 134b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirostatic void ThreadExitCheck(void* arg) { 135b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro LG << "Thread exit check"; 136b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 137b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 138b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirobool Thread::Init() { 139b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Allocate a TLS slot. 140b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) { 141eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes PLOG(WARNING) << "pthread_key_create failed"; 142b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 143b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 144b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 145b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Double-check the TLS slot allocation. 146b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro if (pthread_getspecific(pthread_key_self_) != NULL) { 147eb4f614f2eb53b92ebd416fa418f550861655887Elliott Hughes LOG(WARNING) << "newly-created pthread TLS slot is not NULL"; 148b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return false; 149b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro } 150b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 151b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // TODO: initialize other locks and condition variables 152b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 153b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro return true; 154b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 155b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 156a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogerssize_t Thread::NumShbHandles() { 157a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t count = 0; 158a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) { 159a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers count += cur->NumberOfReferences(); 160a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 161a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return count; 162a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 163a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 164a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogersbool Thread::ShbContains(jobject obj) { 1654873d465a1eb6dfbdeddb085c81239d39db60c42Brian Carlstrom Object** shb_entry = reinterpret_cast<Object**>(obj); 166a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) { 167a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers size_t num_refs = cur->NumberOfReferences(); 168a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers DCHECK_GT(num_refs, 0u); // A SHB should always have a jobject/jclass 169a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers if ((&cur->Handles()[0] >= shb_entry) && 170a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers (shb_entry <= (&cur->Handles()[num_refs-1]))) { 171a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return true; 172a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 173a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers } 174a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers return false; 175a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers} 176a8cd9f4a849835af7856f9c9782ea59e11ddef85Ian Rogers 17737f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughesvoid Thread::ThrowNewException(Class* exception_class, const char* msg) { 178a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes Object* exception = exception_class->NewInstance(); 179a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes CHECK(exception != NULL); 180a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 181bfaadc83460726b049614a8616effbb03a247552Elliott Hughes String* java_msg = String::AllocFromModifiedUtf8(msg); 182a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes CHECK(java_msg != NULL); 183a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 184a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes // TODO: what if there's already a pending exception? 185a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes // TODO: support the other constructors. 186a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes Method* ctor = exception_class->FindDirectMethod("<init>", "(Ljava/lang/String;)V"); 187710a0cbb4b0af03ce8651ed7936437c73250045eElliott Hughes CHECK(ctor != NULL); 188a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 189a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes // TODO: need to *call* the constructor! 190a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes UNIMPLEMENTED(WARNING) << "can't call " 1919cff8e13d41825c4f3f0127af061e94b06114fc8Brian Carlstrom << exception_class->GetDescriptor()->ToModifiedUtf8() << ".<init> " 192a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes << "\"" << msg << "\""; 193a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 19437f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes SetException(exception); 195a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes} 196a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 197a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughesvoid Thread::ThrowNewException(const char* exception_class_name, const char* fmt, ...) { 19837f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 19937f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes Class* exception_class = class_linker->FindSystemClass(exception_class_name); 20037f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes CHECK(exception_class != NULL); 20137f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes 20237f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes std::string msg; 203a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_list args; 204a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_start(args, fmt); 20537f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes StringAppendV(&msg, fmt, args); 206a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes va_end(args); 20737f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes 20837f7a40f6789bb287f287a9af00777af9d6428eeElliott Hughes ThrowNewException(exception_class, msg.c_str()); 209a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes} 210a5b897eae4b6f9f9608faa9eada7ddf42bf1bfd2Elliott Hughes 2111a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei LiaoFrame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) { 2121a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao ClassLinker* class_linker = Runtime::Current()->GetClassLinker(); 2131a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DCHECK(class_linker != NULL); 2141a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 2151a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Frame cur_frame = GetTopOfStack(); 2161a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao for (int unwind_depth = 0; ; unwind_depth++) { 2171a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const Method* cur_method = cur_frame.GetMethod(); 2181a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache(); 2191a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile& dex_file = class_linker->FindDexFile(dex_cache); 2201a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 2211a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao void* handler_addr = FindExceptionHandlerInMethod(cur_method, 2221a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao throw_pc, 2231a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao dex_file, 2241a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao class_linker); 2251a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (handler_addr) { 2261a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao *handler_pc = handler_addr; 2271a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return cur_frame; 2281a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 2291a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao // Check if we are at the last frame 2301a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (cur_frame.HasNext()) { 2311a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao cur_frame.Next(); 2321a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 2331a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao // Either at the top of stack or next frame is native. 2341a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao break; 2351a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 2361a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 2371a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 2381a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao *handler_pc = NULL; 2391a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return Frame(); 2401a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 2411a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 2421a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liaovoid* Thread::FindExceptionHandlerInMethod(const Method* method, 2431a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao void* throw_pc, 2441a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile& dex_file, 2451a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao ClassLinker* class_linker) { 2461a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Object* exception_obj = exception_; 2471a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao exception_ = NULL; 2481a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 2491a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao intptr_t dex_pc = -1; 2501a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_); 2511a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DexFile::CatchHandlerIterator iter; 2521a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao for (iter = dex_file.dexFindCatchHandler(*code_item, 2531a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc))); 2541a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao !iter.HasNext(); 2551a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao iter.Next()) { 2561a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_)); 2571a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao DCHECK(klass != NULL); 2581a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (exception_obj->InstanceOf(klass)) { 2591a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao dex_pc = iter.Get().address_; 2601a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao break; 2611a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 2621a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 2631a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 2641a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao exception_ = exception_obj; 2651a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao if (iter.HasNext()) { 2661a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return NULL; 2671a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } else { 2681a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao return reinterpret_cast<void*>( method->ToNativePC(dex_pc) ); 2691a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao } 2701a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao} 2711a18c8c1c0e4ea1ff06177e93c7ff703376dcee2Shih-wei Liao 272b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstatic const char* kStateNames[] = { 273b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "New", 274b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Runnable", 275b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Blocked", 276b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Waiting", 277b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "TimedWaiting", 278b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Native", 279b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers "Terminated", 280b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers}; 281b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogersstd::ostream& operator<<(std::ostream& os, const Thread::State& state) { 282b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers if (state >= Thread::kNew && state <= Thread::kTerminated) { 283b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers os << kStateNames[state-Thread::kNew]; 284b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } else { 285b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers os << "State[" << static_cast<int>(state) << "]"; 286b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers } 287b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers return os; 288b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers} 289b033c75ebda80ac75f936366fe78d1edf5cec937Ian Rogers 290330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughesstd::ostream& operator<<(std::ostream& os, const Thread& thread) { 291330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes os << "Thread[" << &thread 292330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes << ",id=" << thread.GetId() 293330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes << ",tid=" << thread.GetNativeId() 294330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes << ",state=" << thread.GetState() << "]"; 295330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes return os; 296330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes} 297330304de14dc7118b45b8e7b5bd11a172fa61701Elliott Hughes 29861e019d291583029c01b61b93bea750f2b663c37Carl ShapiroThreadList* ThreadList::Create() { 29961e019d291583029c01b61b93bea750f2b663c37Carl Shapiro return new ThreadList; 30061e019d291583029c01b61b93bea750f2b663c37Carl Shapiro} 30161e019d291583029c01b61b93bea750f2b663c37Carl Shapiro 302b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::ThreadList() { 303b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_ = Mutex::Create("ThreadList::Lock"); 304b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 305b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 306b557353b22c728eecbd1c68593b482622c7782a8Carl ShapiroThreadList::~ThreadList() { 307b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // Make sure that all threads have exited and unregistered when we 308b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // reach this point. This means that all daemon threads had been 309b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro // shutdown cleanly. 3104a289ed61242964b921434de7d375f46480472a1Brian Carlstrom CHECK_LE(list_.size(), 1U); 3117a90959d4ef7a69f3bcb7b8763f646e12d9267d3Carl Shapiro // TODO: wait for all other threads to unregister 3124a289ed61242964b921434de7d375f46480472a1Brian Carlstrom CHECK(list_.size() == 0 || list_.front() == Thread::Current()); 3137a90959d4ef7a69f3bcb7b8763f646e12d9267d3Carl Shapiro // TODO: detach the current thread 314b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro delete lock_; 315b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro lock_ = NULL; 316b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 317b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 318b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Register(Thread* thread) { 319b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro MutexLock mu(lock_); 320b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK(find(list_.begin(), list_.end(), thread) == list_.end()); 321b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro list_.push_front(thread); 322b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 323b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 324b557353b22c728eecbd1c68593b482622c7782a8Carl Shapirovoid ThreadList::Unregister(Thread* thread) { 325b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro MutexLock mu(lock_); 326b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro CHECK(find(list_.begin(), list_.end(), thread) != list_.end()); 327b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro list_.remove(thread); 328b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} 329b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro 330b557353b22c728eecbd1c68593b482622c7782a8Carl Shapiro} // namespace 331