| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef VM_THREAD_REGISTRY_H_ | 5 #ifndef VM_THREAD_REGISTRY_H_ |
| 6 #define VM_THREAD_REGISTRY_H_ | 6 #define VM_THREAD_REGISTRY_H_ |
| 7 | 7 |
| 8 #include "vm/globals.h" | 8 #include "vm/globals.h" |
| 9 #include "vm/growable_array.h" | 9 #include "vm/growable_array.h" |
| 10 #include "vm/isolate.h" | 10 #include "vm/isolate.h" |
| 11 #include "vm/lockers.h" | 11 #include "vm/lockers.h" |
| 12 #include "vm/stack_frame.h" | 12 #include "vm/stack_frame.h" |
| 13 #include "vm/thread.h" | 13 #include "vm/thread.h" |
| 14 | 14 |
| 15 namespace dart { | 15 namespace dart { |
| 16 | 16 |
| 17 // Unordered collection of threads relating to a particular isolate. | 17 // Unordered collection of threads relating to a particular isolate. |
| 18 class ThreadRegistry { | 18 class ThreadRegistry { |
| 19 public: | 19 public: |
| 20 ThreadRegistry() | 20 ThreadRegistry() |
| 21 : monitor_(new Monitor()), | 21 : monitor_(new Monitor()), |
| 22 entries_(), | 22 entries_(), |
| 23 in_rendezvous_(false), | 23 in_rendezvous_(false), |
| 24 remaining_(0), | 24 remaining_(0), |
| 25 round_(0) {} | 25 round_(0) {} |
| 26 | 26 |
| 27 // Bring all threads in this isolate to a safepoint. The caller is | 27 // Bring all threads in this isolate to a safepoint. The caller is |
| 28 // expected to be implicitly at a safepoint. The threads will wait | 28 // expected to be implicitly at a safepoint. The threads will wait |
| 29 // until ResumeAllThreads is called. First participates in any | 29 // until ResumeAllThreads is called. First participates in any |
| 30 // already pending rendezvous requested by another thread. Any | 30 // already pending rendezvous requested by another thread. |
| 31 // |
| 32 // Returns an identifier of this rendezvous, which can be passed to |
| 33 // Thread::EnterIsolateAsHelper to allow the thread free passage in/out |
| 34 // of the isolate while this rendezvous is in progress. Otherwise, any |
| 31 // thread that tries to enter this isolate during rendezvous will | 35 // thread that tries to enter this isolate during rendezvous will |
| 32 // wait in RestoreStateTo. Nesting is not supported: the caller must | 36 // wait in RestoreStateTo. Nesting is not supported: the caller must |
| 33 // call ResumeAllThreads before making further calls to | 37 // call ResumeAllThreads before making further calls to |
| 34 // SafepointThreads. | 38 // SafepointThreads. |
| 35 void SafepointThreads(); | 39 SafepointId SafepointThreads(); |
| 36 | 40 |
| 37 // Unblocks all threads participating in the rendezvous that was organized | 41 // Unblocks all threads participating in the rendezvous that was organized |
| 38 // by a prior call to SafepointThreads. | 42 // by a prior call to SafepointThreads. |
| 39 // TODO(koda): Consider adding a scope helper to avoid omitting this call. | 43 // TODO(koda): Consider adding a scope helper to avoid omitting this call. |
| 40 void ResumeAllThreads(); | 44 void ResumeAllThreads(); |
| 41 | 45 |
| 42 // Indicate that the current thread is at a safepoint, and offer to wait for | 46 // Indicate that the current thread is at a safepoint, and offer to wait for |
| 43 // any pending rendezvous request (if none, returns immediately). | 47 // any pending rendezvous request (if none, returns immediately). |
| 44 void CheckSafepoint() { | 48 void CheckSafepoint() { |
| 45 MonitorLocker ml(monitor_); | 49 MonitorLocker ml(monitor_); |
| 46 CheckSafepointLocked(); | 50 CheckSafepointLocked(); |
| 47 } | 51 } |
| 48 | 52 |
| 49 bool RestoreStateTo(Thread* thread, Thread::State* state) { | 53 bool RestoreStateTo(Thread* thread, Thread::State* state) { |
| 50 MonitorLocker ml(monitor_); | 54 MonitorLocker ml(monitor_); |
| 51 // Wait for any rendezvous in progress. | 55 // Wait for any rendezvous in progress. |
| 52 while (in_rendezvous_) { | 56 while (IsParticipant(thread)) { |
| 53 ml.Wait(Monitor::kNoTimeout); | 57 ml.Wait(Monitor::kNoTimeout); |
| 54 } | 58 } |
| 55 Entry* entry = FindEntry(thread); | 59 Entry* entry = FindEntry(thread); |
| 56 if (entry != NULL) { | 60 if (entry != NULL) { |
| 57 Thread::State st = entry->state; | 61 Thread::State st = entry->state; |
| 58 // TODO(koda): Support same thread re-entering same isolate with | 62 // TODO(koda): Support same thread re-entering same isolate with |
| 59 // Dart frames in between. For now, just assert it doesn't happen. | 63 // Dart frames in between. For now, just assert it doesn't happen. |
| 60 if (st.top_exit_frame_info != thread->top_exit_frame_info()) { | 64 if (st.top_exit_frame_info != thread->top_exit_frame_info()) { |
| 61 ASSERT(thread->top_exit_frame_info() == 0 || | 65 ASSERT(thread->top_exit_frame_info() == 0 || |
| 62 thread->top_exit_frame_info() > st.top_exit_frame_info); | 66 thread->top_exit_frame_info() > st.top_exit_frame_info); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 81 return false; | 85 return false; |
| 82 } | 86 } |
| 83 | 87 |
| 84 void SaveStateFrom(Thread* thread, const Thread::State& state) { | 88 void SaveStateFrom(Thread* thread, const Thread::State& state) { |
| 85 MonitorLocker ml(monitor_); | 89 MonitorLocker ml(monitor_); |
| 86 Entry* entry = FindEntry(thread); | 90 Entry* entry = FindEntry(thread); |
| 87 ASSERT(entry != NULL); | 91 ASSERT(entry != NULL); |
| 88 ASSERT(entry->scheduled); | 92 ASSERT(entry->scheduled); |
| 89 entry->scheduled = false; | 93 entry->scheduled = false; |
| 90 entry->state = state; | 94 entry->state = state; |
| 91 if (in_rendezvous_) { | 95 if (IsParticipant(thread)) { |
| 92 // Don't wait for this thread. | 96 // Update count (don't wait for this thread when resuming). |
| 93 ASSERT(remaining_ > 0); | 97 ASSERT(remaining_ > 0); |
| 94 if (--remaining_ == 0) { | 98 if (--remaining_ == 0) { |
| 95 ml.NotifyAll(); | 99 ml.NotifyAll(); |
| 96 } | 100 } |
| 97 } | 101 } |
| 98 } | 102 } |
| 99 | 103 |
| 100 bool Contains(Thread* thread) { | 104 bool Contains(Thread* thread) { |
| 101 MonitorLocker ml(monitor_); | 105 MonitorLocker ml(monitor_); |
| 102 return (FindEntry(thread) != NULL); | 106 return (FindEntry(thread) != NULL); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 151 if (entries_[i].thread == thread) { | 155 if (entries_[i].thread == thread) { |
| 152 return &entries_[i]; | 156 return &entries_[i]; |
| 153 } | 157 } |
| 154 } | 158 } |
| 155 return NULL; | 159 return NULL; |
| 156 } | 160 } |
| 157 | 161 |
| 158 // Note: Lock should be taken before this function is called. | 162 // Note: Lock should be taken before this function is called. |
| 159 void CheckSafepointLocked(); | 163 void CheckSafepointLocked(); |
| 160 | 164 |
| 161 // Returns the number threads that are scheduled on this isolate. | 165 // Returns true if there is a rendezvous in progress and the given thread |
| 162 // Note: Lock should be taken before this function is called. | 166 // is/will be a participant of it. |
| 163 intptr_t CountScheduledLocked(); | 167 bool IsParticipant(Thread* thread) { |
| 168 return in_rendezvous_ && (thread->pass_safepoint_ != round_); |
| 169 } |
| 164 | 170 |
| 165 Monitor* monitor_; // All access is synchronized through this monitor. | 171 Monitor* monitor_; // All access is synchronized through this monitor. |
| 166 MallocGrowableArray<Entry> entries_; | 172 MallocGrowableArray<Entry> entries_; |
| 167 | 173 |
| 168 // Safepoint rendezvous state. | 174 // Safepoint rendezvous state. |
| 169 bool in_rendezvous_; // A safepoint rendezvous request is in progress. | 175 bool in_rendezvous_; // A safepoint rendezvous request is in progress. |
| 170 intptr_t remaining_; // Number of threads yet to reach their safepoint. | 176 intptr_t remaining_; // Number of threads yet to reach their safepoint. |
| 171 int64_t round_; // Counter, to prevent missing updates to remaining_ | 177 int64_t round_; // Counter, to prevent missing updates to remaining_ |
| 172 // (see comments in CheckSafepointLocked). | 178 // (see comments in CheckSafepointLocked). |
| 173 | 179 |
| 174 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry); | 180 DISALLOW_COPY_AND_ASSIGN(ThreadRegistry); |
| 175 }; | 181 }; |
| 176 | 182 |
| 177 } // namespace dart | 183 } // namespace dart |
| 178 | 184 |
| 179 #endif // VM_THREAD_REGISTRY_H_ | 185 #endif // VM_THREAD_REGISTRY_H_ |
| OLD | NEW |