blob: 0878b501738a25ef047f48159b1ce1ca4c94d3c5 [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 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
187bool Thread::Init() {
188 // Allocate a TLS slot.
189 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700190 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700191 return false;
192 }
193
194 // Double-check the TLS slot allocation.
195 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700196 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700197 return false;
198 }
199
200 // TODO: initialize other locks and condition variables
201
202 return true;
203}
204
Ian Rogers408f79a2011-08-23 18:22:33 -0700205size_t Thread::NumSirtReferences() {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700206 size_t count = 0;
Ian Rogers408f79a2011-08-23 18:22:33 -0700207 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700208 count += cur->NumberOfReferences();
209 }
210 return count;
211}
212
Ian Rogers408f79a2011-08-23 18:22:33 -0700213bool Thread::SirtContains(jobject obj) {
214 Object** sirt_entry = reinterpret_cast<Object**>(obj);
215 for (StackIndirectReferenceTable* cur = top_sirt_; cur; cur = cur->Link()) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700216 size_t num_refs = cur->NumberOfReferences();
Ian Rogers408f79a2011-08-23 18:22:33 -0700217 // A SIRT should always have a jobject/jclass as a native method is passed
218 // in a this pointer or a class
219 DCHECK_GT(num_refs, 0u);
220 if ((&cur->References()[0] >= sirt_entry) &&
221 (sirt_entry <= (&cur->References()[num_refs-1]))) {
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700222 return true;
223 }
224 }
225 return false;
226}
227
Ian Rogers408f79a2011-08-23 18:22:33 -0700228Object* Thread::DecodeJObject(jobject obj) {
229 // TODO: Only allowed to hold Object* when in the runnable state
230 // DCHECK(state_ == kRunnable);
231 if (obj == NULL) {
232 return NULL;
233 }
234 IndirectRef ref = reinterpret_cast<IndirectRef>(obj);
235 IndirectRefKind kind = GetIndirectRefKind(ref);
236 Object* result;
237 switch (kind) {
238 case kLocal:
239 {
Elliott Hughes69f5bc62011-08-24 09:26:14 -0700240 IndirectReferenceTable& locals = jni_env_->locals;
Ian Rogers408f79a2011-08-23 18:22:33 -0700241 result = locals.Get(ref);
242 break;
243 }
244 case kGlobal:
245 {
246 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
247 IndirectReferenceTable& globals = vm->globals;
248 MutexLock mu(vm->globals_lock);
249 result = globals.Get(ref);
250 break;
251 }
252 case kWeakGlobal:
253 {
254 JavaVMExt* vm = Runtime::Current()->GetJavaVM();
255 IndirectReferenceTable& weak_globals = vm->weak_globals;
256 MutexLock mu(vm->weak_globals_lock);
257 result = weak_globals.Get(ref);
258 if (result == kClearedJniWeakGlobal) {
259 // This is a special case where it's okay to return NULL.
260 return NULL;
261 }
262 break;
263 }
264 case kSirtOrInvalid:
265 default:
266 // TODO: make stack indirect reference table lookup more efficient
267 // Check if this is a local reference in the SIRT
268 if (SirtContains(obj)) {
269 result = *reinterpret_cast<Object**>(obj); // Read from SIRT
270 } else if (false /*gDvmJni.workAroundAppJniBugs*/) { // TODO
271 // Assume an invalid local reference is actually a direct pointer.
272 result = reinterpret_cast<Object*>(obj);
273 } else {
274 LOG(FATAL) << "Invalid indirect reference " << obj;
275 result = reinterpret_cast<Object*>(kInvalidIndirectRefObject);
276 }
277 }
278
279 if (result == NULL) {
280 LOG(FATAL) << "JNI ERROR (app bug): use of deleted " << kind << ": "
281 << obj;
282 }
283 Heap::VerifyObject(result);
284 return result;
285}
286
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700287void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700288 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700289 va_list args;
290 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700291 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700292 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700293
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700294 // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
295 CHECK(exception_class_descriptor[0] == 'L');
296 std::string descriptor(exception_class_descriptor + 1);
297 CHECK(descriptor[descriptor.length() - 1] == ';');
298 descriptor.erase(descriptor.length() - 1);
299
300 JNIEnv* env = GetJniEnv();
301 jclass exception_class = env->FindClass(descriptor.c_str());
302 CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
303 int rc = env->ThrowNew(exception_class, msg.c_str());
304 CHECK_EQ(rc, JNI_OK);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700305}
306
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700307Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
308 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
309 DCHECK(class_linker != NULL);
310
311 Frame cur_frame = GetTopOfStack();
312 for (int unwind_depth = 0; ; unwind_depth++) {
313 const Method* cur_method = cur_frame.GetMethod();
314 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
315 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
316
317 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
318 throw_pc,
319 dex_file,
320 class_linker);
321 if (handler_addr) {
322 *handler_pc = handler_addr;
323 return cur_frame;
324 } else {
325 // Check if we are at the last frame
326 if (cur_frame.HasNext()) {
327 cur_frame.Next();
328 } else {
329 // Either at the top of stack or next frame is native.
330 break;
331 }
332 }
333 }
334 *handler_pc = NULL;
335 return Frame();
336}
337
338void* Thread::FindExceptionHandlerInMethod(const Method* method,
339 void* throw_pc,
340 const DexFile& dex_file,
341 ClassLinker* class_linker) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700342 Throwable* exception_obj = exception_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700343 exception_ = NULL;
344
345 intptr_t dex_pc = -1;
346 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
347 DexFile::CatchHandlerIterator iter;
348 for (iter = dex_file.dexFindCatchHandler(*code_item,
349 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
350 !iter.HasNext();
351 iter.Next()) {
352 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
353 DCHECK(klass != NULL);
354 if (exception_obj->InstanceOf(klass)) {
355 dex_pc = iter.Get().address_;
356 break;
357 }
358 }
359
360 exception_ = exception_obj;
361 if (iter.HasNext()) {
362 return NULL;
363 } else {
364 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
365 }
366}
367
Ian Rogersb033c752011-07-20 12:22:35 -0700368static const char* kStateNames[] = {
369 "New",
370 "Runnable",
371 "Blocked",
372 "Waiting",
373 "TimedWaiting",
374 "Native",
375 "Terminated",
376};
377std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
378 if (state >= Thread::kNew && state <= Thread::kTerminated) {
379 os << kStateNames[state-Thread::kNew];
380 } else {
381 os << "State[" << static_cast<int>(state) << "]";
382 }
383 return os;
384}
385
Elliott Hughes330304d2011-08-12 14:28:05 -0700386std::ostream& operator<<(std::ostream& os, const Thread& thread) {
387 os << "Thread[" << &thread
388 << ",id=" << thread.GetId()
389 << ",tid=" << thread.GetNativeId()
390 << ",state=" << thread.GetState() << "]";
391 return os;
392}
393
Carl Shapiro61e019d2011-07-14 16:53:09 -0700394ThreadList* ThreadList::Create() {
395 return new ThreadList;
396}
397
Carl Shapirob5573532011-07-12 18:22:59 -0700398ThreadList::ThreadList() {
399 lock_ = Mutex::Create("ThreadList::Lock");
400}
401
402ThreadList::~ThreadList() {
403 // Make sure that all threads have exited and unregistered when we
404 // reach this point. This means that all daemon threads had been
405 // shutdown cleanly.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700406 CHECK_LE(list_.size(), 1U);
Carl Shapiro7a909592011-07-24 19:21:59 -0700407 // TODO: wait for all other threads to unregister
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700408 CHECK(list_.size() == 0 || list_.front() == Thread::Current());
Carl Shapiro7a909592011-07-24 19:21:59 -0700409 // TODO: detach the current thread
Carl Shapirob5573532011-07-12 18:22:59 -0700410 delete lock_;
411 lock_ = NULL;
412}
413
414void ThreadList::Register(Thread* thread) {
415 MutexLock mu(lock_);
416 CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
417 list_.push_front(thread);
418}
419
420void ThreadList::Unregister(Thread* thread) {
421 MutexLock mu(lock_);
422 CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
423 list_.remove(thread);
424}
425
Carl Shapirob5573532011-07-12 18:22:59 -0700426} // namespace