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