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 |