thread.h revision 578bbdc684db8ed68e9fedbc678669d27fa68b6e
1// Copyright 2011 Google Inc. All Rights Reserved. 2// Author: cshapiro@google.com (Carl Shapiro) 3 4#ifndef ART_SRC_THREAD_H_ 5#define ART_SRC_THREAD_H_ 6 7#include <pthread.h> 8#include <list> 9 10#include "globals.h" 11#include "jni_internal.h" 12#include "logging.h" 13#include "macros.h" 14#include "object.h" 15#include "offsets.h" 16#include "runtime.h" 17 18#include "jni.h" 19 20namespace art { 21 22class Object; 23class Runtime; 24class StackHandleBlock; 25class Thread; 26class ThreadList; 27 28class Mutex { 29 public: 30 virtual ~Mutex() {} 31 32 void Lock(); 33 34 bool TryLock(); 35 36 void Unlock(); 37 38 const char* GetName() { return name_; } 39 40 Thread* GetOwner() { return owner_; } 41 42 static Mutex* Create(const char* name); 43 44 public: // TODO: protected 45 explicit Mutex(const char* name) : name_(name), owner_(NULL) {} 46 47 void SetOwner(Thread* thread) { owner_ = thread; } 48 49 private: 50 const char* name_; 51 52 Thread* owner_; 53 54 pthread_mutex_t lock_impl_; 55 56 DISALLOW_COPY_AND_ASSIGN(Mutex); 57}; 58 59class MutexLock { 60 public: 61 explicit MutexLock(Mutex *mu) : mu_(mu) { 62 mu_->Lock(); 63 } 64 ~MutexLock() { mu_->Unlock(); } 65 private: 66 Mutex* const mu_; 67 DISALLOW_COPY_AND_ASSIGN(MutexLock); 68}; 69 70// Stack handle blocks are allocated within the bridge frame between managed 71// and native code. 72class StackHandleBlock { 73 public: 74 // Number of references contained within this SHB 75 size_t NumberOfReferences() { 76 return number_of_references_; 77 } 78 79 // Link to previous SHB or NULL 80 StackHandleBlock* Link() { 81 return link_; 82 } 83 84 // Offset of length within SHB, used by generated code 85 static size_t NumberOfReferencesOffset() { 86 return OFFSETOF_MEMBER(StackHandleBlock, number_of_references_); 87 } 88 89 // Offset of link within SHB, used by generated code 90 static size_t LinkOffset() { 91 return OFFSETOF_MEMBER(StackHandleBlock, link_); 92 } 93 94 private: 95 StackHandleBlock() {} 96 97 size_t number_of_references_; 98 StackHandleBlock* link_; 99 100 DISALLOW_COPY_AND_ASSIGN(StackHandleBlock); 101}; 102 103class Thread { 104 public: 105 enum State { 106 kUnknown = -1, 107 kNew, 108 kRunnable, 109 kBlocked, 110 kWaiting, 111 kTimedWaiting, 112 kNative, 113 kTerminated, 114 }; 115 116 static const size_t kDefaultStackSize = 64 * KB; 117 118 // Creates a new thread. 119 static Thread* Create(size_t stack_size); 120 121 // Creates a new thread from the calling thread. 122 static Thread* Attach(); 123 124 static Thread* Current() { 125 void* thread = pthread_getspecific(Thread::pthread_key_self_); 126 return reinterpret_cast<Thread*>(thread); 127 } 128 129 uint32_t GetId() const { 130 return id_; 131 } 132 133 pid_t GetNativeId() const { 134 return native_id_; 135 } 136 137 bool IsExceptionPending() const { 138 return false; // TODO exception_ != NULL; 139 } 140 141 Object* GetException() const { 142 return exception_; 143 } 144 145 void SetException(Object* new_exception) { 146 CHECK(new_exception != NULL); 147 // TODO: CHECK(exception_ == NULL); 148 exception_ = new_exception; // TODO 149 } 150 151 void ClearException() { 152 exception_ = NULL; 153 } 154 155 // Offset of exception within Thread, used by generated code 156 static ThreadOffset ExceptionOffset() { 157 return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_)); 158 } 159 160 void SetName(const char* name); 161 162 void Suspend(); 163 164 bool IsSuspended(); 165 166 void Resume(); 167 168 static bool Init(); 169 170 Runtime* GetRuntime() const { 171 return runtime_; 172 } 173 174 State GetState() { 175 return state_; 176 } 177 178 void SetState(State new_state) { 179 state_ = new_state; 180 } 181 182 static ThreadOffset SuspendCountOffset() { 183 return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_)); 184 } 185 186 // Offset of state within Thread, used by generated code 187 static ThreadOffset StateOffset() { 188 return ThreadOffset(OFFSETOF_MEMBER(Thread, state_)); 189 } 190 191 // JNI methods 192 JniEnvironment* GetJniEnv() const { 193 return jni_env_; 194 } 195 196 // Offset of JNI environment within Thread, used by generated code 197 static ThreadOffset JniEnvOffset() { 198 return ThreadOffset(OFFSETOF_MEMBER(Thread, jni_env_)); 199 } 200 201 // Offset of top of managed stack address, used by generated code 202 static ThreadOffset TopOfManagedStackOffset() { 203 return ThreadOffset(OFFSETOF_MEMBER(Thread, top_of_managed_stack_)); 204 } 205 206 // Offset of top stack handle block within Thread, used by generated code 207 static ThreadOffset TopShbOffset() { 208 return ThreadOffset(OFFSETOF_MEMBER(Thread, top_shb_)); 209 } 210 211 // Number of references allocated in StackHandleBlocks on this thread 212 size_t NumShbHandles() { 213 size_t count = 0; 214 for (StackHandleBlock* cur = top_shb_; cur; cur = cur->Link()) { 215 count += cur->NumberOfReferences(); 216 } 217 return count; 218 } 219 220 // Offset of exception_entry_point_ within Thread, used by generated code 221 static ThreadOffset ExceptionEntryPointOffset() { 222 return ThreadOffset(OFFSETOF_MEMBER(Thread, exception_entry_point_)); 223 } 224 225 void RegisterExceptionEntryPoint(void (*handler)(Method**)) { 226 exception_entry_point_ = handler; 227 } 228 229 // Offset of suspend_count_entry_point_ within Thread, used by generated code 230 static ThreadOffset SuspendCountEntryPointOffset() { 231 return ThreadOffset(OFFSETOF_MEMBER(Thread, suspend_count_entry_point_)); 232 } 233 234 void RegisterSuspendCountEntryPoint(void (*handler)(Method**)) { 235 suspend_count_entry_point_ = handler; 236 } 237 238 // Increasing the suspend count, will cause the thread to run to safepoint 239 void IncrementSuspendCount() { suspend_count_++; } 240 void DecrementSuspendCount() { suspend_count_--; } 241 242 private: 243 Thread() : 244 id_(1234), top_shb_(NULL), exception_(NULL), suspend_count_(0) { 245 jni_env_ = new JniEnvironment(); 246 } 247 248 ~Thread() { 249 delete jni_env_; 250 } 251 252 void InitCpu(); 253 254 // Managed thread id. 255 uint32_t id_; 256 257 // Top of the managed stack, written out prior to the state transition from 258 // kRunnable to kNative. Uses include to give the starting point for scanning 259 // a managed stack when a thread is in native code. 260 void* top_of_managed_stack_; 261 262 // Top of linked list of stack handle blocks or NULL for none 263 StackHandleBlock* top_shb_; 264 265 // Every thread may have an associated JNI environment 266 JniEnvironment* jni_env_; 267 268 State state_; 269 270 // Native (kernel) thread id. 271 pid_t native_id_; 272 273 // Native thread handle. 274 pthread_t handle_; 275 276 // Initialized to "this". On certain architectures (such as x86) reading 277 // off of Thread::Current is easy but getting the address of Thread::Current 278 // is hard. This field can be read off of Thread::Current to give the address. 279 Thread* self_; 280 281 Runtime* runtime_; 282 283 // The pending exception or NULL. 284 Object* exception_; 285 286 // A non-zero value is used to tell the current thread to enter a safe point 287 // at the next poll. 288 int suspend_count_; 289 290 // The inclusive base of the control stack. 291 byte* stack_base_; 292 293 // The exclusive limit of the control stack. 294 byte* stack_limit_; 295 296 // TLS key used to retrieve the VM thread object. 297 static pthread_key_t pthread_key_self_; 298 299 // Entry point called when exception_ is set 300 void (*exception_entry_point_)(Method** frame); 301 302 // Entry point called when suspend_count_ is non-zero 303 void (*suspend_count_entry_point_)(Method** frame); 304 305 DISALLOW_COPY_AND_ASSIGN(Thread); 306}; 307std::ostream& operator<<(std::ostream& os, const Thread::State& state); 308 309class ThreadList { 310 public: 311 static const int kMaxId = 0xFFFF; 312 static const int kInvalidId = 0; 313 static const int kMainId = 1; 314 315 static ThreadList* Create(); 316 317 ~ThreadList(); 318 319 void Register(Thread* thread); 320 321 void Unregister(Thread* thread); 322 323 void Lock() { 324 lock_->Lock(); 325 } 326 327 void Unlock() { 328 lock_->Unlock(); 329 }; 330 331 private: 332 ThreadList(); 333 334 std::list<Thread*> list_; 335 336 Mutex* lock_; 337 338 DISALLOW_COPY_AND_ASSIGN(ThreadList); 339}; 340 341class ThreadListLock { 342 public: 343 ThreadListLock(ThreadList* thread_list, Thread* current_thread) 344 : thread_list_(thread_list) { 345 if (current_thread == NULL) { // try to get it from TLS 346 current_thread = Thread::Current(); 347 } 348 Thread::State old_state; 349 if (current_thread != NULL) { 350 old_state = current_thread->GetState(); 351 current_thread->SetState(Thread::kWaiting); // TODO: VMWAIT 352 } else { 353 // happens during VM shutdown 354 old_state = Thread::kUnknown; // TODO: something else 355 } 356 thread_list_->Lock(); 357 if (current_thread != NULL) { 358 current_thread->SetState(old_state); 359 } 360 } 361 362 ~ThreadListLock() { 363 thread_list_->Unlock(); 364 } 365 366 private: 367 ThreadList* thread_list_; 368 369 DISALLOW_COPY_AND_ASSIGN(ThreadListLock); 370}; 371 372} // namespace art 373 374#endif // ART_SRC_THREAD_H_ 375