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