blob: 477b14974cffa68e550a6168b2ec267ba3e4942a [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) {
175 PLOG(FATAL) << "pthread_setspecific failed";
176 }
177
Elliott Hughes0af55432011-08-17 18:37:28 -0700178 JavaVMExt* vm = runtime->GetJavaVM();
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700179 CHECK(vm != NULL);
180 bool check_jni = vm->check_jni;
Elliott Hughes69f5bc62011-08-24 09:26:14 -0700181 thread->jni_env_ = new JNIEnvExt(thread, check_jni);
Elliott Hughes330304d2011-08-12 14:28:05 -0700182
Carl Shapiro61e019d2011-07-14 16:53:09 -0700183 return thread;
184}
185
Carl Shapirob5573532011-07-12 18:22:59 -0700186static void ThreadExitCheck(void* arg) {
187 LG << "Thread exit check";
188}
189
190bool Thread::Init() {
191 // Allocate a TLS slot.
192 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700193 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700194 return false;
195 }
196
197 // Double-check the TLS slot allocation.
198 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700199 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700200 return false;
201 }
202
203 // TODO: initialize other locks and condition variables
204
205 return true;
206}
207
Ian Rogers408f79a2011-08-23 18:22:33 -0700208size_t Thread::NumSirtReferences() {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700209 size_t count = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700210 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700211 count += cur->NumberOfReferences();
212 }
213 return count;
214}
215
Ian Rogers408f79a2011-08-23 18:22:33 -0700216bool Thread::SirtContains(jobject obj) {
217 Object** sirt_entry = reinterpret_cast<Object**>(obj);
218 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700219 size_t num_refs = cur->NumberOfReferences();
Ian Rogers408f79a2011-08-23 18:22:33 -0700220 // A SIRT should always have a jobject/jclass as a native method is passed
221 // in a this pointer or a class
222 DCHECK_GT(num_refs, 0u);
223 if ((&cur->References()[0] >= sirt_entry) &&
224 (sirt_entry <= (&cur->References()[num_refs-1]))) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700225 return true;
226 }
227 }
228 return false;
229}
230
Ian Rogers408f79a2011-08-23 18:22:33 -0700231Object* Thread::DecodeJObject(jobject obj) {
232 // TODO: Only allowed to hold Object* when in the runnable state
233 // DCHECK(state_ == kRunnable);
234 if (obj == NULL) {
235 return NULL;
236 }
237 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
238 IndirectRefKind kind = GetIndirectRefKind(ref);
239 Object* result;
240 switch (kind) {
241 case kLocal:
242 {
Elliott Hughes69f5bc62011-08-24 09:26:14 -0700243 IndirectReferenceTable& locals = jni_env_->locals;
Ian Rogers408f79a2011-08-23 18:22:33 -0700244 result = locals.Get(ref);
245 break;
246 }
247 case kGlobal:
248 {
249 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
250 IndirectReferenceTable& globals = vm->globals;
251 MutexLock mu(vm->globals_lock);
252 result = globals.Get(ref);
253 break;
254 }
255 case kWeakGlobal:
256 {
257 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
258 IndirectReferenceTable& weak_globals = vm->weak_globals;
259 MutexLock mu(vm->weak_globals_lock);
260 result = weak_globals.Get(ref);
261 if (result == kClearedJniWeakGlobal) {
262 // This is a special case where it's okay to return NULL.
263 return NULL;
264 }
265 break;
266 }
267 case kSirtOrInvalid:
268 default:
269 // TODO: make stack indirect reference table lookup more efficient
270 // Check if this is a local reference in the SIRT
271 if (SirtContains(obj)) {
272 result = *reinterpret_cast<Object**>(obj); // Read from SIRT
273 } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
274 // Assume an invalid local reference is actually a direct pointer.
275 result = reinterpret_cast<Object*>(obj);
276 } else {
277 LOG(FATAL) << "Invalid indirect reference " << obj;
278 result = reinterpret_cast<Object*>(kInvalidIndirectRefObject);
279 }
280 }
281
282 if (result == NULL) {
283 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
284 << obj;
285 }
286 Heap::VerifyObject(result);
287 return result;
288}
289
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700290void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700291 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700292 va_list args;
293 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700294 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700295 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700296
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700297 // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
298 CHECK(exception_class_descriptor[0] == 'L');
299 std::string descriptor(exception_class_descriptor + 1);
300 CHECK(descriptor[descriptor.length() - 1] == ';');
301 descriptor.erase(descriptor.length() - 1);
302
303 JNIEnv* env = GetJniEnv();
304 jclass exception_class = env->FindClass(descriptor.c_str());
305 CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
306 int rc = env->ThrowNew(exception_class, msg.c_str());
307 CHECK_EQ(rc, JNI_OK);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700308}
309
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700310Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
311 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
312 DCHECK(class_linker != NULL);
313
314 Frame cur_frame = GetTopOfStack();
315 for (int unwind_depth = 0; ; unwind_depth++) {
316 const Method* cur_method = cur_frame.GetMethod();
317 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
318 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
319
320 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
321 throw_pc,
322 dex_file,
323 class_linker);
324 if (handler_addr) {
325 *handler_pc = handler_addr;
326 return cur_frame;
327 } else {
328 // Check if we are at the last frame
329 if (cur_frame.HasNext()) {
330 cur_frame.Next();
331 } else {
332 // Either at the top of stack or next frame is native.
333 break;
334 }
335 }
336 }
337 *handler_pc = NULL;
338 return Frame();
339}
340
341void* Thread::FindExceptionHandlerInMethod(const Method* method,
342 void* throw_pc,
343 const DexFile& dex_file,
344 ClassLinker* class_linker) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700345 Throwable* exception_obj = exception_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700346 exception_ = NULL;
347
348 intptr_t dex_pc = -1;
349 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
350 DexFile::CatchHandlerIterator iter;
351 for (iter = dex_file.dexFindCatchHandler(*code_item,
352 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
353 !iter.HasNext();
354 iter.Next()) {
355 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
356 DCHECK(klass != NULL);
357 if (exception_obj->InstanceOf(klass)) {
358 dex_pc = iter.Get().address_;
359 break;
360 }
361 }
362
363 exception_ = exception_obj;
364 if (iter.HasNext()) {
365 return NULL;
366 } else {
367 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
368 }
369}
370
Ian Rogersb033c752011-07-20 12:22:35 -0700371static const char* kStateNames[] = {
372 "New",
373 "Runnable",
374 "Blocked",
375 "Waiting",
376 "TimedWaiting",
377 "Native",
378 "Terminated",
379};
380std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
381 if (state >= Thread::kNew && state <= Thread::kTerminated) {
382 os << kStateNames[state-Thread::kNew];
383 } else {
384 os << "State[" << static_cast<int>(state) << "]";
385 }
386 return os;
387}
388
Elliott Hughes330304d2011-08-12 14:28:05 -0700389std::ostream& operator<<(std::ostream& os, const Thread& thread) {
390 os << "Thread[" << &thread
391 << ",id=" << thread.GetId()
392 << ",tid=" << thread.GetNativeId()
393 << ",state=" << thread.GetState() << "]";
394 return os;
395}
396
Carl Shapiro61e019d2011-07-14 16:53:09 -0700397ThreadList* ThreadList::Create() {
398 return new ThreadList;
399}
400
Carl Shapirob5573532011-07-12 18:22:59 -0700401ThreadList::ThreadList() {
402 lock_ = Mutex::Create("ThreadList::Lock");
403}
404
405ThreadList::~ThreadList() {
406 // Make sure that all threads have exited and unregistered when we
407 // reach this point. This means that all daemon threads had been
408 // shutdown cleanly.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700409 CHECK_LE(list_.size(), 1U);
Carl Shapiro7a909592011-07-24 19:21:59 -0700410 // TODO: wait for all other threads to unregister
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700411 CHECK(list_.size() == 0 || list_.front() == Thread::Current());
Carl Shapiro7a909592011-07-24 19:21:59 -0700412 // TODO: detach the current thread
Carl Shapirob5573532011-07-12 18:22:59 -0700413 delete lock_;
414 lock_ = NULL;
415}
416
417void ThreadList::Register(Thread* thread) {
418 MutexLock mu(lock_);
419 CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
420 list_.push_front(thread);
421}
422
423void ThreadList::Unregister(Thread* thread) {
424 MutexLock mu(lock_);
425 CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
426 list_.remove(thread);
427}
428
Carl Shapirob5573532011-07-12 18:22:59 -0700429} // namespace