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/log.h" | 10 #include "vm/log.h" |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 while (current != NULL) { | 59 while (current != NULL) { |
60 ASSERT(current != thread); | 60 ASSERT(current != thread); |
61 current = current->thread_list_next_; | 61 current = current->thread_list_next_; |
62 } | 62 } |
63 } | 63 } |
64 #endif | 64 #endif |
65 | 65 |
66 // Insert at head of list. | 66 // Insert at head of list. |
67 thread->thread_list_next_ = thread_list_head_; | 67 thread->thread_list_next_ = thread_list_head_; |
68 thread_list_head_ = thread; | 68 thread_list_head_ = thread; |
| 69 |
| 70 // Make sure the thread interrupter is awake. |
| 71 ThreadInterrupter::WakeUp(); |
69 } | 72 } |
70 | 73 |
71 | 74 |
72 void Thread::RemoveThreadFromList(Thread* thread) { | 75 void Thread::RemoveThreadFromList(Thread* thread) { |
73 ASSERT(thread != NULL); | 76 ASSERT(thread != NULL); |
74 ASSERT(thread->isolate() == NULL); | 77 ASSERT(thread->isolate() == NULL); |
75 ASSERT(thread_list_lock_ != NULL); | 78 ASSERT(thread_list_lock_ != NULL); |
76 MutexLocker ml(thread_list_lock_); | 79 MutexLocker ml(thread_list_lock_); |
77 | 80 |
78 // Handle case where |thread| is head of list. | 81 // Handle case where |thread| is head of list. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
190 #endif // defined(DEBUG) | 193 #endif // defined(DEBUG) |
191 | 194 |
192 #define REUSABLE_HANDLE_INITIALIZERS(object) \ | 195 #define REUSABLE_HANDLE_INITIALIZERS(object) \ |
193 object##_handle_(NULL), | 196 object##_handle_(NULL), |
194 | 197 |
195 | 198 |
196 Thread::Thread(bool init_vm_constants) | 199 Thread::Thread(bool init_vm_constants) |
197 : id_(OSThread::GetCurrentThreadId()), | 200 : id_(OSThread::GetCurrentThreadId()), |
198 join_id_(OSThread::GetCurrentThreadJoinId()), | 201 join_id_(OSThread::GetCurrentThreadJoinId()), |
199 thread_interrupt_callback_(NULL), | 202 thread_interrupt_callback_(NULL), |
200 thread_interrupt_data_(NULL), | 203 thread_interrupt_disabled_(0), |
201 isolate_(NULL), | 204 isolate_(NULL), |
202 heap_(NULL), | 205 heap_(NULL), |
203 timeline_block_(NULL), | 206 timeline_block_(NULL), |
204 store_buffer_block_(NULL), | 207 store_buffer_block_(NULL), |
205 log_(new class Log()), | 208 log_(new class Log()), |
206 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) | 209 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_INITIALIZERS) |
207 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) | 210 REUSABLE_HANDLE_LIST(REUSABLE_HANDLE_SCOPE_INIT) |
208 reusable_handles_(), | 211 reusable_handles_(), |
209 cha_(NULL), | 212 cha_(NULL), |
210 deopt_id_(0), | 213 deopt_id_(0), |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 ASSERT(thread != NULL); | 352 ASSERT(thread != NULL); |
350 ASSERT(thread->isolate() == NULL); | 353 ASSERT(thread->isolate() == NULL); |
351 thread->isolate_ = isolate; | 354 thread->isolate_ = isolate; |
352 ASSERT(thread->store_buffer_block_ == NULL); | 355 ASSERT(thread->store_buffer_block_ == NULL); |
353 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. | 356 // TODO(koda): Use StoreBufferAcquire once we properly flush before Scavenge. |
354 thread->store_buffer_block_ = | 357 thread->store_buffer_block_ = |
355 thread->isolate()->store_buffer()->PopEmptyBlock(); | 358 thread->isolate()->store_buffer()->PopEmptyBlock(); |
356 ASSERT(isolate->heap() != NULL); | 359 ASSERT(isolate->heap() != NULL); |
357 thread->heap_ = isolate->heap(); | 360 thread->heap_ = isolate->heap(); |
358 ASSERT(thread->thread_interrupt_callback_ == NULL); | 361 ASSERT(thread->thread_interrupt_callback_ == NULL); |
359 ASSERT(thread->thread_interrupt_data_ == NULL); | |
360 // Do not update isolate->mutator_thread, but perform sanity check: | 362 // Do not update isolate->mutator_thread, but perform sanity check: |
361 // this thread should not be both the main mutator and helper. | 363 // this thread should not be both the main mutator and helper. |
362 ASSERT(!thread->IsMutatorThread()); | 364 ASSERT(!thread->IsMutatorThread()); |
363 thread->Schedule(isolate, bypass_safepoint); | 365 thread->Schedule(isolate, bypass_safepoint); |
364 } | 366 } |
365 | 367 |
366 | 368 |
367 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { | 369 void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { |
368 Thread* thread = Thread::Current(); | 370 Thread* thread = Thread::Current(); |
369 Isolate* isolate = thread->isolate(); | 371 Isolate* isolate = thread->isolate(); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 void Thread::StoreBufferAcquire() { | 424 void Thread::StoreBufferAcquire() { |
423 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock(); | 425 store_buffer_block_ = isolate()->store_buffer()->PopNonFullBlock(); |
424 } | 426 } |
425 | 427 |
426 | 428 |
427 bool Thread::IsMutatorThread() const { | 429 bool Thread::IsMutatorThread() const { |
428 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); | 430 return ((isolate_ != NULL) && (isolate_->mutator_thread() == this)); |
429 } | 431 } |
430 | 432 |
431 | 433 |
| 434 bool Thread::IsExecutingDartCode() const { |
| 435 return (top_exit_frame_info() == 0) && |
| 436 (vm_tag() == VMTag::kDartTagId); |
| 437 } |
| 438 |
| 439 |
| 440 bool Thread::HasExitedDartCode() const { |
| 441 return (top_exit_frame_info() != 0) && |
| 442 (vm_tag() != VMTag::kDartTagId); |
| 443 } |
| 444 |
| 445 |
432 CHA* Thread::cha() const { | 446 CHA* Thread::cha() const { |
433 ASSERT(isolate_ != NULL); | 447 ASSERT(isolate_ != NULL); |
434 return cha_; | 448 return cha_; |
435 } | 449 } |
436 | 450 |
437 | 451 |
438 void Thread::set_cha(CHA* value) { | 452 void Thread::set_cha(CHA* value) { |
439 ASSERT(isolate_ != NULL); | 453 ASSERT(isolate_ != NULL); |
440 cha_ = value; | 454 cha_ = value; |
441 } | 455 } |
(...skipping 26 matching lines...) Expand all Loading... |
468 // Visit objects in thread specific handles area. | 482 // Visit objects in thread specific handles area. |
469 reusable_handles_.VisitObjectPointers(visitor); | 483 reusable_handles_.VisitObjectPointers(visitor); |
470 | 484 |
471 if (pending_functions_ != GrowableObjectArray::null()) { | 485 if (pending_functions_ != GrowableObjectArray::null()) { |
472 visitor->VisitPointer( | 486 visitor->VisitPointer( |
473 reinterpret_cast<RawObject**>(&pending_functions_)); | 487 reinterpret_cast<RawObject**>(&pending_functions_)); |
474 } | 488 } |
475 } | 489 } |
476 | 490 |
477 | 491 |
478 void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, | 492 void Thread::DisableThreadInterrupts() { |
479 void* data) { | |
480 ASSERT(Thread::Current() == this); | 493 ASSERT(Thread::Current() == this); |
481 thread_interrupt_callback_ = callback; | 494 AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_); |
482 thread_interrupt_data_ = data; | |
483 } | 495 } |
484 | 496 |
485 | 497 |
486 bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, | 498 void Thread::EnableThreadInterrupts() { |
487 void** data) const { | 499 ASSERT(Thread::Current() == this); |
| 500 uintptr_t old = |
| 501 AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_); |
| 502 if (old == 1) { |
| 503 // We just decremented from 1 to 0. |
| 504 // Make sure the thread interrupter is awake. |
| 505 ThreadInterrupter::WakeUp(); |
| 506 } |
| 507 if (old == 0) { |
| 508 // We just decremented from 0, this means we've got a mismatched pair |
| 509 // of calls to EnableThreadInterrupts and DisableThreadInterrupts. |
| 510 FATAL("Invalid call to Thread::EnableThreadInterrupts()"); |
| 511 } |
| 512 } |
| 513 |
| 514 |
| 515 bool Thread::ThreadInterruptsEnabled() { |
| 516 return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0; |
| 517 } |
| 518 |
| 519 |
| 520 void Thread::SetThreadInterruptCallback(ThreadInterruptCallback callback) { |
| 521 ASSERT(Thread::Current() == this); |
| 522 thread_interrupt_callback_ = callback; |
| 523 } |
| 524 |
| 525 |
| 526 bool Thread::GetThreadInterruptCallback( |
| 527 ThreadInterruptCallback* callback) const { |
488 #if defined(TARGET_OS_WINDOWS) | 528 #if defined(TARGET_OS_WINDOWS) |
489 // On Windows we expect this to be called from the thread interrupter thread. | 529 // On Windows we expect this to be called from the thread interrupter thread. |
490 ASSERT(id() != OSThread::GetCurrentThreadId()); | 530 ASSERT(id() != OSThread::GetCurrentThreadId()); |
491 #else | 531 #else |
492 // On posix platforms, we expect this to be called from signal handler. | 532 // On posix platforms, we expect this to be called from signal handler. |
493 ASSERT(id() == OSThread::GetCurrentThreadId()); | 533 ASSERT(id() == OSThread::GetCurrentThreadId()); |
494 #endif | 534 #endif |
495 ASSERT(callback != NULL); | 535 ASSERT(callback != NULL); |
496 ASSERT(data != NULL); | |
497 *callback = thread_interrupt_callback_; | 536 *callback = thread_interrupt_callback_; |
498 *data = thread_interrupt_data_; | 537 return (*callback != NULL); |
499 return (*callback != NULL) && | |
500 (*data != NULL); | |
501 } | 538 } |
502 | 539 |
503 | 540 |
504 bool Thread::CanLoadFromThread(const Object& object) { | 541 bool Thread::CanLoadFromThread(const Object& object) { |
505 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ | 542 #define CHECK_OBJECT(type_name, member_name, expr, default_init_value) \ |
506 if (object.raw() == expr) return true; | 543 if (object.raw() == expr) return true; |
507 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) | 544 CACHED_VM_OBJECTS_LIST(CHECK_OBJECT) |
508 #undef CHECK_OBJECT | 545 #undef CHECK_OBJECT |
509 return false; | 546 return false; |
510 } | 547 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
566 Thread* ThreadIterator::Next() { | 603 Thread* ThreadIterator::Next() { |
567 ASSERT(Thread::thread_list_lock_ != NULL); | 604 ASSERT(Thread::thread_list_lock_ != NULL); |
568 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); | 605 ASSERT(Thread::thread_list_lock_->IsOwnedByCurrentThread()); |
569 Thread* current = next_; | 606 Thread* current = next_; |
570 next_ = next_->thread_list_next_; | 607 next_ = next_->thread_list_next_; |
571 return current; | 608 return current; |
572 } | 609 } |
573 | 610 |
574 | 611 |
575 } // namespace dart | 612 } // namespace dart |
OLD | NEW |