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 |