Chromium Code Reviews| Index: runtime/vm/thread.cc |
| diff --git a/runtime/vm/thread.cc b/runtime/vm/thread.cc |
| index 5c635b9be57e6009e06a129f78d01e162070cffa..057d1dcd448d3bc324dd71d99884b267a9d59177 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(); |
|
Ivan Posva
2015/10/28 19:31:53
Does not match our discussion from earlier today.
Cutch
2015/10/28 19:50:33
Forgot to remove this. It's gone now.
|
| } |
| @@ -196,8 +199,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), |
| @@ -313,8 +315,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(); |
| } |
| @@ -325,10 +326,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(); |
| @@ -355,17 +356,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); |
| @@ -429,6 +430,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,29 +488,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; |
| } |
| @@ -572,4 +587,18 @@ Thread* ThreadIterator::Next() { |
| } |
| +DisableThreadInterruptsScope::DisableThreadInterruptsScope(Thread* thread) |
| + : StackResource(thread) { |
| + if (thread != NULL) { |
| + thread->DisableThreadInterrupts(); |
| + } |
| +} |
| + |
| + |
| +DisableThreadInterruptsScope::~DisableThreadInterruptsScope() { |
| + if (thread() != NULL) { |
| + thread()->EnableThreadInterrupts(); |
| + } |
| +} |
| + |
| } // namespace dart |