Chromium Code Reviews| 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 all isolate's thread registry. | |
|
koda
2015/08/20 14:55:53
(I'm not a native speaker, but shouldn't this be e
Cutch
2015/08/20 20:40:19
Done.
| |
| 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 // Postpone initialization of VM constants for this first thread. |
| 41 SetCurrent(new Thread(false)); | 62 SetCurrent(new Thread(false)); |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 67 Thread* current = Current(); | 88 Thread* current = Current(); |
| 68 if (current != NULL) { | 89 if (current != NULL) { |
| 69 delete current; | 90 delete current; |
| 70 } | 91 } |
| 71 SetCurrent(NULL); | 92 SetCurrent(NULL); |
| 72 } | 93 } |
| 73 #endif | 94 #endif |
| 74 | 95 |
| 75 | 96 |
| 76 Thread::Thread(bool init_vm_constants) | 97 Thread::Thread(bool init_vm_constants) |
| 77 : isolate_(NULL), | 98 : id_(OSThread::GetCurrentThreadId()), |
|
koda
2015/08/20 14:55:53
This should be in the same place as the call to Se
Cutch
2015/08/20 20:40:19
As discussed. I've moved the SetCurrent call into
| |
| 99 isolate_(NULL), | |
| 78 store_buffer_block_(NULL) { | 100 store_buffer_block_(NULL) { |
| 79 ClearState(); | 101 ClearState(); |
| 80 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ | 102 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ |
| 81 member_name = default_init_value; | 103 member_name = default_init_value; |
| 82 CACHED_CONSTANTS_LIST(DEFAULT_INIT) | 104 CACHED_CONSTANTS_LIST(DEFAULT_INIT) |
| 83 #undef DEFAULT_INIT | 105 #undef DEFAULT_INIT |
| 84 if (init_vm_constants) { | 106 if (init_vm_constants) { |
| 85 InitVMConstants(); | 107 InitVMConstants(); |
| 86 } | 108 } |
| 87 } | 109 } |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 124 ASSERT(thread->isolate() == NULL); | 146 ASSERT(thread->isolate() == NULL); |
| 125 ASSERT(!isolate->HasMutatorThread()); | 147 ASSERT(!isolate->HasMutatorThread()); |
| 126 thread->isolate_ = isolate; | 148 thread->isolate_ = isolate; |
| 127 isolate->MakeCurrentThreadMutator(thread); | 149 isolate->MakeCurrentThreadMutator(thread); |
| 128 isolate->set_vm_tag(VMTag::kVMTagId); | 150 isolate->set_vm_tag(VMTag::kVMTagId); |
| 129 ASSERT(thread->store_buffer_block_ == NULL); | 151 ASSERT(thread->store_buffer_block_ == NULL); |
| 130 thread->StoreBufferAcquire(); | 152 thread->StoreBufferAcquire(); |
| 131 ASSERT(isolate->heap() != NULL); | 153 ASSERT(isolate->heap() != NULL); |
| 132 thread->heap_ = isolate->heap(); | 154 thread->heap_ = isolate->heap(); |
| 133 thread->Schedule(isolate); | 155 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. | 156 // TODO(koda): Migrate profiler interface to use Thread. |
| 144 Profiler::BeginExecution(isolate); | 157 Profiler::BeginExecution(isolate); |
| 145 } | 158 } |
| 146 | 159 |
| 147 | 160 |
| 148 void Thread::ExitIsolate() { | 161 void Thread::ExitIsolate() { |
| 149 Thread* thread = Thread::Current(); | 162 Thread* thread = Thread::Current(); |
| 150 // TODO(koda): Audit callers; they should know whether they're in an isolate. | 163 // TODO(koda): Audit callers; they should know whether they're in an isolate. |
| 151 if (thread == NULL || thread->isolate() == NULL) return; | 164 if (thread == NULL || thread->isolate() == NULL) return; |
| 152 Isolate* isolate = thread->isolate(); | 165 Isolate* isolate = thread->isolate(); |
| 153 Profiler::EndExecution(isolate); | 166 Profiler::EndExecution(isolate); |
| 154 thread->set_thread_state(NULL); | |
| 155 thread->Unschedule(); | 167 thread->Unschedule(); |
| 156 // TODO(koda): Move store_buffer_block_ into State. | 168 // TODO(koda): Move store_buffer_block_ into State. |
| 157 thread->StoreBufferRelease(); | 169 thread->StoreBufferRelease(); |
| 158 if (isolate->is_runnable()) { | 170 if (isolate->is_runnable()) { |
| 159 isolate->set_vm_tag(VMTag::kIdleTagId); | 171 isolate->set_vm_tag(VMTag::kIdleTagId); |
| 160 } else { | 172 } else { |
| 161 isolate->set_vm_tag(VMTag::kLoadWaitTagId); | 173 isolate->set_vm_tag(VMTag::kLoadWaitTagId); |
| 162 } | 174 } |
| 163 isolate->ClearMutatorThread(); | 175 isolate->ClearMutatorThread(); |
| 164 thread->isolate_ = NULL; | 176 thread->isolate_ = NULL; |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 return isolate_->cha_; | 264 return isolate_->cha_; |
| 253 } | 265 } |
| 254 | 266 |
| 255 | 267 |
| 256 void Thread::set_cha(CHA* value) { | 268 void Thread::set_cha(CHA* value) { |
| 257 ASSERT(isolate_ != NULL); | 269 ASSERT(isolate_ != NULL); |
| 258 isolate_->cha_ = value; | 270 isolate_->cha_ = value; |
| 259 } | 271 } |
| 260 | 272 |
| 261 | 273 |
| 274 void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, | |
|
koda
2015/08/20 15:45:14
Consider ASSERT that this is only called on the cu
Cutch
2015/08/20 20:40:18
Done.
| |
| 275 void* data) { | |
| 276 thread_interrupt_callback_ = callback; | |
|
koda
2015/08/20 14:55:53
This update is not done atomically. Thus, if we ge
koda
2015/08/20 15:18:33
One way to make the interface safer is to remove t
Cutch
2015/08/20 20:40:18
I've removed the individual accessors. New API:
b
| |
| 277 thread_interrupt_data_ = data; | |
| 278 } | |
| 279 | |
| 280 | |
| 281 bool Thread::ShouldInterrupt() const { | |
|
koda
2015/08/20 15:45:14
Consider ASSERT that this is only called on the cu
Cutch
2015/08/20 20:40:19
Done.
| |
| 282 return (thread_interrupt_data_ != NULL) && | |
| 283 (thread_interrupt_callback_ != NULL); | |
| 284 } | |
| 285 | |
| 286 | |
| 262 bool Thread::CanLoadFromThread(const Object& object) { | 287 bool Thread::CanLoadFromThread(const Object& object) { |
| 263 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ | 288 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ |
| 264 if (object.raw() == expr) return true; | 289 if (object.raw() == expr) return true; |
| 265 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) | 290 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) |
| 266 #undef CHECK_OBJECT | 291 #undef CHECK_OBJECT |
| 267 return false; | 292 return false; |
| 268 } | 293 } |
| 269 | 294 |
| 270 | 295 |
| 271 intptr_t Thread::OffsetFromThread(const Object& object) { | 296 intptr_t Thread::OffsetFromThread(const Object& object) { |
| 272 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \ | 297 #define COMPUTE_OFFSET(type_name, member_name, expr, default_init_value) \ |
| 273 ASSERT((expr)->IsVMHeapObject()); \ | 298 ASSERT((expr)->IsVMHeapObject()); \ |
| 274 if (object.raw() == expr) return Thread::member_name##offset(); | 299 if (object.raw() == expr) return Thread::member_name##offset(); |
| 275 CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET) | 300 CACHED_VM_OBJECTS_LIST(COMPUTE_OFFSET) |
| 276 #undef COMPUTE_OFFSET | 301 #undef COMPUTE_OFFSET |
| 277 UNREACHABLE(); | 302 UNREACHABLE(); |
| 278 return -1; | 303 return -1; |
| 279 } | 304 } |
| 280 | 305 |
| 281 } // namespace dart | 306 } // namespace dart |
| OLD | NEW |