Index: runtime/vm/thread.cc |
diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc |
index a19440d0799edf3719542aa4b06416b006997ded..26357bb4f1d75f0ddc7efba5e06128e544463e02 100644 |
--- a/runtime/vm/thread.cc |
+++ b/runtime/vm/thread.cc |
@@ -214,8 +214,7 @@ void Thread::EnsureInit() { |
Thread::Thread(bool init_vm_constants) |
: id_(OSThread::GetCurrentThreadId()), |
join_id_(OSThread::GetCurrentThreadJoinId()), |
- thread_interrupt_callback_(NULL), |
- thread_interrupt_data_(NULL), |
+ thread_interrupt_disabled_(1), // Thread interrupts disabled by default. |
isolate_(NULL), |
heap_(NULL), |
timeline_block_(NULL), |
@@ -331,8 +330,7 @@ void Thread::EnterIsolate(Isolate* isolate) { |
ASSERT(isolate->heap() != NULL); |
thread->heap_ = isolate->heap(); |
thread->Schedule(isolate); |
- // TODO(koda): Migrate profiler interface to use Thread. |
- Profiler::BeginExecution(isolate); |
+ thread->EnableThreadInterrupts(); |
} |
@@ -343,10 +341,10 @@ void Thread::ExitIsolate() { |
#if defined(DEBUG) |
ASSERT(!thread->IsAnyReusableHandleScopeActive()); |
#endif // DEBUG |
+ thread->DisableThreadInterrupts(); |
// Clear since GC will not visit the thread once it is unscheduled. |
thread->ClearReusableHandles(); |
Isolate* isolate = thread->isolate(); |
- Profiler::EndExecution(isolate); |
thread->Unschedule(); |
// TODO(koda): Move store_buffer_block_ into State. |
thread->StoreBufferRelease(); |
@@ -373,17 +371,17 @@ void Thread::EnterIsolateAsHelper(Isolate* isolate, bool bypass_safepoint) { |
thread->isolate()->store_buffer()->PopEmptyBlock(); |
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()); |
thread->Schedule(isolate, bypass_safepoint); |
+ thread->EnableThreadInterrupts(); |
} |
void Thread::ExitIsolateAsHelper(bool bypass_safepoint) { |
Thread* thread = Thread::Current(); |
+ thread->DisableThreadInterrupts(); |
Isolate* isolate = thread->isolate(); |
ASSERT(isolate != NULL); |
thread->Unschedule(bypass_safepoint); |
@@ -447,6 +445,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_; |
@@ -493,29 +503,31 @@ void Thread::VisitObjectPointers(ObjectPointerVisitor* visitor) { |
} |
-void Thread::SetThreadInterrupter(ThreadInterruptCallback callback, |
- void* data) { |
+void Thread::DisableThreadInterrupts() { |
ASSERT(Thread::Current() == this); |
- thread_interrupt_callback_ = callback; |
- thread_interrupt_data_ = data; |
+ AtomicOperations::FetchAndIncrement(&thread_interrupt_disabled_); |
} |
-bool Thread::IsThreadInterrupterEnabled(ThreadInterruptCallback* callback, |
- void** data) const { |
-#if defined(TARGET_OS_WINDOWS) |
- // On Windows we expect this to be called from the thread interrupter thread. |
- ASSERT(id() != OSThread::GetCurrentThreadId()); |
-#else |
- // On posix platforms, we expect this to be called from signal handler. |
- ASSERT(id() == OSThread::GetCurrentThreadId()); |
-#endif |
- ASSERT(callback != NULL); |
- ASSERT(data != NULL); |
- *callback = thread_interrupt_callback_; |
- *data = thread_interrupt_data_; |
- return (*callback != NULL) && |
- (*data != NULL); |
+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; |
} |
@@ -590,4 +602,18 @@ Thread* ThreadIterator::Next() { |
} |
+DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) |
+ : StackResource(thread) { |
+ if (thread != NULL) { |
+ thread->DisableThreadInterrupts(); |
+ } |
+} |
+ |
+ |
+DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { |
+ if (thread() != NULL) { |
+ thread()->EnableThreadInterrupts(); |
+ } |
+} |
+ |
} // namespace dart |