| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/thread.h" | 5 #include "vm/thread.h" |
| 6 | 6 |
| 7 #include "vm/growable_array.h" | 7 #include "vm/growable_array.h" |
| 8 #include "vm/isolate.h" | 8 #include "vm/isolate.h" |
| 9 #include "vm/lockers.h" | 9 #include "vm/lockers.h" |
| 10 #include "vm/object.h" | 10 #include "vm/object.h" |
| 11 #include "vm/os_thread.h" | 11 #include "vm/os_thread.h" |
| 12 #include "vm/profiler.h" | 12 #include "vm/profiler.h" |
| 13 #include "vm/stub_code.h" | 13 #include "vm/stub_code.h" |
| 14 #include "vm/thread_interrupter.h" | 14 #include "vm/thread_interrupter.h" |
| 15 #include "vm/thread_registry.h" | 15 #include "vm/thread_registry.h" |
| 16 | 16 |
| 17 namespace dart { | 17 namespace dart { |
| 18 | 18 |
| 19 // The single thread local key which stores all the thread local data | 19 // The single thread local key which stores all the thread local data |
| 20 // for a thread. | 20 // for a thread. |
| 21 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; | 21 ThreadLocalKey Thread::thread_key_ = OSThread::kUnsetThreadLocalKey; |
| 22 | 22 |
| 23 | 23 |
| 24 // Remove |thread| from each isolate's thread registry. |
| 25 class ThreadPruner : public IsolateVisitor { |
| 26 public: |
| 27 explicit ThreadPruner(Thread* thread) |
| 28 : thread_(thread) { |
| 29 ASSERT(thread_ != NULL); |
| 30 } |
| 31 |
| 32 void VisitIsolate(Isolate* isolate) { |
| 33 ThreadRegistry* registry = isolate->thread_registry(); |
| 34 ASSERT(registry != NULL); |
| 35 registry->PruneThread(thread_); |
| 36 } |
| 37 private: |
| 38 Thread* thread_; |
| 39 }; |
| 40 |
| 41 |
| 24 static void DeleteThread(void* thread) { | 42 static void DeleteThread(void* thread) { |
| 25 delete reinterpret_cast<Thread*>(thread); | 43 delete reinterpret_cast<Thread*>(thread); |
| 26 } | 44 } |
| 27 | 45 |
| 28 | 46 |
| 29 Thread::~Thread() { | 47 Thread::~Thread() { |
| 30 // We should cleanly exit any isolate before destruction. | 48 // We should cleanly exit any isolate before destruction. |
| 31 ASSERT(isolate_ == NULL); | 49 ASSERT(isolate_ == NULL); |
| 50 // Clear |this| from all isolate's thread registry. |
| 51 ThreadPruner pruner(this); |
| 52 Isolate::VisitIsolates(&pruner); |
| 32 } | 53 } |
| 33 | 54 |
| 34 | 55 |
| 35 void Thread::InitOnceBeforeIsolate() { | 56 void Thread::InitOnceBeforeIsolate() { |
| 36 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); | 57 ASSERT(thread_key_ == OSThread::kUnsetThreadLocalKey); |
| 37 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); | 58 thread_key_ = OSThread::CreateThreadLocal(DeleteThread); |
| 38 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); | 59 ASSERT(thread_key_ != OSThread::kUnsetThreadLocalKey); |
| 39 ASSERT(Thread::Current() == NULL); | 60 ASSERT(Thread::Current() == NULL); |
| 40 // Postpone initialization of VM constants for this first thread. | 61 // Allocate a new Thread and postpone initialization of VM constants for |
| 41 SetCurrent(new Thread(false)); | 62 // this first thread. |
| 63 Thread* thread = new Thread(false); |
| 64 // Verify that current thread was set. |
| 65 ASSERT(Thread::Current() == thread); |
| 42 } | 66 } |
| 43 | 67 |
| 44 | 68 |
| 45 void Thread::InitOnceAfterObjectAndStubCode() { | 69 void Thread::InitOnceAfterObjectAndStubCode() { |
| 46 Thread* thread = Thread::Current(); | 70 Thread* thread = Thread::Current(); |
| 47 ASSERT(thread != NULL); | 71 ASSERT(thread != NULL); |
| 48 ASSERT(thread->isolate() == Dart::vm_isolate()); | 72 ASSERT(thread->isolate() == Dart::vm_isolate()); |
| 49 thread->InitVMConstants(); | 73 thread->InitVMConstants(); |
| 50 } | 74 } |
| 51 | 75 |
| 52 | 76 |
| 53 void Thread::SetCurrent(Thread* current) { | 77 void Thread::SetCurrent(Thread* current) { |
| 54 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); | 78 OSThread::SetThreadLocal(thread_key_, reinterpret_cast<uword>(current)); |
| 55 } | 79 } |
| 56 | 80 |
| 57 | 81 |
| 58 void Thread::EnsureInit() { | 82 void Thread::EnsureInit() { |
| 59 if (Thread::Current() == NULL) { | 83 if (Thread::Current() == NULL) { |
| 60 SetCurrent(new Thread()); | 84 // Allocate a new Thread. |
| 85 Thread* thread = new Thread(); |
| 86 // Verify that current thread was set. |
| 87 ASSERT(Thread::Current() == thread); |
| 61 } | 88 } |
| 62 } | 89 } |
| 63 | 90 |
| 64 | 91 |
| 65 #if defined(TARGET_OS_WINDOWS) | 92 #if defined(TARGET_OS_WINDOWS) |
| 66 void Thread::CleanUp() { | 93 void Thread::CleanUp() { |
| 67 Thread* current = Current(); | 94 Thread* current = Current(); |
| 68 if (current != NULL) { | 95 if (current != NULL) { |
| 69 delete current; | 96 delete current; |
| 70 } | 97 } |
| 71 SetCurrent(NULL); | 98 SetCurrent(NULL); |
| 72 } | 99 } |
| 73 #endif | 100 #endif |
| 74 | 101 |
| 75 | 102 |
| 76 Thread::Thread(bool init_vm_constants) | 103 Thread::Thread(bool init_vm_constants) |
| 77 : isolate_(NULL), | 104 : id_(OSThread::GetCurrentThreadId()), |
| 105 isolate_(NULL), |
| 78 store_buffer_block_(NULL) { | 106 store_buffer_block_(NULL) { |
| 79 ClearState(); | 107 ClearState(); |
| 80 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ | 108 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
| 81 member_name = default_init_value; | 109 member_name = default_init_value; |
| 82 CACHED_CONSTANTS_LIST(DEFAULT_INIT) | 110 CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
| 83 #undef DEFAULT_INIT | 111 #undef DEFAULT_INIT |
| 84 if (init_vm_constants) { | 112 if (init_vm_constants) { |
| 85 InitVMConstants(); | 113 InitVMConstants(); |
| 86 } | 114 } |
| 115 SetCurrent(this); |
| 87 } | 116 } |
| 88 | 117 |
| 89 | 118 |
| 90 void Thread::InitVMConstants() { | 119 void Thread::InitVMConstants() { |
| 91 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ | 120 #define ASSERT_VM_HEAP(type_name, member_name, init_expr, default_init_value) \ |
| 92 ASSERT((init_expr)->IsOldObject()); | 121 ASSERT((init_expr)->IsOldObject()); |
| 93 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) | 122 CACHED_VM_OBJECTS_LIST(ASSERT_VM_HEAP) |
| 94 #undef ASSERT_VM_HEAP | 123 #undef ASSERT_VM_HEAP |
| 95 | 124 |
| 96 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ | 125 #define INIT_VALUE(type_name, member_name, init_expr, default_init_value) \ |
| (...skipping 27 matching lines...) Expand all Loading... |
| 124 ASSERT(thread->isolate() == NULL); | 153 ASSERT(thread->isolate() == NULL); |
| 125 ASSERT(!isolate->HasMutatorThread()); | 154 ASSERT(!isolate->HasMutatorThread()); |
| 126 thread->isolate_ = isolate; | 155 thread->isolate_ = isolate; |
| 127 isolate->MakeCurrentThreadMutator(thread); | 156 isolate->MakeCurrentThreadMutator(thread); |
| 128 isolate->set_vm_tag(VMTag::kVMTagId); | 157 isolate->set_vm_tag(VMTag::kVMTagId); |
| 129 ASSERT(thread->store_buffer_block_ == NULL); | 158 ASSERT(thread->store_buffer_block_ == NULL); |
| 130 thread->StoreBufferAcquire(); | 159 thread->StoreBufferAcquire(); |
| 131 ASSERT(isolate->heap() != NULL); | 160 ASSERT(isolate->heap() != NULL); |
| 132 thread->heap_ = isolate->heap(); | 161 thread->heap_ = isolate->heap(); |
| 133 thread->Schedule(isolate); | 162 thread->Schedule(isolate); |
| 134 ASSERT(thread->thread_state() == NULL); | |
| 135 InterruptableThreadState* thread_state = | |
| 136 ThreadInterrupter::GetCurrentThreadState(); | |
| 137 #if defined(DEBUG) | |
| 138 thread->set_thread_state(NULL); // Exclude thread itself from the dupe check. | |
| 139 Isolate::CheckForDuplicateThreadState(thread_state); | |
| 140 thread->set_thread_state(thread_state); | |
| 141 #endif | |
| 142 ASSERT(thread_state != NULL); | |
| 143 // TODO(koda): Migrate profiler interface to use Thread. | 163 // TODO(koda): Migrate profiler interface to use Thread. |
| 144 Profiler::BeginExecution(isolate); | 164 Profiler::BeginExecution(isolate); |
| 145 } | 165 } |
| 146 | 166 |
| 147 | 167 |
| 148 void Thread::ExitIsolate() { | 168 void Thread::ExitIsolate() { |
| 149 Thread* thread = Thread::Current(); | 169 Thread* thread = Thread::Current(); |
| 150 // TODO(koda): Audit callers; they should know whether they're in an isolate. | 170 // TODO(koda): Audit callers; they should know whether they're in an isolate. |
| 151 if (thread == NULL || thread->isolate() == NULL) return; | 171 if (thread == NULL || thread->isolate() == NULL) return; |
| 152 Isolate* isolate = thread->isolate(); | 172 Isolate* isolate = thread->isolate(); |
| 153 Profiler::EndExecution(isolate); | 173 Profiler::EndExecution(isolate); |
| 154 thread->set_thread_state(NULL); | |
| 155 thread->Unschedule(); | 174 thread->Unschedule(); |
| 156 // TODO(koda): Move store_buffer_block_ into State. | 175 // TODO(koda): Move store_buffer_block_ into State. |
| 157 thread->StoreBufferRelease(); | 176 thread->StoreBufferRelease(); |
| 158 if (isolate->is_runnable()) { | 177 if (isolate->is_runnable()) { |
| 159 isolate->set_vm_tag(VMTag::kIdleTagId); | 178 isolate->set_vm_tag(VMTag::kIdleTagId); |
| 160 } else { | 179 } else { |
| 161 isolate->set_vm_tag(VMTag::kLoadWaitTagId); | 180 isolate->set_vm_tag(VMTag::kLoadWaitTagId); |
| 162 } | 181 } |
| 163 isolate->ClearMutatorThread(); | 182 isolate->ClearMutatorThread(); |
| 164 thread->isolate_ = NULL; | 183 thread->isolate_ = NULL; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 return isolate_->cha_; | 271 return isolate_->cha_; |
| 253 } | 272 } |
| 254 | 273 |
| 255 | 274 |
| 256 void Thread::set_cha(CHA* value) { | 275 void Thread::set_cha(CHA* value) { |
| 257 ASSERT(isolate_ != NULL); | 276 ASSERT(isolate_ != NULL); |
| 258 isolate_->cha_ = value; | 277 isolate_->cha_ = value; |
| 259 } | 278 } |
| 260 | 279 |
| 261 | 280 |
| 281 void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, |
| 282 void* data) { |
| 283 ASSERT(Thread::Current() == this); |
| 284 thread_interrupt_callback_ = callback; |
| 285 thread_interrupt_data_ = data; |
| 286 } |
| 287 |
| 288 |
| 289 bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, |
| 290 void** data) const { |
| 291 #if defined(TARGET_OS_WINDOWS) |
| 292 // On Windows we expect this to be called from the thread interrupter thread. |
| 293 ASSERT(id() != OSThread::GetCurrentThreadId()); |
| 294 #else |
| 295 // On posix platforms, we expect this to be called from signal handler. |
| 296 ASSERT(id() == OSThread::GetCurrentThreadId()); |
| 297 #endif |
| 298 ASSERT(callback != NULL); |
| 299 ASSERT(data != NULL); |
| 300 *callback = thread_interrupt_callback_; |
| 301 *data = thread_interrupt_data_; |
| 302 return (*callback != NULL) && |
| 303 (*data != NULL); |
| 304 } |
| 305 |
| 306 |
| 262 bool Thread::CanLoadFromThread(const Object& object) { | 307 bool Thread::CanLoadFromThread(const Object& object) { |
| 263 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ | 308 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ |
| 264 if (object.raw() == expr) return true; | 309 if (object.raw() == expr) return true; |
| 265 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) | 310 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) |
| 266 #undef CHECK_OBJECT | 311 #undef CHECK_OBJECT |
| 267 return false; | 312 return false; |
| 268 } | 313 } |
| 269 | 314 |
| 270 | 315 |
| 271 intptr_t Thread::OffsetFromThread(const Object& object) { | 316 intptr_t Thread::OffsetFromThread(const Object& object) { |
| 272 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \ | 317 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \ |
| 273 ASSERT((expr)->IsVMHeapObject()); \ | 318 ASSERT((expr)->IsVMHeapObject()); \ |
| 274 if (object.raw() == expr) return Thread::member_name##offset(); | 319 if (object.raw() == expr) return Thread::member_name##offset(); |
| 275 CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET) | 320 CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET) |
| 276 #undef COMPUTE_OFFSET | 321 #undef COMPUTE_OFFSET |
| 277 UNREACHABLE(); | 322 UNREACHABLE(); |
| 278 return -1; | 323 return -1; |
| 279 } | 324 } |
| 280 | 325 |
| 281 } // namespace dart | 326 } // namespace dart |
| OLD | NEW |