Index: runtime/vm/thread_registry.h |
diff --git a/runtime/vm/thread_registry.h b/runtime/vm/thread_registry.h |
index 20f4d95d55da3a53a40d95ba0fc4afce8405145c..51ebceb46dbefed785cc0123941ed45b0e7ba6bc 100644 |
--- a/runtime/vm/thread_registry.h |
+++ b/runtime/vm/thread_registry.h |
@@ -19,13 +19,17 @@ class ThreadRegistry { |
public: |
ThreadRegistry() |
: monitor_(new Monitor()), |
- entries_(), |
+ active_list_(NULL), |
+ free_list_(NULL), |
+ mutator_thread_(NULL), |
in_rendezvous_(false), |
remaining_(0), |
round_(0) {} |
~ThreadRegistry(); |
+ Thread* active_list() const { return active_list_; } |
+ |
// Bring all threads in this isolate to a safepoint. The caller is |
// expected to be implicitly at a safepoint. The threads will wait |
// until ResumeAllThreads is called. First participates in any |
@@ -48,145 +52,13 @@ class ThreadRegistry { |
CheckSafepointLocked(); |
} |
- bool RestoreStateTo(Thread* thread, Thread::State* state, |
- bool bypass_safepoint) { |
- MonitorLocker ml(monitor_); |
- // Wait for any rendezvous in progress. |
- while (!bypass_safepoint && in_rendezvous_) { |
- ml.Wait(Monitor::kNoTimeout); |
- } |
- Entry* entry = FindEntry(thread); |
- if (entry != NULL) { |
- Thread::State st = entry->state; |
- // TODO(koda): Support same thread re-entering same isolate with |
- // Dart frames in between. For now, just assert it doesn't happen. |
- if (st.top_exit_frame_info != thread->top_exit_frame_info()) { |
- ASSERT(thread->top_exit_frame_info() == 0 || |
- thread->top_exit_frame_info() > st.top_exit_frame_info); |
- } |
- ASSERT(!entry->scheduled); |
- entry->scheduled = true; |
-#if defined(DEBUG) |
- // State field is not in use, so zap it. |
- memset(&entry->state, 0xda, sizeof(entry->state)); |
-#endif |
- *state = st; |
- return true; |
- } |
- Entry new_entry; |
- new_entry.thread = thread; |
- new_entry.scheduled = true; |
-#if defined(DEBUG) |
- // State field is not in use, so zap it. |
- memset(&new_entry.state, 0xda, sizeof(new_entry.state)); |
-#endif |
- entries_.Add(new_entry); |
- return false; |
- } |
- |
- void SaveStateFrom(Thread* thread, const Thread::State& state, |
- bool bypass_safepoint) { |
- MonitorLocker ml(monitor_); |
- Entry* entry = FindEntry(thread); |
- ASSERT(entry != NULL); |
- ASSERT(entry->scheduled); |
- entry->scheduled = false; |
- entry->state = state; |
- if (!bypass_safepoint && in_rendezvous_) { |
- // Don't wait for this thread. |
- ASSERT(remaining_ > 0); |
- if (--remaining_ == 0) { |
- ml.NotifyAll(); |
- } |
- } |
- } |
- |
- bool Contains(Thread* thread) { |
- MonitorLocker ml(monitor_); |
- return (FindEntry(thread) != NULL); |
- } |
- |
- void CheckNotScheduled(Isolate* isolate) { |
- MonitorLocker ml(monitor_); |
- for (int i = 0; i < entries_.length(); ++i) { |
- const Entry& entry = entries_[i]; |
- if (entry.scheduled) { |
- FATAL3("Isolate %p still scheduled on %p (whose isolate_ is %p)\n", |
- isolate, |
- entry.thread, |
- entry.thread->isolate()); |
- } |
- } |
- } |
- |
- void VisitObjectPointers(ObjectPointerVisitor* visitor, |
- bool validate_frames) { |
- MonitorLocker ml(monitor_); |
- for (int i = 0; i < entries_.length(); ++i) { |
- const Entry& entry = entries_[i]; |
- const Thread::State& state = |
- entry.scheduled ? entry.thread->state_ : entry.state; |
- if (state.zone != NULL) { |
- state.zone->VisitObjectPointers(visitor); |
- } |
- if (entry.scheduled) { |
- ASSERT(entry.thread != NULL); |
- entry.thread->VisitObjectPointers(visitor); |
- } |
- // Iterate over all the stack frames and visit objects on the stack. |
- StackFrameIterator frames_iterator(state.top_exit_frame_info, |
- validate_frames); |
- StackFrame* frame = frames_iterator.NextFrame(); |
- while (frame != NULL) { |
- frame->VisitObjectPointers(visitor); |
- frame = frames_iterator.NextFrame(); |
- } |
- } |
- } |
- |
- void PruneThread(Thread* thread); |
- |
- void ReclaimTimelineBlocks(); |
- |
- struct Entry { |
- // NOTE: |thread| is deleted automatically when the thread exits. |
- // In other words, it is not safe to dereference |thread| unless you are on |
- // the thread itself. |
- Thread* thread; |
- bool scheduled; |
- Thread::State state; |
- }; |
- |
- class EntryIterator { |
- public: |
- explicit EntryIterator(ThreadRegistry* registry); |
- ~EntryIterator(); |
- |
- // Returns false when there are no more entries. |
- bool HasNext() const; |
- |
- // Returns the next entry and moves forward. |
- const Entry& Next(); |
- |
- private: |
- void Reset(ThreadRegistry* registry); |
- |
- intptr_t index_; |
- ThreadRegistry* registry_; |
- }; |
+ Thread* Schedule(Isolate* isolate, bool is_mutator, bool bypass_safepoint); |
+ void Unschedule(Thread* thread, bool is_mutator, bool bypass_safepoint); |
+ void VisitObjectPointers(ObjectPointerVisitor* visitor, bool validate_frames); |
private: |
- // Returns Entry corresponding to thread in registry or NULL. |
- // Note: Lock should be taken before this function is called. |
- // TODO(koda): Add method Monitor::IsOwnedByCurrentThread. |
- Entry* FindEntry(Thread* thread) { |
- for (int i = 0; i < entries_.length(); ++i) { |
- if (entries_[i].thread == thread) { |
- return &entries_[i]; |
- } |
- } |
- return NULL; |
- } |
+ Thread* GetThreadFromFreelist(Isolate* isolate); |
+ void ReturnThreadToFreelist(Thread* thread); |
// Note: Lock should be taken before this function is called. |
void CheckSafepointLocked(); |
@@ -196,7 +68,16 @@ class ThreadRegistry { |
intptr_t CountScheduledLocked(); |
Monitor* monitor_; // All access is synchronized through this monitor. |
- MallocGrowableArray<Entry> entries_; |
+ Thread* active_list_; // List of active threads in the isolate. |
+ Thread* free_list_; // Free list of Thread objects that can be reused. |
+ // TODO(asiva): Currently we treat a mutator thread as a special thread |
+ // and always schedule execution of Dart code on the same mutator thread |
+ // object. This is because ApiState is still an object associated with |
+ // the isolate and switching execution to another thread causes problems. |
+ // Once ApiState is made a per Thread object it should be possible to |
+ // free a mutator thread like all other threads and continue running on |
+ // a different thread. |
+ Thread* mutator_thread_; |
// Safepoint rendezvous state. |
bool in_rendezvous_; // A safepoint rendezvous request is in progress. |