blob: 2f43e232917de0d826f7963e40b52253cf6933ac [file] [log] [blame]
Carl Shapirob5573532011-07-12 18:22:59 -07001// Copyright 2011 Google Inc. All Rights Reserved.
2
Brian Carlstrom578bbdc2011-07-21 14:07:47 -07003#include "thread.h"
Carl Shapirob5573532011-07-12 18:22:59 -07004
Ian Rogersb033c752011-07-20 12:22:35 -07005#include <pthread.h>
6#include <sys/mman.h>
Carl Shapirob5573532011-07-12 18:22:59 -07007#include <algorithm>
Elliott Hugheseb4f6142011-07-15 17:43:51 -07008#include <cerrno>
Carl Shapirob5573532011-07-12 18:22:59 -07009#include <list>
Carl Shapirob5573532011-07-12 18:22:59 -070010
Elliott Hughesa5b897e2011-08-16 11:33:06 -070011#include "class_linker.h"
Ian Rogers408f79a2011-08-23 18:22:33 -070012#include "heap.h"
Elliott Hughesc5f7c912011-08-18 14:00:42 -070013#include "jni_internal.h"
Elliott Hughesa5b897e2011-08-16 11:33:06 -070014#include "object.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070015#include "runtime.h"
16#include "utils.h"
buzbee54330722011-08-23 16:46:55 -070017#include "runtime_support.h"
Carl Shapirob5573532011-07-12 18:22:59 -070018
19namespace art {
20
Elliott Hughese27955c2011-08-26 15:21:24 -070021/* desktop Linux needs a little help with gettid() */
22#if !defined(HAVE_ANDROID_OS)
23#define __KERNEL__
24# include <linux/unistd.h>
25#ifdef _syscall0
26_syscall0(pid_t, gettid)
27#else
28pid_t gettid() { return syscall(__NR_gettid);}
29#endif
30#undef __KERNEL__
31#endif
32
Carl Shapirob5573532011-07-12 18:22:59 -070033pthread_key_t Thread::pthread_key_self_;
34
buzbee3ea4ec52011-08-22 17:37:19 -070035void Thread::InitFunctionPointers() {
buzbee54330722011-08-23 16:46:55 -070036#if defined(__arm__)
37 pShlLong = art_shl_long;
38 pShrLong = art_shr_long;
39 pUshrLong = art_ushr_long;
40#endif
buzbee3ea4ec52011-08-22 17:37:19 -070041 pArtAllocArrayByClass = Array::Alloc;
42 pMemcpy = memcpy;
43#if 0
44//void* (Thread::*pMemcpy)(void*, const void*, size_t) /* = memcpy*/ ;
45float (Thread::*pI2f)(int);
46int (Thread::*pF2iz)(float);
47float (Thread::*pD2f)(double);
48double (Thread::*pF2d)(float);
49double (Thread::*pI2d)(int);
50int (Thread::*pD2iz)(double);
51float (Thread::*pL2f)(long);
52double (Thread::*pL2d)(long);
53long long (Thread::*pArtF2l)(float);
54long long (Thread::*pArtD2l)(double);
55float (Thread::*pFadd)(float, float);
56float (Thread::*pFsub)(float, float);
57float (Thread::*pFdiv)(float, float);
58float (Thread::*pFmul)(float, float);
59float (Thread::*pFmodf)(float, float);
60double (Thread::*pDadd)(double, double);
61double (Thread::*pDsub)(double, double);
62double (Thread::*pDdiv)(double, double);
63double (Thread::*pDmul)(double, double);
64double (Thread::*pFmod)(double, double);
65int (Thread::*pIdivmod)(int, int);
66int (Thread::*pIdiv)(int, int);
67long long (Thread::*pLdivmod)(long long, long long);
68bool (Thread::*pArtUnlockObject)(struct Thread*, struct Object*);
69bool (Thread::*pArtCanPutArrayElementNoThrow)(const struct ClassObject*,
70 const struct ClassObject*);
71int (Thread::*pArtInstanceofNonTrivialNoThrow)
72 (const struct ClassObject*, const struct ClassObject*);
73int (Thread::*pArtInstanceofNonTrivial) (const struct ClassObject*,
74 const struct ClassObject*);
75struct Method* (Thread::*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t,
76 const struct Method*, struct DvmDex*);
77bool (Thread::*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*);
78void (Thread::*pArtLockObjectNoThrow)(struct Thread*, struct Object*);
79struct Object* (Thread::*pArtAllocObjectNoThrow)(struct ClassObject*, int);
80void (Thread::*pArtThrowException)(struct Thread*, struct Object*);
81bool (Thread::*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*);
82#endif
83}
84
Carl Shapirob5573532011-07-12 18:22:59 -070085Mutex* Mutex::Create(const char* name) {
86 Mutex* mu = new Mutex(name);
87 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070088 CHECK_EQ(0, result);
Carl Shapirob5573532011-07-12 18:22:59 -070089 return mu;
90}
91
92void Mutex::Lock() {
93 int result = pthread_mutex_lock(&lock_impl_);
94 CHECK_EQ(result, 0);
95 SetOwner(Thread::Current());
96}
97
98bool Mutex::TryLock() {
99 int result = pthread_mutex_lock(&lock_impl_);
100 if (result == EBUSY) {
101 return false;
102 } else {
103 CHECK_EQ(result, 0);
104 SetOwner(Thread::Current());
105 return true;
106 }
107}
108
109void Mutex::Unlock() {
110 CHECK(GetOwner() == Thread::Current());
111 int result = pthread_mutex_unlock(&lock_impl_);
112 CHECK_EQ(result, 0);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700113 SetOwner(NULL);
Carl Shapirob5573532011-07-12 18:22:59 -0700114}
115
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700116void Frame::Next() {
117 byte* next_sp = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700118 GetMethod()->GetFrameSizeInBytes();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700119 sp_ = reinterpret_cast<const Method**>(next_sp);
120}
121
122void* Frame::GetPC() const {
123 byte* pc_addr = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700124 GetMethod()->GetReturnPcOffsetInBytes();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700125 return reinterpret_cast<void*>(pc_addr);
126}
127
128const Method* Frame::NextMethod() const {
129 byte* next_sp = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700130 GetMethod()->GetFrameSizeInBytes();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700131 return reinterpret_cast<const Method*>(next_sp);
132}
133
Carl Shapiro61e019d2011-07-14 16:53:09 -0700134void* ThreadStart(void *arg) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700135 UNIMPLEMENTED(FATAL);
Carl Shapirob5573532011-07-12 18:22:59 -0700136 return NULL;
137}
138
Brian Carlstromb765be02011-08-17 23:54:10 -0700139Thread* Thread::Create(const Runtime* runtime) {
140 size_t stack_size = runtime->GetStackSize();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700141
142 Thread* new_thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700143 new_thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700144
145 pthread_attr_t attr;
Elliott Hughese27955c2011-08-26 15:21:24 -0700146 errno = pthread_attr_init(&attr);
147 if (errno != 0) {
148 PLOG(FATAL) << "pthread_attr_init failed";
149 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700150
Elliott Hughese27955c2011-08-26 15:21:24 -0700151 errno = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
152 if (errno != 0) {
153 PLOG(FATAL) << "pthread_attr_setdetachstate(PTHREAD_CREATE_DETACHED) failed";
154 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700155
Elliott Hughese27955c2011-08-26 15:21:24 -0700156 errno = pthread_attr_setstacksize(&attr, stack_size);
157 if (errno != 0) {
158 PLOG(FATAL) << "pthread_attr_setstacksize(" << stack_size << ") failed";
159 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700160
Elliott Hughese27955c2011-08-26 15:21:24 -0700161 errno = pthread_create(&new_thread->handle_, &attr, ThreadStart, new_thread);
162 if (errno != 0) {
163 PLOG(FATAL) << "pthread_create failed";
164 }
165
166 errno = pthread_attr_destroy(&attr);
167 if (errno != 0) {
168 PLOG(FATAL) << "pthread_attr_destroy failed";
169 }
Carl Shapiro61e019d2011-07-14 16:53:09 -0700170
171 return new_thread;
172}
173
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700174Thread* Thread::Attach(const Runtime* runtime) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700175 Thread* thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700176 thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700177
178 thread->handle_ = pthread_self();
179
180 thread->state_ = kRunnable;
181
Elliott Hughesa5780da2011-07-17 11:39:39 -0700182 errno = pthread_setspecific(Thread::pthread_key_self_, thread);
183 if (errno != 0) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700184 PLOG(FATAL) << "pthread_setspecific failed";
Elliott Hughesa5780da2011-07-17 11:39:39 -0700185 }
186
Elliott Hughes75770752011-08-24 17:52:38 -0700187 thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM());
Elliott Hughes330304d2011-08-12 14:28:05 -0700188
Carl Shapiro61e019d2011-07-14 16:53:09 -0700189 return thread;
190}
191
Elliott Hughese27955c2011-08-26 15:21:24 -0700192pid_t Thread::GetTid() const {
193 return gettid();
194}
195
Carl Shapirob5573532011-07-12 18:22:59 -0700196static void ThreadExitCheck(void* arg) {
197 LG << "Thread exit check";
198}
199
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700200bool Thread::Startup() {
Carl Shapirob5573532011-07-12 18:22:59 -0700201 // Allocate a TLS slot.
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700202 errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck);
203 if (errno != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700204 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700205 return false;
206 }
207
208 // Double-check the TLS slot allocation.
209 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700210 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700211 return false;
212 }
213
214 // TODO: initialize other locks and condition variables
215
216 return true;
217}
218
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700219void Thread::Shutdown() {
220 errno = pthread_key_delete(Thread::pthread_key_self_);
221 if (errno != 0) {
222 PLOG(WARNING) << "pthread_key_delete failed";
223 }
224}
225
226Thread::~Thread() {
227 delete jni_env_;
228}
229
Ian Rogers408f79a2011-08-23 18:22:33 -0700230size_t Thread::NumSirtReferences() {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700231 size_t count = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700232 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700233 count += cur->NumberOfReferences();
234 }
235 return count;
236}
237
Ian Rogers408f79a2011-08-23 18:22:33 -0700238bool Thread::SirtContains(jobject obj) {
239 Object** sirt_entry = reinterpret_cast<Object**>(obj);
240 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700241 size_t num_refs = cur->NumberOfReferences();
Ian Rogers408f79a2011-08-23 18:22:33 -0700242 // A SIRT should always have a jobject/jclass as a native method is passed
243 // in a this pointer or a class
244 DCHECK_GT(num_refs, 0u);
245 if ((&cur->References()[0] >= sirt_entry) &&
246 (sirt_entry <= (&cur->References()[num_refs-1]))) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700247 return true;
248 }
249 }
250 return false;
251}
252
Ian Rogers408f79a2011-08-23 18:22:33 -0700253Object* Thread::DecodeJObject(jobject obj) {
254 // TODO: Only allowed to hold Object* when in the runnable state
255 // DCHECK(state_ == kRunnable);
256 if (obj == NULL) {
257 return NULL;
258 }
259 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
260 IndirectRefKind kind = GetIndirectRefKind(ref);
261 Object* result;
262 switch (kind) {
263 case kLocal:
264 {
Elliott Hughes69f5bc62011-08-24 09:26:14 -0700265 IndirectReferenceTable& locals = jni_env_->locals;
Ian Rogers408f79a2011-08-23 18:22:33 -0700266 result = locals.Get(ref);
267 break;
268 }
269 case kGlobal:
270 {
271 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
272 IndirectReferenceTable& globals = vm->globals;
273 MutexLock mu(vm->globals_lock);
274 result = globals.Get(ref);
275 break;
276 }
277 case kWeakGlobal:
278 {
279 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
280 IndirectReferenceTable& weak_globals = vm->weak_globals;
281 MutexLock mu(vm->weak_globals_lock);
282 result = weak_globals.Get(ref);
283 if (result == kClearedJniWeakGlobal) {
284 // This is a special case where it's okay to return NULL.
285 return NULL;
286 }
287 break;
288 }
289 case kSirtOrInvalid:
290 default:
291 // TODO: make stack indirect reference table lookup more efficient
292 // Check if this is a local reference in the SIRT
293 if (SirtContains(obj)) {
294 result = *reinterpret_cast<Object**>(obj); // Read from SIRT
295 } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
296 // Assume an invalid local reference is actually a direct pointer.
297 result = reinterpret_cast<Object*>(obj);
298 } else {
299 LOG(FATAL) << "Invalid indirect reference " << obj;
300 result = reinterpret_cast<Object*>(kInvalidIndirectRefObject);
301 }
302 }
303
304 if (result == NULL) {
305 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
306 << obj;
307 }
308 Heap::VerifyObject(result);
309 return result;
310}
311
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700312void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700313 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700314 va_list args;
315 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700316 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700317 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700318
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700319 // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
320 CHECK(exception_class_descriptor[0] == 'L');
321 std::string descriptor(exception_class_descriptor + 1);
322 CHECK(descriptor[descriptor.length() - 1] == ';');
323 descriptor.erase(descriptor.length() - 1);
324
325 JNIEnv* env = GetJniEnv();
326 jclass exception_class = env->FindClass(descriptor.c_str());
327 CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
328 int rc = env->ThrowNew(exception_class, msg.c_str());
329 CHECK_EQ(rc, JNI_OK);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700330}
331
Elliott Hughes79082e32011-08-25 12:07:32 -0700332void Thread::ThrowOutOfMemoryError() {
333 UNIMPLEMENTED(FATAL);
334}
335
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700336Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
337 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
338 DCHECK(class_linker != NULL);
339
340 Frame cur_frame = GetTopOfStack();
341 for (int unwind_depth = 0; ; unwind_depth++) {
342 const Method* cur_method = cur_frame.GetMethod();
343 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
344 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
345
346 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
347 throw_pc,
348 dex_file,
349 class_linker);
350 if (handler_addr) {
351 *handler_pc = handler_addr;
352 return cur_frame;
353 } else {
354 // Check if we are at the last frame
355 if (cur_frame.HasNext()) {
356 cur_frame.Next();
357 } else {
358 // Either at the top of stack or next frame is native.
359 break;
360 }
361 }
362 }
363 *handler_pc = NULL;
364 return Frame();
365}
366
367void* Thread::FindExceptionHandlerInMethod(const Method* method,
368 void* throw_pc,
369 const DexFile& dex_file,
370 ClassLinker* class_linker) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700371 Throwable* exception_obj = exception_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700372 exception_ = NULL;
373
374 intptr_t dex_pc = -1;
375 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
376 DexFile::CatchHandlerIterator iter;
377 for (iter = dex_file.dexFindCatchHandler(*code_item,
378 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
379 !iter.HasNext();
380 iter.Next()) {
381 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
382 DCHECK(klass != NULL);
383 if (exception_obj->InstanceOf(klass)) {
384 dex_pc = iter.Get().address_;
385 break;
386 }
387 }
388
389 exception_ = exception_obj;
390 if (iter.HasNext()) {
391 return NULL;
392 } else {
393 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
394 }
395}
396
Ian Rogersb033c752011-07-20 12:22:35 -0700397static const char* kStateNames[] = {
398 "New",
399 "Runnable",
400 "Blocked",
401 "Waiting",
402 "TimedWaiting",
403 "Native",
404 "Terminated",
405};
406std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
407 if (state >= Thread::kNew && state <= Thread::kTerminated) {
408 os << kStateNames[state-Thread::kNew];
409 } else {
410 os << "State[" << static_cast<int>(state) << "]";
411 }
412 return os;
413}
414
Elliott Hughes330304d2011-08-12 14:28:05 -0700415std::ostream& operator<<(std::ostream& os, const Thread& thread) {
416 os << "Thread[" << &thread
Elliott Hughese27955c2011-08-26 15:21:24 -0700417 << ",pthread_t=" << thread.GetImpl()
418 << ",tid=" << thread.GetTid()
419 << ",id=" << thread.GetId()
420 << ",state=" << thread.GetState() << "]";
Elliott Hughes330304d2011-08-12 14:28:05 -0700421 return os;
422}
423
Carl Shapiro61e019d2011-07-14 16:53:09 -0700424ThreadList* ThreadList::Create() {
425 return new ThreadList;
426}
427
Carl Shapirob5573532011-07-12 18:22:59 -0700428ThreadList::ThreadList() {
429 lock_ = Mutex::Create("ThreadList::Lock");
430}
431
432ThreadList::~ThreadList() {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700433 if (Contains(Thread::Current())) {
434 Runtime::Current()->DetachCurrentThread();
435 }
436
437 // All threads should have exited and unregistered when we
Carl Shapirob5573532011-07-12 18:22:59 -0700438 // reach this point. This means that all daemon threads had been
439 // shutdown cleanly.
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700440 // TODO: dump ThreadList if non-empty.
441 CHECK_EQ(list_.size(), 0U);
442
Carl Shapirob5573532011-07-12 18:22:59 -0700443 delete lock_;
444 lock_ = NULL;
445}
446
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700447bool ThreadList::Contains(Thread* thread) {
448 return find(list_.begin(), list_.end(), thread) != list_.end();
449}
450
Carl Shapirob5573532011-07-12 18:22:59 -0700451void ThreadList::Register(Thread* thread) {
452 MutexLock mu(lock_);
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700453 CHECK(!Contains(thread));
Carl Shapirob5573532011-07-12 18:22:59 -0700454 list_.push_front(thread);
455}
456
457void ThreadList::Unregister(Thread* thread) {
458 MutexLock mu(lock_);
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700459 CHECK(Contains(thread));
Carl Shapirob5573532011-07-12 18:22:59 -0700460 list_.remove(thread);
461}
462
Carl Shapirob5573532011-07-12 18:22:59 -0700463} // namespace