blob: db4c59f95b33d95a3a4e9dfe70a8cf6460ec52d0 [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"
Carl Shapirob5573532011-07-12 18:22:59 -070016
17namespace art {
18
19pthread_key_t Thread::pthread_key_self_;
20
21Mutex* Mutex::Create(const char* name) {
22 Mutex* mu = new Mutex(name);
23 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070024 CHECK_EQ(0, result);
Carl Shapirob5573532011-07-12 18:22:59 -070025 return mu;
26}
27
28void Mutex::Lock() {
29 int result = pthread_mutex_lock(&lock_impl_);
30 CHECK_EQ(result, 0);
31 SetOwner(Thread::Current());
32}
33
34bool Mutex::TryLock() {
35 int result = pthread_mutex_lock(&lock_impl_);
36 if (result == EBUSY) {
37 return false;
38 } else {
39 CHECK_EQ(result, 0);
40 SetOwner(Thread::Current());
41 return true;
42 }
43}
44
45void Mutex::Unlock() {
46 CHECK(GetOwner() == Thread::Current());
47 int result = pthread_mutex_unlock(&lock_impl_);
48 CHECK_EQ(result, 0);
Elliott Hughesf4c21c92011-08-19 17:31:31 -070049 SetOwner(NULL);
Carl Shapirob5573532011-07-12 18:22:59 -070050}
51
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -070052void Frame::Next() {
53 byte* next_sp = reinterpret_cast<byte*>(sp_) +
54 GetMethod()->GetFrameSize();
55 sp_ = reinterpret_cast<const Method**>(next_sp);
56}
57
58void* Frame::GetPC() const {
59 byte* pc_addr = reinterpret_cast<byte*>(sp_) +
60 GetMethod()->GetPcOffset();
61 return reinterpret_cast<void*>(pc_addr);
62}
63
64const Method* Frame::NextMethod() const {
65 byte* next_sp = reinterpret_cast<byte*>(sp_) +
66 GetMethod()->GetFrameSize();
67 return reinterpret_cast<const Method*>(next_sp);
68}
69
Carl Shapiro61e019d2011-07-14 16:53:09 -070070void* ThreadStart(void *arg) {
Elliott Hughes53b61312011-08-12 18:28:20 -070071 UNIMPLEMENTED(FATAL);
Carl Shapirob5573532011-07-12 18:22:59 -070072 return NULL;
73}
74
Brian Carlstromb765be02011-08-17 23:54:10 -070075Thread* Thread::Create(const Runtime* runtime) {
76 size_t stack_size = runtime->GetStackSize();
Brian Carlstrom4a289ed2011-08-16 17:17:49 -070077 scoped_ptr<MemMap> stack(MemMap::Map(stack_size, PROT_READ | PROT_WRITE));
Brian Carlstromb765be02011-08-17 23:54:10 -070078 if (stack == NULL) {
79 LOG(FATAL) << "failed to allocate thread stack";
80 // notreached
81 return NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -070082 }
83
84 Thread* new_thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -070085 new_thread->InitCpu();
Brian Carlstromb765be02011-08-17 23:54:10 -070086 new_thread->stack_.reset(stack.release());
87 // Since stacks are assumed to grown downward the base is the limit and the limit is the base.
88 new_thread->stack_limit_ = stack->GetAddress();
89 new_thread->stack_base_ = stack->GetLimit();
Carl Shapiro61e019d2011-07-14 16:53:09 -070090
91 pthread_attr_t attr;
92 int result = pthread_attr_init(&attr);
93 CHECK_EQ(result, 0);
94
95 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
96 CHECK_EQ(result, 0);
97
98 pthread_t handle;
99 result = pthread_create(&handle, &attr, ThreadStart, new_thread);
100 CHECK_EQ(result, 0);
101
102 result = pthread_attr_destroy(&attr);
103 CHECK_EQ(result, 0);
104
105 return new_thread;
106}
107
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700108Thread* Thread::Attach(const Runtime* runtime) {
Carl Shapiro61e019d2011-07-14 16:53:09 -0700109 Thread* thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -0700110 thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -0700111 thread->stack_limit_ = reinterpret_cast<byte*>(-1); // TODO: getrlimit
112 uintptr_t addr = reinterpret_cast<uintptr_t>(&thread); // TODO: ask pthreads
Brian Carlstromb0460ea2011-07-29 10:08:05 -0700113 uintptr_t stack_base = RoundUp(addr, kPageSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -0700114 thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
115 // TODO: set the stack size
116
117 thread->handle_ = pthread_self();
118
119 thread->state_ = kRunnable;
120
Elliott Hughesa5780da2011-07-17 11:39:39 -0700121 errno = pthread_setspecific(Thread::pthread_key_self_, thread);
122 if (errno != 0) {
123 PLOG(FATAL) << "pthread_setspecific failed";
124 }
125
Elliott Hughes0af55432011-08-17 18:37:28 -0700126 JavaVMExt* vm = runtime->GetJavaVM();
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700127 CHECK(vm != NULL);
128 bool check_jni = vm->check_jni;
129 thread->jni_env_ = reinterpret_cast<JNIEnv*>(new JNIEnvExt(thread, check_jni));
Elliott Hughes330304d2011-08-12 14:28:05 -0700130
Carl Shapiro61e019d2011-07-14 16:53:09 -0700131 return thread;
132}
133
Carl Shapirob5573532011-07-12 18:22:59 -0700134static void ThreadExitCheck(void* arg) {
135 LG << "Thread exit check";
136}
137
138bool Thread::Init() {
139 // Allocate a TLS slot.
140 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700141 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700142 return false;
143 }
144
145 // Double-check the TLS slot allocation.
146 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700147 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700148 return false;
149 }
150
151 // TODO: initialize other locks and condition variables
152
153 return true;
154}
155
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700156size_t Thread::NumShbHandles() {
157 size_t count = 0;
158 for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
159 count += cur->NumberOfReferences();
160 }
161 return count;
162}
163
164bool Thread::ShbContains(jobject obj) {
Brian Carlstrom4873d462011-08-21 15:23:39 -0700165 Object** shb_entry = reinterpret_cast<Object**>(obj);
Ian Rogersa8cd9f42011-08-19 16:43:41 -0700166 for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) {
167 size_t num_refs = cur->NumberOfReferences();
168 DCHECK_GT(num_refs, 0u); // A SHB should always have a jobject/jclass
169 if ((&cur->Handles()[0] >= shb_entry) &&
170 (shb_entry <= (&cur->Handles()[num_refs-1]))) {
171 return true;
172 }
173 }
174 return false;
175}
176
Elliott Hughes37f7a402011-08-22 18:56:01 -0700177void Thread::ThrowNewException(Class* exception_class, const char* msg) {
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700178 Object* exception = exception_class->NewInstance();
179 CHECK(exception != NULL);
180
Elliott Hughesbfaadc82011-08-18 17:36:58 -0700181 String* java_msg = String::AllocFromModifiedUtf8(msg);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700182 CHECK(java_msg != NULL);
183
184 // TODO: what if there's already a pending exception?
185 // TODO: support the other constructors.
186 Method* ctor = exception_class->FindDirectMethod("<init>", "(Ljava/lang/String;)V");
Elliott Hughes710a0cb2011-08-16 14:32:37 -0700187 CHECK(ctor != NULL);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700188
189 // TODO: need to *call* the constructor!
190 UNIMPLEMENTED(WARNING) << "can't call "
Brian Carlstrom9cff8e12011-08-18 16:47:29 -0700191 << exception_class->GetDescriptor()->ToModifiedUtf8() << ".<init> "
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700192 << "\"" << msg << "\"";
193
Elliott Hughes37f7a402011-08-22 18:56:01 -0700194 SetException(exception);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700195}
196
197void Thread::ThrowNewException(const char* exception_class_name, const char* fmt, ...) {
Elliott Hughes37f7a402011-08-22 18:56:01 -0700198 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
199 Class* exception_class = class_linker->FindSystemClass(exception_class_name);
200 CHECK(exception_class != NULL);
201
202 std::string msg;
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700203 va_list args;
204 va_start(args, fmt);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700205 StringAppendV(&msg, fmt, args);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700206 va_end(args);
Elliott Hughes37f7a402011-08-22 18:56:01 -0700207
208 ThrowNewException(exception_class, msg.c_str());
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700209}
210
Shih-wei Liao1a18c8c2011-08-14 17:47:36 -0700211Frame Thread::FindExceptionHandler(void* throw_pc, void** handler_pc) {
212 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
213 DCHECK(class_linker != NULL);
214
215 Frame cur_frame = GetTopOfStack();
216 for (int unwind_depth = 0; ; unwind_depth++) {
217 const Method* cur_method = cur_frame.GetMethod();
218 DexCache* dex_cache = cur_method->GetDeclaringClass()->GetDexCache();
219 const DexFile& dex_file = class_linker->FindDexFile(dex_cache);
220
221 void* handler_addr = FindExceptionHandlerInMethod(cur_method,
222 throw_pc,
223 dex_file,
224 class_linker);
225 if (handler_addr) {
226 *handler_pc = handler_addr;
227 return cur_frame;
228 } else {
229 // Check if we are at the last frame
230 if (cur_frame.HasNext()) {
231 cur_frame.Next();
232 } else {
233 // Either at the top of stack or next frame is native.
234 break;
235 }
236 }
237 }
238 *handler_pc = NULL;
239 return Frame();
240}
241
242void* Thread::FindExceptionHandlerInMethod(const Method* method,
243 void* throw_pc,
244 const DexFile& dex_file,
245 ClassLinker* class_linker) {
246 Object* exception_obj = exception_;
247 exception_ = NULL;
248
249 intptr_t dex_pc = -1;
250 const DexFile::CodeItem* code_item = dex_file.GetCodeItem(method->code_off_);
251 DexFile::CatchHandlerIterator iter;
252 for (iter = dex_file.dexFindCatchHandler(*code_item,
253 method->ToDexPC(reinterpret_cast<intptr_t>(throw_pc)));
254 !iter.HasNext();
255 iter.Next()) {
256 Class* klass = class_linker->FindSystemClass(dex_file.dexStringByTypeIdx(iter.Get().type_idx_));
257 DCHECK(klass != NULL);
258 if (exception_obj->InstanceOf(klass)) {
259 dex_pc = iter.Get().address_;
260 break;
261 }
262 }
263
264 exception_ = exception_obj;
265 if (iter.HasNext()) {
266 return NULL;
267 } else {
268 return reinterpret_cast<void*>( method->ToNativePC(dex_pc) );
269 }
270}
271
Ian Rogersb033c752011-07-20 12:22:35 -0700272static const char* kStateNames[] = {
273 "New",
274 "Runnable",
275 "Blocked",
276 "Waiting",
277 "TimedWaiting",
278 "Native",
279 "Terminated",
280};
281std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
282 if (state >= Thread::kNew && state <= Thread::kTerminated) {
283 os << kStateNames[state-Thread::kNew];
284 } else {
285 os << "State[" << static_cast<int>(state) << "]";
286 }
287 return os;
288}
289
Elliott Hughes330304d2011-08-12 14:28:05 -0700290std::ostream& operator<<(std::ostream& os, const Thread& thread) {
291 os << "Thread[" << &thread
292 << ",id=" << thread.GetId()
293 << ",tid=" << thread.GetNativeId()
294 << ",state=" << thread.GetState() << "]";
295 return os;
296}
297
Carl Shapiro61e019d2011-07-14 16:53:09 -0700298ThreadList* ThreadList::Create() {
299 return new ThreadList;
300}
301
Carl Shapirob5573532011-07-12 18:22:59 -0700302ThreadList::ThreadList() {
303 lock_ = Mutex::Create("ThreadList::Lock");
304}
305
306ThreadList::~ThreadList() {
307 // Make sure that all threads have exited and unregistered when we
308 // reach this point. This means that all daemon threads had been
309 // shutdown cleanly.
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700310 CHECK_LE(list_.size(), 1U);
Carl Shapiro7a909592011-07-24 19:21:59 -0700311 // TODO: wait for all other threads to unregister
Brian Carlstrom4a289ed2011-08-16 17:17:49 -0700312 CHECK(list_.size() == 0 || list_.front() == Thread::Current());
Carl Shapiro7a909592011-07-24 19:21:59 -0700313 // TODO: detach the current thread
Carl Shapirob5573532011-07-12 18:22:59 -0700314 delete lock_;
315 lock_ = NULL;
316}
317
318void ThreadList::Register(Thread* thread) {
319 MutexLock mu(lock_);
320 CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
321 list_.push_front(thread);
322}
323
324void ThreadList::Unregister(Thread* thread) {
325 MutexLock mu(lock_);
326 CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
327 list_.remove(thread);
328}
329
Carl Shapirob5573532011-07-12 18:22:59 -0700330} // namespace