Index: runtime/vm/thread.cc |
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc |
index 5c635b9be57e6009e06a129f78d01e162070cffa..6b2133b8f59652617c4eb09e4779c68809c93e0b 100644 |
--- a/runtime/vm/thread.cc |
+++ b/runtime/vm/thread.cc |
@@ -66,6 +66,9 @@ void Thread::AddThreadToList(Thread* thread) { |
// Insert at head of list. |
thread->thread_list_next_ = thread_list_head_; |
thread_list_head_ = thread; |
+ |
+ // Make sure the thread interrupter is awake. |
+ ThreadInterrupter::WakeUp(); |
} |
@@ -197,7 +200,7 @@ Thread::Thread(bool init_vm_constants) |
: id_(OSThread::GetCurrentThreadId()), |
join_id_(OSThread::GetCurrentThreadJoinId()), |
thread_interrupt_callback_(NULL), |
- thread_interrupt_data_(NULL), |
+ thread_interrupt_disabled_(0), |
isolate_(NULL), |
heap_(NULL), |
timeline_block_(NULL), |
@@ -356,7 +359,6 @@ void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { |
ASSERT(isolate->heap() != NULL); |
thread->heap_ = isolate->heap(); |
ASSERT(thread->thread_interrupt_callback_ == NULL); |
- ASSERT(thread->thread_interrupt_data_ == NULL); |
// Do not update isolate->mutator_thread, but perform sanity check: |
// this thread should not be both the main mutator and helper. |
ASSERT(!thread->IsMutatorThread()); |
@@ -429,6 +431,18 @@ bool Thread::IsMutatorThread() const { |
} |
+bool Thread::IsExecutingDartCode() const { |
+ return (top_exit_frame_info() == 0) && |
+ (vm_tag() == VMTag::kDartTagId); |
+} |
+ |
+ |
+bool Thread::HasExitedDartCode() const { |
+ return (top_exit_frame_info() != 0) && |
+ (vm_tag() != VMTag::kDartTagId); |
+} |
+ |
+ |
CHA* Thread::cha() const { |
ASSERT(isolate_ != NULL); |
return cha_; |
@@ -475,16 +489,42 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
} |
-void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, |
- void* data) { |
+void Thread::DisableThreadInterrupts() { |
+ ASSERT(Thread::Current() == this); |
+ AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_); |
+} |
+ |
+ |
+void Thread::EnableThreadInterrupts() { |
+ ASSERT(Thread::Current() == this); |
+ uintptr_t old = |
+ AtomicOperations::FetchAndDecrement(&thread_interrupt_disabled_); |
+ if (old == 1) { |
+ // We just decremented from 1 to 0. |
+ // Make sure the thread interrupter is awake. |
+ ThreadInterrupter::WakeUp(); |
+ } |
+ if (old == 0) { |
+ // We just decremented from 0, this means we've got a mismatched pair |
+ // of calls to EnableThreadInterrupts and DisableThreadInterrupts. |
+ FATAL("Invalid call to Thread::EnableThreadInterrupts()"); |
+ } |
+} |
+ |
+ |
+bool Thread::ThreadInterruptsEnabled() { |
+ return AtomicOperations::LoadRelaxed(&thread_interrupt_disabled_) == 0; |
+} |
+ |
+ |
+void Thread::SetThreadInterruptCallback(ThreadInterruptCallback callback) { |
ASSERT(Thread::Current() == this); |
thread_interrupt_callback_ = callback; |
- thread_interrupt_data_ = data; |
} |
-bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, |
- void** data) const { |
+bool Thread::GetThreadInterruptCallback( |
+ ThreadInterruptCallback* callback) const { |
#if defined(TARGET_OS_WINDOWS) |
// On Windows we expect this to be called from the thread interrupter thread. |
ASSERT(id() != OSThread::GetCurrentThreadId()); |
@@ -493,11 +533,8 @@ bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, |
ASSERT(id() == OSThread::GetCurrentThreadId()); |
#endif |
ASSERT(callback != NULL); |
- ASSERT(data != NULL); |
*callback = thread_interrupt_callback_; |
- *data = thread_interrupt_data_; |
- return (*callback != NULL) && |
- (*data != NULL); |
+ return (*callback != NULL); |
} |