blob: 40aaa7dfb500c36113089b8a99768856ad5aa250 [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
21pthread_key_t Thread::pthread_key_self_;
22
buzbee3ea4ec52011-08-22 17:37:19 -070023void Thread::InitFunctionPointers() {
buzbee54330722011-08-23 16:46:55 -070024#if defined(__arm__)
25 pShlLong = art_shl_long;
26 pShrLong = art_shr_long;
27 pUshrLong = art_ushr_long;
28#endif
buzbee3ea4ec52011-08-22 17:37:19 -070029 pArtAllocArrayByClass = Array::Alloc;
30 pMemcpy = memcpy;
31#if 0
32//void* (Thread::*pMemcpy)(void*, const void*, size_t) /* = memcpy*/ ;
33float (Thread::*pI2f)(int);
34int (Thread::*pF2iz)(float);
35float (Thread::*pD2f)(double);
36double (Thread::*pF2d)(float);
37double (Thread::*pI2d)(int);
38int (Thread::*pD2iz)(double);
39float (Thread::*pL2f)(long);
40double (Thread::*pL2d)(long);
41long long (Thread::*pArtF2l)(float);
42long long (Thread::*pArtD2l)(double);
43float (Thread::*pFadd)(float, float);
44float (Thread::*pFsub)(float, float);
45float (Thread::*pFdiv)(float, float);
46float (Thread::*pFmul)(float, float);
47float (Thread::*pFmodf)(float, float);
48double (Thread::*pDadd)(double, double);
49double (Thread::*pDsub)(double, double);
50double (Thread::*pDdiv)(double, double);
51double (Thread::*pDmul)(double, double);
52double (Thread::*pFmod)(double, double);
53int (Thread::*pIdivmod)(int, int);
54int (Thread::*pIdiv)(int, int);
55long long (Thread::*pLdivmod)(long long, long long);
56bool (Thread::*pArtUnlockObject)(struct Thread*, struct Object*);
57bool (Thread::*pArtCanPutArrayElementNoThrow)(const struct ClassObject*,
58 const struct ClassObject*);
59int (Thread::*pArtInstanceofNonTrivialNoThrow)
60 (const struct ClassObject*, const struct ClassObject*);
61int (Thread::*pArtInstanceofNonTrivial) (const struct ClassObject*,
62 const struct ClassObject*);
63struct Method* (Thread::*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t,
64 const struct Method*, struct DvmDex*);
65bool (Thread::*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*);
66void (Thread::*pArtLockObjectNoThrow)(struct Thread*, struct Object*);
67struct Object* (Thread::*pArtAllocObjectNoThrow)(struct ClassObject*, int);
68void (Thread::*pArtThrowException)(struct Thread*, struct Object*);
69bool (Thread::*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*);
70#endif
71}
72
Carl Shapirob5573532011-07-12 18:22:59 -070073Mutex* Mutex::Create(const char* name) {
74 Mutex* mu = new Mutex(name);
75 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070076 CHECK_EQ(0, result);
Carl Shapirob5573532011-07-12 18:22:59 -070077 return mu;
78}
79
80void Mutex::Lock() {
81 int result = pthread_mutex_lock(&lock_impl_);
82 CHECK_EQ(result, 0);
83 SetOwner(Thread::Current());
84}
85
86bool Mutex::TryLock() {
87 int result = pthread_mutex_lock(&lock_impl_);
88 if (result == EBUSY) {
89 return false;
90 } else {
91 CHECK_EQ(result, 0);
92 SetOwner(Thread::Current());
93 return true;
94 }
95}
96
97void Mutex::Unlock() {
98 CHECK(GetOwner() == Thread::Current());
99 int result = pthread_mutex_unlock(&lock_impl_);
100 CHECK_EQ(result, 0);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700101 SetOwner(NULL);
Carl Shapirob5573532011-07-12 18:22:59 -0700102}
103
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700104void Frame::Next() {
105 byte* next_sp = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700106 GetMethod()->GetFrameSizeInBytes();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700107 sp_ = reinterpret_cast<const Method**>(next_sp);
108}
109
110void* Frame::GetPC() const {
111 byte* pc_addr = reinterpret_cast<byte*>(sp_) +
Shih-wei Liaod11af152011-08-23 16:02:11 -0700112 GetMethod()->GetReturnPcOffsetInBytes();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700113 return reinterpret_cast<void*>(pc_addr);
114}
115
116const Method* Frame::NextMethod() const {
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 return reinterpret_cast<const Method*>(next_sp);
120}
121
Carl Shapiro61e019d2011-07-14 16:53:09 -0700122void* ThreadStart(void *arg) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700123 UNIMPLEMENTED(FATAL);
Carl Shapirob5573532011-07-12 18:22:59 -0700124 return NULL;
125}
126
Brian Carlstromb765be02011-08-17 23:54:10 -0700127Thread* Thread::Create(const Runtime* runtime) {
128 size_t stack_size = runtime->GetStackSize();
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700129 scoped_ptr<MemMap> stack(MemMap::Map(stack_size, PROT_READ | PROT_WRITE));
Brian Carlstromb765be02011-08-17 23:54:10 -0700130 if (stack == NULL) {
131 LOG(FATAL) << "failed to allocate thread stack";
132 // notreached
133 return NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -0700134 }
135
136 Thread* new_thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700137 new_thread->InitCpu();
Brian Carlstromb765be02011-08-17 23:54:10 -0700138 new_thread->stack_.reset(stack.release());
139 // Since stacks are assumed to grown downward the base is the limit and the limit is the base.
140 new_thread->stack_limit_ = stack->GetAddress();
141 new_thread->stack_base_ = stack->GetLimit();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700142
143 pthread_attr_t attr;
144 int result = pthread_attr_init(&attr);
145 CHECK_EQ(result, 0);
146
147 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
148 CHECK_EQ(result, 0);
149
150 pthread_t handle;
151 result = pthread_create(&handle, &attr, ThreadStart, new_thread);
152 CHECK_EQ(result, 0);
153
154 result = pthread_attr_destroy(&attr);
155 CHECK_EQ(result, 0);
156
157 return new_thread;
158}
159
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700160Thread* Thread::Attach(const Runtime* runtime) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700161 Thread* thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700162 thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700163 thread->stack_limit_ = reinterpret_cast<byte*>(-1); // TODO: getrlimit
164 uintptr_t addr = reinterpret_cast<uintptr_t>(&thread); // TODO: ask pthreads
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700165 uintptr_t stack_base = RoundUp(addr, kPageSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700166 thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
167 // TODO: set the stack size
168
169 thread->handle_ = pthread_self();
170
171 thread->state_ = kRunnable;
172
Elliott Hughesa5780da2011-07-17 11:39:39 -0700173 errno = pthread_setspecific(Thread::pthread_key_self_, thread);
174 if (errno != 0) {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700175 PLOG(FATAL) << "pthread_setspecific failed";
Elliott Hughesa5780da2011-07-17 11:39:39 -0700176 }
177
Elliott Hughes75770752011-08-24 17:52:38 -0700178 thread->jni_env_ = new JNIEnvExt(thread, runtime->GetJavaVM());
Elliott Hughes330304d2011-08-12 14:28:05 -0700179
Carl Shapiro61e019d2011-07-14 16:53:09 -0700180 return thread;
181}
182
Carl Shapirob5573532011-07-12 18:22:59 -0700183static void ThreadExitCheck(void* arg) {
184 LG << "Thread exit check";
185}
186
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700187bool Thread::Startup() {
Carl Shapirob5573532011-07-12 18:22:59 -0700188 // Allocate a TLS slot.
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700189 errno = pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck);
190 if (errno != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700191 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700192 return false;
193 }
194
195 // Double-check the TLS slot allocation.
196 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700197 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700198 return false;
199 }
200
201 // TODO: initialize other locks and condition variables
202
203 return true;
204}
205
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700206void Thread::Shutdown() {
207 errno = pthread_key_delete(Thread::pthread_key_self_);
208 if (errno != 0) {
209 PLOG(WARNING) << "pthread_key_delete failed";
210 }
211}
212
213Thread::~Thread() {
214 delete jni_env_;
215}
216
Ian Rogers408f79a2011-08-23 18:22:33 -0700217size_t Thread::NumSirtReferences() {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700218 size_t count = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700219 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700220 count += cur->NumberOfReferences();
221 }
222 return count;
223}
224
Ian Rogers408f79a2011-08-23 18:22:33 -0700225bool Thread::SirtContains(jobject obj) {
226 Object** sirt_entry = reinterpret_cast<Object**>(obj);
227 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700228 size_t num_refs = cur->NumberOfReferences();
Ian Rogers408f79a2011-08-23 18:22:33 -0700229 // A SIRT should always have a jobject/jclass as a native method is passed
230 // in a this pointer or a class
231 DCHECK_GT(num_refs, 0u);
232 if ((&cur->References()[0] >= sirt_entry) &&
233 (sirt_entry <= (&cur->References()[num_refs-1]))) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700234 return true;
235 }
236 }
237 return false;
238}
239
Ian Rogers408f79a2011-08-23 18:22:33 -0700240Object* Thread::DecodeJObject(jobject obj) {
241 // TODO: Only allowed to hold Object* when in the runnable state
242 // DCHECK(state_ == kRunnable);
243 if (obj == NULL) {
244 return NULL;
245 }
246 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
247 IndirectRefKind kind = GetIndirectRefKind(ref);
248 Object* result;
249 switch (kind) {
250 case kLocal:
251 {
Elliott Hughes69f5bc62011-08-24 09:26:14 -0700252 IndirectReferenceTable& locals = jni_env_->locals;
Ian Rogers408f79a2011-08-23 18:22:33 -0700253 result = locals.Get(ref);
254 break;
255 }
256 case kGlobal:
257 {
258 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
259 IndirectReferenceTable& globals = vm->globals;
260 MutexLock mu(vm->globals_lock);
261 result = globals.Get(ref);
262 break;
263 }
264 case kWeakGlobal:
265 {
266 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
267 IndirectReferenceTable& weak_globals = vm->weak_globals;
268 MutexLock mu(vm->weak_globals_lock);
269 result = weak_globals.Get(ref);
270 if (result == kClearedJniWeakGlobal) {
271 // This is a special case where it's okay to return NULL.
272 return NULL;
273 }
274 break;
275 }
276 case kSirtOrInvalid:
277 default:
278 // TODO: make stack indirect reference table lookup more efficient
279 // Check if this is a local reference in the SIRT
280 if (SirtContains(obj)) {
281 result = *reinterpret_cast<Object**>(obj); // Read from SIRT
282 } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
283 // Assume an invalid local reference is actually a direct pointer.
284 result = reinterpret_cast<Object*>(obj);
285 } else {
286 LOG(FATAL) << "Invalid indirect reference " << obj;
287 result = reinterpret_cast<Object*>(kInvalidIndirectRefObject);
288 }
289 }
290
291 if (result == NULL) {
292 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
293 << obj;
294 }
295 Heap::VerifyObject(result);
296 return result;
297}
298
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700299void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700300 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700301 va_list args;
302 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700303 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700304 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700305
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700306 // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
307 CHECK(exception_class_descriptor[0] == 'L');
308 std::string descriptor(exception_class_descriptor + 1);
309 CHECK(descriptor[descriptor.length() - 1] == ';');
310 descriptor.erase(descriptor.length() - 1);
311
312 JNIEnv* env = GetJniEnv();
313 jclass exception_class = env->FindClass(descriptor.c_str());
314 CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
315 int rc = env->ThrowNew(exception_class, msg.c_str());
316 CHECK_EQ(rc, JNI_OK);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700317}
318
Elliott Hughes79082e32011-08-25 12:07:32 -0700319void Thread::ThrowOutOfMemoryError() {
320 UNIMPLEMENTED(FATAL);
321}
322
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700323Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
324 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
325 DCHECK(class_linker != NULL);
326
327 Frame cur_frame = GetTopOfStack();
328 for (int unwind_depth = 0; ; unwind_depth++) {
329 const Method* cur_method = cur_frame.GetMethod();
330 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
331 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
332
333 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
334 throw_pc,
335 dex_file,
336 class_linker);
337 if (handler_addr) {
338 *handler_pc = handler_addr;
339 return cur_frame;
340 } else {
341 // Check if we are at the last frame
342 if (cur_frame.HasNext()) {
343 cur_frame.Next();
344 } else {
345 // Either at the top of stack or next frame is native.
346 break;
347 }
348 }
349 }
350 *handler_pc = NULL;
351 return Frame();
352}
353
354void* Thread::FindExceptionHandlerInMethod(const Method* method,
355 void* throw_pc,
356 const DexFile& dex_file,
357 ClassLinker* class_linker) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700358 Throwable* exception_obj = exception_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700359 exception_ = NULL;
360
361 intptr_t dex_pc = -1;
362 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
363 DexFile::CatchHandlerIterator iter;
364 for (iter = dex_file.dexFindCatchHandler(*code_item,
365 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
366 !iter.HasNext();
367 iter.Next()) {
368 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
369 DCHECK(klass != NULL);
370 if (exception_obj->InstanceOf(klass)) {
371 dex_pc = iter.Get().address_;
372 break;
373 }
374 }
375
376 exception_ = exception_obj;
377 if (iter.HasNext()) {
378 return NULL;
379 } else {
380 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
381 }
382}
383
Ian Rogersb033c752011-07-20 12:22:35 -0700384static const char* kStateNames[] = {
385 "New",
386 "Runnable",
387 "Blocked",
388 "Waiting",
389 "TimedWaiting",
390 "Native",
391 "Terminated",
392};
393std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
394 if (state >= Thread::kNew && state <= Thread::kTerminated) {
395 os << kStateNames[state-Thread::kNew];
396 } else {
397 os << "State[" << static_cast<int>(state) << "]";
398 }
399 return os;
400}
401
Elliott Hughes330304d2011-08-12 14:28:05 -0700402std::ostream& operator<<(std::ostream& os, const Thread& thread) {
403 os << "Thread[" << &thread
404 << ",id=" << thread.GetId()
405 << ",tid=" << thread.GetNativeId()
406 << ",state=" << thread.GetState() << "]";
407 return os;
408}
409
Carl Shapiro61e019d2011-07-14 16:53:09 -0700410ThreadList* ThreadList::Create() {
411 return new ThreadList;
412}
413
Carl Shapirob5573532011-07-12 18:22:59 -0700414ThreadList::ThreadList() {
415 lock_ = Mutex::Create("ThreadList::Lock");
416}
417
418ThreadList::~ThreadList() {
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700419 if (Contains(Thread::Current())) {
420 Runtime::Current()->DetachCurrentThread();
421 }
422
423 // All threads should have exited and unregistered when we
Carl Shapirob5573532011-07-12 18:22:59 -0700424 // reach this point. This means that all daemon threads had been
425 // shutdown cleanly.
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700426 // TODO: dump ThreadList if non-empty.
427 CHECK_EQ(list_.size(), 0U);
428
Carl Shapirob5573532011-07-12 18:22:59 -0700429 delete lock_;
430 lock_ = NULL;
431}
432
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700433bool ThreadList::Contains(Thread* thread) {
434 return find(list_.begin(), list_.end(), thread) != list_.end();
435}
436
Carl Shapirob5573532011-07-12 18:22:59 -0700437void ThreadList::Register(Thread* thread) {
438 MutexLock mu(lock_);
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700439 CHECK(!Contains(thread));
Carl Shapirob5573532011-07-12 18:22:59 -0700440 list_.push_front(thread);
441}
442
443void ThreadList::Unregister(Thread* thread) {
444 MutexLock mu(lock_);
Elliott Hughesc1674ed2011-08-25 18:09:09 -0700445 CHECK(Contains(thread));
Carl Shapirob5573532011-07-12 18:22:59 -0700446 list_.remove(thread);
447}
448
Carl Shapirob5573532011-07-12 18:22:59 -0700449} // namespace