Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(412)

Side by Side Diff: runtime/vm/thread.cc

Issue 1293253005: Completely remove InterruptableThreadState and Fix ThreadRegistry leak (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
OLDNEW
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_interrupter.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698