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 |