blob: aa3fe9569c08e5167d38432d1b832a9902fcbc5c [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"
12#include "object.h"
Brian Carlstrom578bbdc2011-07-21 14:07:47 -070013#include "runtime.h"
14#include "utils.h"
Carl Shapirob5573532011-07-12 18:22:59 -070015
16namespace art {
17
18pthread_key_t Thread::pthread_key_self_;
19
20Mutex* Mutex::Create(const char* name) {
21 Mutex* mu = new Mutex(name);
22 int result = pthread_mutex_init(&mu->lock_impl_, NULL);
Ian Rogersb033c752011-07-20 12:22:35 -070023 CHECK_EQ(0, result);
Carl Shapirob5573532011-07-12 18:22:59 -070024 return mu;
25}
26
27void Mutex::Lock() {
28 int result = pthread_mutex_lock(&lock_impl_);
29 CHECK_EQ(result, 0);
30 SetOwner(Thread::Current());
31}
32
33bool Mutex::TryLock() {
34 int result = pthread_mutex_lock(&lock_impl_);
35 if (result == EBUSY) {
36 return false;
37 } else {
38 CHECK_EQ(result, 0);
39 SetOwner(Thread::Current());
40 return true;
41 }
42}
43
44void Mutex::Unlock() {
45 CHECK(GetOwner() == Thread::Current());
46 int result = pthread_mutex_unlock(&lock_impl_);
47 CHECK_EQ(result, 0);
48 SetOwner(Thread::Current());
49}
50
Carl Shapiro61e019d2011-07-14 16:53:09 -070051void* ThreadStart(void *arg) {
Elliott Hughes53b61312011-08-12 18:28:20 -070052 UNIMPLEMENTED(FATAL);
Carl Shapirob5573532011-07-12 18:22:59 -070053 return NULL;
54}
55
Brian Carlstromb765be02011-08-17 23:54:10 -070056Thread* Thread::Create(const Runtime* runtime) {
57 size_t stack_size = runtime->GetStackSize();
58 scoped_ptr<MemMap> stack(MemMap::Map(stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE));
59 if (stack == NULL) {
60 LOG(FATAL) << "failed to allocate thread stack";
61 // notreached
62 return NULL;
Carl Shapiro61e019d2011-07-14 16:53:09 -070063 }
64
65 Thread* new_thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -070066 new_thread->InitCpu();
Brian Carlstromb765be02011-08-17 23:54:10 -070067 new_thread->stack_.reset(stack.release());
68 // Since stacks are assumed to grown downward the base is the limit and the limit is the base.
69 new_thread->stack_limit_ = stack->GetAddress();
70 new_thread->stack_base_ = stack->GetLimit();
Carl Shapiro61e019d2011-07-14 16:53:09 -070071
72 pthread_attr_t attr;
73 int result = pthread_attr_init(&attr);
74 CHECK_EQ(result, 0);
75
76 result = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
77 CHECK_EQ(result, 0);
78
79 pthread_t handle;
80 result = pthread_create(&handle, &attr, ThreadStart, new_thread);
81 CHECK_EQ(result, 0);
82
83 result = pthread_attr_destroy(&attr);
84 CHECK_EQ(result, 0);
85
86 return new_thread;
87}
88
Elliott Hughes515a5bc2011-08-17 11:08:34 -070089Thread* Thread::Attach(const Runtime* runtime) {
Carl Shapiro61e019d2011-07-14 16:53:09 -070090 Thread* thread = new Thread;
Ian Rogers176f59c2011-07-20 13:14:11 -070091 thread->InitCpu();
Carl Shapiro61e019d2011-07-14 16:53:09 -070092 thread->stack_limit_ = reinterpret_cast<byte*>(-1); // TODO: getrlimit
93 uintptr_t addr = reinterpret_cast<uintptr_t>(&thread); // TODO: ask pthreads
Brian Carlstromb0460ea2011-07-29 10:08:05 -070094 uintptr_t stack_base = RoundUp(addr, kPageSize);
Carl Shapiro61e019d2011-07-14 16:53:09 -070095 thread->stack_base_ = reinterpret_cast<byte*>(stack_base);
96 // TODO: set the stack size
97
98 thread->handle_ = pthread_self();
99
100 thread->state_ = kRunnable;
101
Elliott Hughesa5780da2011-07-17 11:39:39 -0700102 errno = pthread_setspecific(Thread::pthread_key_self_, thread);
103 if (errno != 0) {
104 PLOG(FATAL) << "pthread_setspecific failed";
105 }
106
Elliott Hughes0af55432011-08-17 18:37:28 -0700107 JavaVMExt* vm = runtime->GetJavaVM();
Elliott Hughes515a5bc2011-08-17 11:08:34 -0700108 CHECK(vm != NULL);
109 bool check_jni = vm->check_jni;
110 thread->jni_env_ = reinterpret_cast<JNIEnv*>(new JNIEnvExt(thread, check_jni));
Elliott Hughes330304d2011-08-12 14:28:05 -0700111
Carl Shapiro61e019d2011-07-14 16:53:09 -0700112 return thread;
113}
114
Carl Shapirob5573532011-07-12 18:22:59 -0700115static void ThreadExitCheck(void* arg) {
116 LG << "Thread exit check";
117}
118
119bool Thread::Init() {
120 // Allocate a TLS slot.
121 if (pthread_key_create(&Thread::pthread_key_self_, ThreadExitCheck) != 0) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700122 PLOG(WARNING) << "pthread_key_create failed";
Carl Shapirob5573532011-07-12 18:22:59 -0700123 return false;
124 }
125
126 // Double-check the TLS slot allocation.
127 if (pthread_getspecific(pthread_key_self_) != NULL) {
Elliott Hugheseb4f6142011-07-15 17:43:51 -0700128 LOG(WARNING) << "newly-created pthread TLS slot is not NULL";
Carl Shapirob5573532011-07-12 18:22:59 -0700129 return false;
130 }
131
132 // TODO: initialize other locks and condition variables
133
134 return true;
135}
136
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700137void ThrowNewException(Thread* thread, const char* exception_class_name, const char* msg) {
138 CHECK(thread != NULL);
139
140 ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
141 Class* exception_class = class_linker->FindSystemClass(exception_class_name);
142 CHECK(exception_class != NULL);
143
144 Object* exception = exception_class->NewInstance();
145 CHECK(exception != NULL);
146
147 size_t char_count = String::ModifiedUtf8Len(msg);
148 String* java_msg = String::AllocFromModifiedUtf8(char_count, msg);
149 CHECK(java_msg != NULL);
150
151 // TODO: what if there's already a pending exception?
152 // TODO: support the other constructors.
153 Method* ctor = exception_class->FindDirectMethod("<init>", "(Ljava/lang/String;)V");
Elliott Hughes710a0cb2011-08-16 14:32:37 -0700154 CHECK(ctor != NULL);
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700155
156 // TODO: need to *call* the constructor!
157 UNIMPLEMENTED(WARNING) << "can't call "
Elliott Hughes710a0cb2011-08-16 14:32:37 -0700158 << exception_class->GetDescriptor() << ".<init> "
Elliott Hughesa5b897e2011-08-16 11:33:06 -0700159 << "\"" << msg << "\"";
160
161 thread->SetException(exception);
162}
163
164void ThrowNewExceptionV(Thread* thread, const char* exception_class_name, const char* fmt, va_list args) {
165 char msg[512];
166 vsnprintf(msg, sizeof(msg), fmt, args);
167 ThrowNewException(thread, exception_class_name, msg);
168}
169
170void Thread::ThrowNewException(const char* exception_class_name, const char* fmt, ...) {
171 va_list args;
172 va_start(args, fmt);
173 ThrowNewExceptionV(this, exception_class_name, fmt, args);
174 va_end(args);
175}
176
Ian Rogersb033c752011-07-20 12:22:35 -0700177static const char* kStateNames[] = {
178 "New",
179 "Runnable",
180 "Blocked",
181 "Waiting",
182 "TimedWaiting",
183 "Native",
184 "Terminated",
185};
186std::ostream& operator<<(std::ostream& os, const Thread::State& state) {
187 if (state >= Thread::kNew && state <= Thread::kTerminated) {
188 os << kStateNames[state-Thread::kNew];
189 } else {
190 os << "State[" << static_cast<int>(state) << "]";
191 }
192 return os;
193}
194
Elliott Hughes330304d2011-08-12 14:28:05 -0700195std::ostream& operator<<(std::ostream& os, const Thread& thread) {
196 os << "Thread[" << &thread
197 << ",id=" << thread.GetId()
198 << ",tid=" << thread.GetNativeId()
199 << ",state=" << thread.GetState() << "]";
200 return os;
201}
202
Carl Shapiro61e019d2011-07-14 16:53:09 -0700203ThreadList* ThreadList::Create() {
204 return new ThreadList;
205}
206
Carl Shapirob5573532011-07-12 18:22:59 -0700207ThreadList::ThreadList() {
208 lock_ = Mutex::Create("ThreadList::Lock");
209}
210
211ThreadList::~ThreadList() {
212 // Make sure that all threads have exited and unregistered when we
213 // reach this point. This means that all daemon threads had been
214 // shutdown cleanly.
Carl Shapiro7a909592011-07-24 19:21:59 -0700215 CHECK_EQ(list_.size(), 1U);
216 // TODO: wait for all other threads to unregister
217 CHECK_EQ(list_.front(), Thread::Current());
218 // TODO: detach the current thread
Carl Shapirob5573532011-07-12 18:22:59 -0700219 delete lock_;
220 lock_ = NULL;
221}
222
223void ThreadList::Register(Thread* thread) {
224 MutexLock mu(lock_);
225 CHECK(find(list_.begin(), list_.end(), thread) == list_.end());
226 list_.push_front(thread);
227}
228
229void ThreadList::Unregister(Thread* thread) {
230 MutexLock mu(lock_);
231 CHECK(find(list_.begin(), list_.end(), thread) != list_.end());
232 list_.remove(thread);
233}
234
Carl Shapirob5573532011-07-12 18:22:59 -0700235} // namespace