Chromium Code Reviews| Index: runtime/vm/thread_registry.cc |
| diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc |
| index f0f80e3fd08cab01d2c82715410765c1953df4aa..80ad999c83768b3021ea216858d22a70ac8bbf57 100644 |
| --- a/runtime/vm/thread_registry.cc |
| +++ b/runtime/vm/thread_registry.cc |
| @@ -10,6 +10,24 @@ |
| namespace dart { |
| ThreadRegistry::~ThreadRegistry() { |
| + // Go over the free thread list and delete the thread objects. |
| + { |
| + MonitorLocker ml(monitor_); |
| + // At this point the mutator thread should be the only thread |
| + // in the active list, delete it. |
| + ASSERT(active_list_->next_ == NULL); |
| + ASSERT(active_list_ == mutator_thread_); |
| + delete mutator_thread_; |
| + active_list_ = NULL; |
| + mutator_thread_ = NULL; |
| + // Now delete all the threads in the free list. |
| + while (free_list_ != NULL) { |
| + Thread* thread = free_list_; |
| + free_list_ = thread->next_; |
| + delete thread; |
| + } |
| + } |
| + |
| // Delete monitor. |
| delete monitor_; |
| } |
| @@ -50,67 +68,123 @@ void ThreadRegistry::ResumeAllThreads() { |
| } |
| -void ThreadRegistry::PruneThread(Thread* thread) { |
| +Thread* ThreadRegistry::Schedule(Isolate* isolate, |
| + bool is_mutator, |
| + bool bypass_safepoint) { |
| MonitorLocker ml(monitor_); |
| - intptr_t length = entries_.length(); |
| - if (length == 0) { |
| - return; |
| + // Wait for any rendezvous in progress. |
| + while (!bypass_safepoint && in_rendezvous_) { |
| + ml.Wait(Monitor::kNoTimeout); |
| } |
| - intptr_t found_index = -1; |
| - for (intptr_t index = 0; index < length; index++) { |
| - if (entries_.At(index).thread == thread) { |
| - found_index = index; |
| - break; |
| + Thread* thread = NULL; |
| + OSThread* os_thread = OSThread::Current(); |
| + ASSERT(os_thread != NULL); |
| + ASSERT(isolate->heap() != NULL); |
| + if (is_mutator) { |
| + if (mutator_thread_ == NULL) { |
| + mutator_thread_ = GetThreadFromFreelist(isolate); |
| } |
| + thread = mutator_thread_; |
| + } else { |
| + thread = GetThreadFromFreelist(isolate); |
| } |
| - if (found_index < 0) { |
| - return; |
| - } |
| - entries_.RemoveAt(found_index); |
| -} |
| - |
| - |
| -ThreadRegistry::EntryIterator::EntryIterator(ThreadRegistry* registry) |
| - : index_(0), |
| - registry_(NULL) { |
| - Reset(registry); |
| + thread->isolate_ = isolate; |
| + thread->heap_ = isolate->heap(); |
| + thread->set_os_thread(os_thread); |
| + os_thread->set_thread(thread); |
| + Thread::SetCurrent(thread); |
| + os_thread->EnableThreadInterrupts(); |
| + return thread; |
| } |
| -ThreadRegistry::EntryIterator::~EntryIterator() { |
| - Reset(NULL); |
| -} |
| - |
| - |
| -void ThreadRegistry::EntryIterator::Reset(ThreadRegistry* registry) { |
| - // Reset index. |
| - index_ = 0; |
| - |
| - // Unlock old registry. |
| - if (registry_ != NULL) { |
| - registry_->monitor_->Exit(); |
| +void ThreadRegistry::Unschedule(Thread* thread, |
| + bool is_mutator, |
| + bool bypass_safepoint) { |
| + MonitorLocker ml(monitor_); |
| + OSThread* os_thread = thread->os_thread(); |
| + ASSERT(os_thread != NULL); |
| + os_thread->DisableThreadInterrupts(); |
| + thread->isolate_ = NULL; |
| + thread->heap_ = NULL; |
| + thread->set_os_thread(NULL); |
| + os_thread->set_thread(NULL); |
| + OSThread::SetCurrent(os_thread); |
| + if (!is_mutator) { |
| + ReturnThreadToFreelist(thread); |
| } |
| + if (!bypass_safepoint && in_rendezvous_) { |
| + // Don't wait for this thread. |
| + ASSERT(remaining_ > 0); |
| + if (--remaining_ == 0) { |
| + ml.NotifyAll(); |
| + } |
| + } |
| +} |
| - registry_ = registry; |
| - // Lock new registry. |
| - if (registry_ != NULL) { |
| - registry_->monitor_->Enter(); |
| +void ThreadRegistry::VisitObjectPointers(ObjectPointerVisitor* visitor, |
| + bool validate_frames) { |
| + MonitorLocker ml(monitor_); |
| + Thread* thread = active_list_; |
| + while (thread != NULL) { |
| + if (thread->zone() != NULL) { |
| + thread->zone()->VisitObjectPointers(visitor); |
| + } |
| + thread->VisitObjectPointers(visitor); |
| + // Iterate over all the stack frames and visit objects on the stack. |
| + StackFrameIterator frames_iterator(thread->top_exit_frame_info(), |
| + validate_frames); |
| + StackFrame* frame = frames_iterator.NextFrame(); |
| + while (frame != NULL) { |
| + frame->VisitObjectPointers(visitor); |
| + frame = frames_iterator.NextFrame(); |
| + } |
| + thread = thread->next_; |
| } |
| } |
| -bool ThreadRegistry::EntryIterator::HasNext() const { |
| - if (registry_ == NULL) { |
| - return false; |
| +Thread* ThreadRegistry::GetThreadFromFreelist(Isolate* isolate) { |
| + ASSERT(monitor_->IsOwnedByCurrentThread()); |
| + Thread* thread = NULL; |
| + // Get thread structure from free list or create a new one. |
| + if (free_list_ == NULL) { |
| + thread = new Thread(isolate); |
| + } else { |
| + thread = free_list_; |
| + free_list_ = thread->next_; |
| } |
| - return index_ < registry_->entries_.length(); |
| + // Add thread to active list. |
| + thread->next_ = active_list_; |
| + active_list_ = thread; |
| + return thread; |
| } |
| - |
| -const ThreadRegistry::Entry& ThreadRegistry::EntryIterator::Next() { |
| - ASSERT(HasNext()); |
| - return registry_->entries_.At(index_++); |
| +void ThreadRegistry::ReturnThreadToFreelist(Thread* thread) { |
| + ASSERT(thread != NULL); |
| + ASSERT(thread->os_thread_ == NULL); |
| + ASSERT(thread->isolate_ == NULL); |
| + ASSERT(thread->heap_ == NULL); |
| + ASSERT(monitor_->IsOwnedByCurrentThread()); |
| + // First remove the thread from the active list. |
| + Thread* prev = NULL; |
| + Thread* iterator = active_list_; |
| + while (iterator != NULL) { |
|
Ivan Posva
2015/11/19 06:23:23
iterator is a weird name for this. How about using
siva
2015/11/19 20:54:05
Done.
|
| + if (iterator == thread) { |
| + if (prev == NULL) { |
| + active_list_ = iterator->next_; |
| + } else { |
| + prev->next_ = iterator->next_; |
| + } |
| + break; |
| + } |
| + prev = iterator; |
| + iterator = iterator->next_; |
| + } |
| + // Now add thread to the free list. |
| + thread->next_ = free_list_; |
| + free_list_ = thread; |
| } |
| @@ -142,11 +216,10 @@ void ThreadRegistry::CheckSafepointLocked() { |
| intptr_t ThreadRegistry::CountScheduledLocked() { |
| intptr_t count = 0; |
| - for (int i = 0; i < entries_.length(); ++i) { |
| - const Entry& entry = entries_[i]; |
| - if (entry.scheduled) { |
| - ++count; |
| - } |
| + Thread* iterator = active_list_; |
|
Ivan Posva
2015/11/19 06:23:23
ditto
siva
2015/11/19 20:54:05
Done.
|
| + while (iterator != NULL) { |
| + ++count; |
| + iterator = iterator->next_; |
| } |
| return count; |
| } |