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

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

Issue 1541073002: Implement safepointing of threads (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: fix-typo Created 4 years, 10 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_registry.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/dart_api_state.h" 7 #include "vm/dart_api_state.h"
8 #include "vm/growable_array.h" 8 #include "vm/growable_array.h"
9 #include "vm/isolate.h" 9 #include "vm/isolate.h"
10 #include "vm/lockers.h" 10 #include "vm/lockers.h"
(...skipping 23 matching lines...) Expand all
34 #define REUSABLE_HANDLE_SCOPE_INIT(object) 34 #define REUSABLE_HANDLE_SCOPE_INIT(object)
35 #endif // defined(DEBUG) 35 #endif // defined(DEBUG)
36 36
37 #define REUSABLE_HANDLE_INITIALIZERS(object) \ 37 #define REUSABLE_HANDLE_INITIALIZERS(object) \
38 object##_handle_(NULL), 38 object##_handle_(NULL),
39 39
40 40
41 Thread::Thread(Isolate* isolate) 41 Thread::Thread(Isolate* isolate)
42 : BaseThread(false), 42 : BaseThread(false),
43 os_thread_(NULL), 43 os_thread_(NULL),
44 thread_lock_(new Monitor()),
44 isolate_(NULL), 45 isolate_(NULL),
45 heap_(NULL), 46 heap_(NULL),
46 zone_(NULL), 47 zone_(NULL),
47 api_reusable_scope_(NULL), 48 api_reusable_scope_(NULL),
48 api_top_scope_(NULL), 49 api_top_scope_(NULL),
49 top_exit_frame_info_(0), 50 top_exit_frame_info_(0),
50 top_resource_(NULL), 51 top_resource_(NULL),
51 long_jump_base_(NULL), 52 long_jump_base_(NULL),
52 store_buffer_block_(NULL), 53 store_buffer_block_(NULL),
53 no_callback_scope_depth_(0), 54 no_callback_scope_depth_(0),
54 #if defined(DEBUG) 55 #if defined(DEBUG)
55 top_handle_scope_(NULL), 56 top_handle_scope_(NULL),
56 no_handle_scope_depth_(0), 57 no_handle_scope_depth_(0),
57 no_safepoint_scope_depth_(0), 58 no_safepoint_scope_depth_(0),
58 #endif 59 #endif
59 reusable_handles_(), 60 reusable_handles_(),
60 cha_(NULL), 61 cha_(NULL),
61 deopt_id_(0), 62 deopt_id_(0),
62 vm_tag_(0), 63 vm_tag_(0),
63 pending_functions_(GrowableObjectArray::null()), 64 pending_functions_(GrowableObjectArray::null()),
64 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) 65 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS)
65 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) 66 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT)
67 safepoint_state_(0),
68 execution_state_(kThreadInVM),
66 next_(NULL) { 69 next_(NULL) {
67 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \ 70 #define DEFAULT_INIT(type_name, member_name, init_expr, default_init_value) \
68 member_name = default_init_value; 71 member_name = default_init_value;
69 CACHED_CONSTANTS_LIST(DEFAULT_INIT) 72 CACHED_CONSTANTS_LIST(DEFAULT_INIT)
70 #undef DEFAULT_INIT 73 #undef DEFAULT_INIT
71 74
72 #define DEFAULT_INIT(name) \ 75 #define DEFAULT_INIT(name) \
73 name##_entry_point_ = 0; 76 name##_entry_point_ = 0;
74 RUNTIME_ENTRY_LIST(DEFAULT_INIT) 77 RUNTIME_ENTRY_LIST(DEFAULT_INIT)
75 #undef DEFAULT_INIT 78 #undef DEFAULT_INIT
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
167 RawGrowableObjectArray* Thread::pending_functions() { 170 RawGrowableObjectArray* Thread::pending_functions() {
168 if (pending_functions_ == GrowableObjectArray::null()) { 171 if (pending_functions_ == GrowableObjectArray::null()) {
169 pending_functions_ = GrowableObjectArray::New(Heap::kOld); 172 pending_functions_ = GrowableObjectArray::New(Heap::kOld);
170 } 173 }
171 return pending_functions_; 174 return pending_functions_;
172 } 175 }
173 176
174 177
175 bool Thread::EnterIsolate(Isolate* isolate) { 178 bool Thread::EnterIsolate(Isolate* isolate) {
176 const bool kIsMutatorThread = true; 179 const bool kIsMutatorThread = true;
177 const bool kDontBypassSafepoints = false; 180 Thread* thread = isolate->ScheduleThread(kIsMutatorThread);
178 ThreadRegistry* tr = isolate->thread_registry();
179 Thread* thread = tr->Schedule(
180 isolate, kIsMutatorThread, kDontBypassSafepoints);
181 if (thread != NULL) { 181 if (thread != NULL) {
182 isolate->MakeCurrentThreadMutator(thread);
183 thread->set_vm_tag(VMTag::kVMTagId);
184 ASSERT(thread->store_buffer_block_ == NULL); 182 ASSERT(thread->store_buffer_block_ == NULL);
185 thread->StoreBufferAcquire(); 183 thread->StoreBufferAcquire();
186 return true; 184 return true;
187 } 185 }
188 return false; 186 return false;
189 } 187 }
190 188
191 189
192 void Thread::ExitIsolate() { 190 void Thread::ExitIsolate() {
193 Thread* thread = Thread::Current(); 191 Thread* thread = Thread::Current();
194 ASSERT(thread != NULL); 192 ASSERT(thread != NULL && thread->IsMutatorThread());
195 ASSERT(thread->IsMutatorThread()); 193 DEBUG_ASSERT(!thread->IsAnyReusableHandleScopeActive());
196 #if defined(DEBUG) 194
197 ASSERT(!thread->IsAnyReusableHandleScopeActive()); 195 Isolate* isolate = thread->isolate();
198 #endif // DEBUG 196 ASSERT(isolate != NULL);
197 ASSERT(thread->execution_state() == Thread::kThreadInVM);
199 // Clear since GC will not visit the thread once it is unscheduled. 198 // Clear since GC will not visit the thread once it is unscheduled.
200 thread->ClearReusableHandles(); 199 thread->ClearReusableHandles();
201 thread->StoreBufferRelease(); 200 thread->StoreBufferRelease();
202 Isolate* isolate = thread->isolate();
203 ASSERT(isolate != NULL);
204 if (isolate->is_runnable()) { 201 if (isolate->is_runnable()) {
205 thread->set_vm_tag(VMTag::kIdleTagId); 202 thread->set_vm_tag(VMTag::kIdleTagId);
206 } else { 203 } else {
207 thread->set_vm_tag(VMTag::kLoadWaitTagId); 204 thread->set_vm_tag(VMTag::kLoadWaitTagId);
208 } 205 }
209 const bool kIsMutatorThread = true; 206 const bool kIsMutatorThread = true;
210 const bool kDontBypassSafepoints = false; 207 isolate->UnscheduleThread(thread, kIsMutatorThread);
211 ThreadRegistry* tr = isolate->thread_registry();
212 tr->Unschedule(thread, kIsMutatorThread, kDontBypassSafepoints);
213 isolate->ClearMutatorThread();
214 } 208 }
215 209
216 210
217 bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { 211 bool Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) {
218 const bool kIsNotMutatorThread = false; 212 const bool kIsNotMutatorThread = false;
219 ThreadRegistry* tr = isolate->thread_registry(); 213 Thread* thread = isolate->ScheduleThread(kIsNotMutatorThread,
220 Thread* thread = tr->Schedule(isolate, kIsNotMutatorThread, bypass_safepoint); 214 bypass_safepoint);
221 if (thread != NULL) { 215 if (thread != NULL) {
222 ASSERT(thread->store_buffer_block_ == NULL); 216 ASSERT(thread->store_buffer_block_ == NULL);
223 // TODO(koda): Use StoreBufferAcquire once we properly flush 217 // TODO(koda): Use StoreBufferAcquire once we properly flush
224 // before Scavenge. 218 // before Scavenge.
225 thread->store_buffer_block_ = 219 thread->store_buffer_block_ =
226 thread->isolate()->store_buffer()->PopEmptyBlock(); 220 thread->isolate()->store_buffer()->PopEmptyBlock();
227 // This thread should not be the main mutator. 221 // This thread should not be the main mutator.
228 ASSERT(!thread->IsMutatorThread()); 222 ASSERT(!thread->IsMutatorThread());
229 return true; 223 return true;
230 } 224 }
231 return false; 225 return false;
232 } 226 }
233 227
234 228
235 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { 229 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) {
236 Thread* thread = Thread::Current(); 230 Thread* thread = Thread::Current();
237 ASSERT(thread != NULL); 231 ASSERT(thread != NULL);
238 ASSERT(!thread->IsMutatorThread()); 232 ASSERT(!thread->IsMutatorThread());
233 ASSERT(thread->execution_state() == Thread::kThreadInVM);
239 thread->StoreBufferRelease(); 234 thread->StoreBufferRelease();
240 Isolate* isolate = thread->isolate(); 235 Isolate* isolate = thread->isolate();
241 ASSERT(isolate != NULL); 236 ASSERT(isolate != NULL);
242 const bool kIsNotMutatorThread = false; 237 const bool kIsNotMutatorThread = false;
243 ThreadRegistry* tr = isolate->thread_registry(); 238 isolate->UnscheduleThread(thread, kIsNotMutatorThread, bypass_safepoint);
244 tr->Unschedule(thread, kIsNotMutatorThread, bypass_safepoint);
245 } 239 }
246 240
247 241
248 void Thread::PrepareForGC() { 242 void Thread::PrepareForGC() {
249 ASSERT(isolate()->thread_registry()->AtSafepoint()); 243 ASSERT(IsAtSafepoint());
250 // Prevent scheduling another GC by ignoring the threshold. 244 // Prevent scheduling another GC by ignoring the threshold.
245 ASSERT(store_buffer_block_ != NULL);
251 StoreBufferRelease(StoreBuffer::kIgnoreThreshold); 246 StoreBufferRelease(StoreBuffer::kIgnoreThreshold);
252 // Make sure to get an *empty* block; the isolate needs all entries 247 // Make sure to get an *empty* block; the isolate needs all entries
253 // at GC time. 248 // at GC time.
254 // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires. 249 // TODO(koda): Replace with an epilogue (PrepareAfterGC) that acquires.
255 store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock(); 250 store_buffer_block_ = isolate()->store_buffer()->PopEmptyBlock();
256 } 251 }
257 252
258 253
259 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) { 254 void Thread::StoreBufferBlockProcess(StoreBuffer::ThresholdPolicy policy) {
260 StoreBufferRelease(policy); 255 StoreBufferRelease(policy);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 287
293 bool Thread::IsMutatorThread() const { 288 bool Thread::IsMutatorThread() const {
294 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); 289 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this));
295 } 290 }
296 291
297 292
298 bool Thread::CanCollectGarbage() const { 293 bool Thread::CanCollectGarbage() const {
299 // We have non mutator threads grow the heap instead of triggering 294 // We have non mutator threads grow the heap instead of triggering
300 // a garbage collection when they are at a safepoint (e.g: background 295 // a garbage collection when they are at a safepoint (e.g: background
301 // compiler thread finalizing and installing code at a safepoint). 296 // compiler thread finalizing and installing code at a safepoint).
302 // Note: This code will change once the new Safepoint logic is in place. 297 return (IsMutatorThread() || IsAtSafepoint());
303 return (IsMutatorThread() ||
304 (isolate_ != NULL && !isolate_->thread_registry()->AtSafepoint()));
305 } 298 }
306 299
307 300
308 bool Thread::IsExecutingDartCode() const { 301 bool Thread::IsExecutingDartCode() const {
309 return (top_exit_frame_info() == 0) && 302 return (top_exit_frame_info() == 0) &&
310 (vm_tag() == VMTag::kDartTagId); 303 (vm_tag() == VMTag::kDartTagId);
311 } 304 }
312 305
313 306
314 bool Thread::HasExitedDartCode() const { 307 bool Thread::HasExitedDartCode() const {
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 while (scope != NULL && 440 while (scope != NULL &&
448 scope->stack_marker() != 0 && 441 scope->stack_marker() != 0 &&
449 scope->stack_marker() == stack_marker) { 442 scope->stack_marker() == stack_marker) {
450 api_top_scope_ = scope->previous(); 443 api_top_scope_ = scope->previous();
451 delete scope; 444 delete scope;
452 scope = api_top_scope_; 445 scope = api_top_scope_;
453 } 446 }
454 } 447 }
455 448
456 449
450 void Thread::EnterSafepointUsingLock() {
451 isolate()->safepoint_handler()->EnterSafepointUsingLock(this);
452 }
453
454
455 void Thread::ExitSafepointUsingLock() {
456 isolate()->safepoint_handler()->ExitSafepointUsingLock(this);
457 }
458
459
460 void Thread::BlockForSafepoint() {
461 isolate()->safepoint_handler()->BlockForSafepoint(this);
462 }
463
464
457 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) 465 DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread)
458 : StackResource(thread) { 466 : StackResource(thread) {
459 if (thread != NULL) { 467 if (thread != NULL) {
460 OSThread* os_thread = thread->os_thread(); 468 OSThread* os_thread = thread->os_thread();
461 ASSERT(os_thread != NULL); 469 ASSERT(os_thread != NULL);
462 os_thread->DisableThreadInterrupts(); 470 os_thread->DisableThreadInterrupts();
463 } 471 }
464 } 472 }
465 473
466 474
467 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { 475 DisableThreadInterruptsScope::~DisableThreadInterruptsScope() {
468 if (thread() != NULL) { 476 if (thread() != NULL) {
469 OSThread* os_thread = thread()->os_thread(); 477 OSThread* os_thread = thread()->os_thread();
470 ASSERT(os_thread != NULL); 478 ASSERT(os_thread != NULL);
471 os_thread->EnableThreadInterrupts(); 479 os_thread->EnableThreadInterrupts();
472 } 480 }
473 } 481 }
474 482
475 } // namespace dart 483 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/thread.h ('k') | runtime/vm/thread_registry.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698