Index: runtime/vm/thread_registry.cc |
diff --git a/runtime/vm/thread_registry.cc b/runtime/vm/thread_registry.cc |
index f0f80e3fd08cab01d2c82715410765c1953df4aa..6031366895be857a0855147128a8516c55c818a5 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* current = active_list_; |
+ while (current != NULL) { |
+ if (current == thread) { |
+ if (prev == NULL) { |
+ active_list_ = current->next_; |
+ } else { |
+ prev->next_ = current->next_; |
+ } |
+ break; |
+ } |
+ prev = current; |
+ current = current->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* current = active_list_; |
+ while (current != NULL) { |
+ ++count; |
+ current = current->next_; |
} |
return count; |
} |