blob: f37dcbab6c4610955a476753affb4bd16ae855da [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"
Elliott Hughesc5f7c912011-08-18 14:00:42 -070012#include "jni_internal.h"
Elliott Hughesa5b897e2011-08-16 11:33:06 -070013#include "object.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070014#include "runtime.h"
15#include "utils.h"
buzbee54330722011-08-23 16:46:55 -070016#include "runtime_support.h"
Carl Shapirob5573532011-07-12 18:22:59 -070017
18namespace art {
19
20pthread_key_t Thread::pthread_key_self_;
21
buzbee3ea4ec52011-08-22 17:37:19 -070022void Thread::InitFunctionPointers() {
buzbee54330722011-08-23 16:46:55 -070023#if defined(__arm__)
24 pShlLong = art_shl_long;
25 pShrLong = art_shr_long;
26 pUshrLong = art_ushr_long;
27#endif
buzbee3ea4ec52011-08-22 17:37:19 -070028 pArtAllocArrayByClass = Array::Alloc;
29 pMemcpy = memcpy;
30#if 0
31//void* (Thread::*pMemcpy)(void*, const void*, size_t) /* = memcpy*/ ;
32float (Thread::*pI2f)(int);
33int (Thread::*pF2iz)(float);
34float (Thread::*pD2f)(double);
35double (Thread::*pF2d)(float);
36double (Thread::*pI2d)(int);
37int (Thread::*pD2iz)(double);
38float (Thread::*pL2f)(long);
39double (Thread::*pL2d)(long);
40long long (Thread::*pArtF2l)(float);
41long long (Thread::*pArtD2l)(double);
42float (Thread::*pFadd)(float, float);
43float (Thread::*pFsub)(float, float);
44float (Thread::*pFdiv)(float, float);
45float (Thread::*pFmul)(float, float);
46float (Thread::*pFmodf)(float, float);
47double (Thread::*pDadd)(double, double);
48double (Thread::*pDsub)(double, double);
49double (Thread::*pDdiv)(double, double);
50double (Thread::*pDmul)(double, double);
51double (Thread::*pFmod)(double, double);
52int (Thread::*pIdivmod)(int, int);
53int (Thread::*pIdiv)(int, int);
54long long (Thread::*pLdivmod)(long long, long long);
55bool (Thread::*pArtUnlockObject)(struct Thread*, struct Object*);
56bool (Thread::*pArtCanPutArrayElementNoThrow)(const struct ClassObject*,
57 const struct ClassObject*);
58int (Thread::*pArtInstanceofNonTrivialNoThrow)
59 (const struct ClassObject*, const struct ClassObject*);
60int (Thread::*pArtInstanceofNonTrivial) (const struct ClassObject*,
61 const struct ClassObject*);
62struct Method* (Thread::*pArtFindInterfaceMethodInCache)(ClassObject*, uint32_t,
63 const struct Method*, struct DvmDex*);
64bool (Thread::*pArtUnlockObjectNoThrow)(struct Thread*, struct Object*);
65void (Thread::*pArtLockObjectNoThrow)(struct Thread*, struct Object*);
66struct Object* (Thread::*pArtAllocObjectNoThrow)(struct ClassObject*, int);
67void (Thread::*pArtThrowException)(struct Thread*, struct Object*);
68bool (Thread::*pArtHandleFillArrayDataNoThrow)(struct ArrayObject*, const uint16_t*);
69#endif
70}
71
Carl Shapirob5573532011-07-12 18:22:59 -070072Mutex* Mutex::Create(const char* name) {
73 Mutex* mu = new Mutex(name);
74 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070075 CHECK_EQ(0, result);
Carl Shapirob5573532011-07-12 18:22:59 -070076 return mu;
77}
78
79void Mutex::Lock() {
80 int result = pthread_mutex_lock(&lock_impl_);
81 CHECK_EQ(result, 0);
82 SetOwner(Thread::Current());
83}
84
85bool Mutex::TryLock() {
86 int result = pthread_mutex_lock(&lock_impl_);
87 if (result == EBUSY) {
88 return false;
89 } else {
90 CHECK_EQ(result, 0);
91 SetOwner(Thread::Current());
92 return true;
93 }
94}
95
96void Mutex::Unlock() {
97 CHECK(GetOwner() == Thread::Current());
98 int result = pthread_mutex_unlock(&lock_impl_);
99 CHECK_EQ(result, 0);
Elliott Hughesf4c21c92011-08-19 17:31:31 -0700100 SetOwner(NULL);
Carl Shapirob5573532011-07-12 18:22:59 -0700101}
102
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700103void Frame::Next() {
104 byte* next_sp = reinterpret_cast<byte*>(sp_) +
105 GetMethod()->GetFrameSize();
106 sp_ = reinterpret_cast<const Method**>(next_sp);
107}
108
109void* Frame::GetPC() const {
110 byte* pc_addr = reinterpret_cast<byte*>(sp_) +
Ian Rogers762400c2011-08-23 12:14:16 -0700111 GetMethod()->GetReturnPcOffset();
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700112 return reinterpret_cast<void*>(pc_addr);
113}
114
115const Method* Frame::NextMethod() const {
116 byte* next_sp = reinterpret_cast<byte*>(sp_) +
117 GetMethod()->GetFrameSize();
118 return reinterpret_cast<const Method*>(next_sp);
119}
120
Carl Shapiro61e019d2011-07-14 16:53:09 -0700121void* ThreadStart(void *arg) {
Elliott Hughes53b61312011-08-12 18:28:20 -0700122 UNIMPLEMENTED(FATAL);
Carl Shapirob5573532011-07-12 18:22:59 -0700123 return NULL;
124}
125
Brian Carlstromb765be02011-08-17 23:54:10 -0700126Thread* Thread::Create(const Runtime* runtime) {
127 size_t stack_size = runtime->GetStackSize();
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700128 scoped_ptr<MemMap> stack(MemMap::Map(stack_size, PROT_READ | PROT_WRITE));
Brian Carlstromb765be02011-08-17 23:54:10 -0700129 if (stack == NULL) {
130 LOG(FATAL) << "failed to allocate thread stack";
131 // notreached
132 return NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -0700133 }
134
135 Thread* new_thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700136 new_thread->InitCpu();
Brian Carlstromb765be02011-08-17 23:54:10 -0700137 new_thread->stack_.reset(stack.release());
138 // Since stacks are assumed to grown downward the base is the limit and the limit is the base.
139 new_thread->stack_limit_ = stack->GetAddress();
140 new_thread->stack_base_ = stack->GetLimit();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700141
142 pthread_attr_t attr;
143 int result = pthread_attr_init(&attr);
144 CHECK_EQ(result, 0);
145
146 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
147 CHECK_EQ(result, 0);
148
149 pthread_t handle;
150 result = pthread_create(&handle, &attr, ThreadStart, new_thread);
151 CHECK_EQ(result, 0);
152
153 result = pthread_attr_destroy(&attr);
154 CHECK_EQ(result, 0);
155
156 return new_thread;
157}
158
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700159Thread* Thread::Attach(const Runtime* runtime) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700160 Thread* thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700161 thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700162 thread->stack_limit_ = reinterpret_cast<byte*>(-1); // TODO: getrlimit
163 uintptr_t addr = reinterpret_cast<uintptr_t>(&thread); // TODO: ask pthreads
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700164 uintptr_t stack_base = RoundUp(addr, kPageSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700165 thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
166 // TODO: set the stack size
167
168 thread->handle_ = pthread_self();
169
170 thread->state_ = kRunnable;
171
Elliott Hughesa5780da2011-07-17 11:39:39 -0700172 errno = pthread_setspecific(Thread::pthread_key_self_, thread);
173 if (errno != 0) {
174 PLOG(FATAL) << "pthread_setspecific failed";
175 }
176
Elliott Hughes0af55432011-08-17 18:37:28 -0700177 JavaVMExt* vm = runtime->GetJavaVM();
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700178 CHECK(vm != NULL);
179 bool check_jni = vm->check_jni;
180 thread->jni_env_ = reinterpret_cast<JNIEnv*>(new JNIEnvExt(thread, check_jni));
Elliott Hughes330304d2011-08-12 14:28:05 -0700181
Carl Shapiro61e019d2011-07-14 16:53:09 -0700182 return thread;
183}
184
Carl Shapirob5573532011-07-12 18:22:59 -0700185static void ThreadExitCheck(void* arg) {
186 LG << "Thread exit check";
187}
188
189bool Thread::Init() {
190 // Allocate a TLS slot.
191 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700192 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700193 return false;
194 }
195
196 // Double-check the TLS slot allocation.
197 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700198 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700199 return false;
200 }
201
202 // TODO: initialize other locks and condition variables
203
204 return true;
205}
206
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700207size_t Thread::NumShbHandles() {
208 size_t count = 0;
209 for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
210 count += cur->NumberOfReferences();
211 }
212 return count;
213}
214
215bool Thread::ShbContains(jobject obj) {
Brian Carlstrom4873d462011-08-21 15:23:39 -0700216 Object** shb_entry = reinterpret_cast<Object**>(obj);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700217 for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
218 size_t num_refs = cur->NumberOfReferences();
219 DCHECK_GT(num_refs, 0u); // A SHB should always have a jobject/jclass
220 if ((&cur->Handles()[0] >= shb_entry) &&
221 (shb_entry <= (&cur->Handles()[num_refs-1]))) {
222 return true;
223 }
224 }
225 return false;
226}
227
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700228void Thread::ThrowNewException(const char* exception_class_descriptor, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700229 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700230 va_list args;
231 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700232 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700233 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700234
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700235 // Convert "Ljava/lang/Exception;" into JNI-style "java/lang/Exception".
236 CHECK(exception_class_descriptor[0] == 'L');
237 std::string descriptor(exception_class_descriptor + 1);
238 CHECK(descriptor[descriptor.length() - 1] == ';');
239 descriptor.erase(descriptor.length() - 1);
240
241 JNIEnv* env = GetJniEnv();
242 jclass exception_class = env->FindClass(descriptor.c_str());
243 CHECK(exception_class != NULL) << "descriptor=\"" << descriptor << "\"";
244 int rc = env->ThrowNew(exception_class, msg.c_str());
245 CHECK_EQ(rc, JNI_OK);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700246}
247
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700248Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
249 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
250 DCHECK(class_linker != NULL);
251
252 Frame cur_frame = GetTopOfStack();
253 for (int unwind_depth = 0; ; unwind_depth++) {
254 const Method* cur_method = cur_frame.GetMethod();
255 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
256 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
257
258 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
259 throw_pc,
260 dex_file,
261 class_linker);
262 if (handler_addr) {
263 *handler_pc = handler_addr;
264 return cur_frame;
265 } else {
266 // Check if we are at the last frame
267 if (cur_frame.HasNext()) {
268 cur_frame.Next();
269 } else {
270 // Either at the top of stack or next frame is native.
271 break;
272 }
273 }
274 }
275 *handler_pc = NULL;
276 return Frame();
277}
278
279void* Thread::FindExceptionHandlerInMethod(const Method* method,
280 void* throw_pc,
281 const DexFile& dex_file,
282 ClassLinker* class_linker) {
Elliott Hughese5b0dc82011-08-23 09:59:02 -0700283 Throwable* exception_obj = exception_;
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700284 exception_ = NULL;
285
286 intptr_t dex_pc = -1;
287 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
288 DexFile::CatchHandlerIterator iter;
289 for (iter = dex_file.dexFindCatchHandler(*code_item,
290 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
291 !iter.HasNext();
292 iter.Next()) {
293 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
294 DCHECK(klass != NULL);
295 if (exception_obj->InstanceOf(klass)) {
296 dex_pc = iter.Get().address_;
297 break;
298 }
299 }
300
301 exception_ = exception_obj;
302 if (iter.HasNext()) {
303 return NULL;
304 } else {
305 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
306 }
307}
308
Ian Rogersb033c752011-07-20 12:22:35 -0700309static const char* kStateNames[] = {
310 "New",
311 "Runnable",
312 "Blocked",
313 "Waiting",
314 "TimedWaiting",
315 "Native",
316 "Terminated",
317};
318std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
319 if (state >= Thread::kNew && state <= Thread::kTerminated) {
320 os << kStateNames[state-Thread::kNew];
321 } else {
322 os << "State[" << static_cast<int>(state) << "]";
323 }
324 return os;
325}
326
Elliott Hughes330304d2011-08-12 14:28:05 -0700327std::ostream& operator<<(std::ostream& os, const Thread& thread) {
328 os << "Thread[" << &thread
329 << ",id=" << thread.GetId()
330 << ",tid=" << thread.GetNativeId()
331 << ",state=" << thread.GetState() << "]";
332 return os;
333}
334
Carl Shapiro61e019d2011-07-14 16:53:09 -0700335ThreadList* ThreadList::Create() {
336 return new ThreadList;
337}
338
Carl Shapirob5573532011-07-12 18:22:59 -0700339ThreadList::ThreadList() {
340 lock_ = Mutex::Create("ThreadList::Lock");
341}
342
343ThreadList::~ThreadList() {
344 // Make sure that all threads have exited and unregistered when we
345 // reach this point. This means that all daemon threads had been
346 // shutdown cleanly.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700347 CHECK_LE(list_.size(), 1U);
Carl Shapiro7a909592011-07-24 19:21:59 -0700348 // TODO: wait for all other threads to unregister
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700349 CHECK(list_.size() == 0 || list_.front() == Thread::Current());
Carl Shapiro7a909592011-07-24 19:21:59 -0700350 // TODO: detach the current thread
Carl Shapirob5573532011-07-12 18:22:59 -0700351 delete lock_;
352 lock_ = NULL;
353}
354
355void ThreadList::Register(Thread* thread) {
356 MutexLock mu(lock_);
357 CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
358 list_.push_front(thread);
359}
360
361void ThreadList::Unregister(Thread* thread) {
362 MutexLock mu(lock_);
363 CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
364 list_.remove(thread);
365}
366
Carl Shapirob5573532011-07-12 18:22:59 -0700367} // namespace