Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(362)

Side by Side Diff: runtime/vm/thread_interrupter.cc

Issue 1412733008: Switch profiler from isolates to threads (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 #include "vm/thread_interrupter.h" 5 #include "vm/thread_interrupter.h"
6 6
7 #include "vm/flags.h" 7 #include "vm/flags.h"
8 #include "vm/lockers.h" 8 #include "vm/lockers.h"
9 #include "vm/os.h" 9 #include "vm/os.h"
10 #include "vm/simulator.h" 10 #include "vm/simulator.h"
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
44 // thread local storage pointer is set again. This has an important side 44 // thread local storage pointer is set again. This has an important side
45 // effect: if the thread is interrupted by a signal handler during a ThreadState 45 // effect: if the thread is interrupted by a signal handler during a ThreadState
46 // update the signal handler will immediately return. 46 // update the signal handler will immediately return.
47 47
48 DEFINE_FLAG(bool, trace_thread_interrupter, false, 48 DEFINE_FLAG(bool, trace_thread_interrupter, false,
49 "Trace thread interrupter"); 49 "Trace thread interrupter");
50 50
51 bool ThreadInterrupter::initialized_ = false; 51 bool ThreadInterrupter::initialized_ = false;
52 bool ThreadInterrupter::shutdown_ = false; 52 bool ThreadInterrupter::shutdown_ = false;
53 bool ThreadInterrupter::thread_running_ = false; 53 bool ThreadInterrupter::thread_running_ = false;
54 bool ThreadInterrupter::woken_up_ = false;
54 ThreadJoinId ThreadInterrupter::interrupter_thread_id_ = 55 ThreadJoinId ThreadInterrupter::interrupter_thread_id_ =
55 OSThread::kInvalidThreadJoinId; 56 OSThread::kInvalidThreadJoinId;
56 Monitor* ThreadInterrupter::monitor_ = NULL; 57 Monitor* ThreadInterrupter::monitor_ = NULL;
57 intptr_t ThreadInterrupter::interrupt_period_ = 1000; 58 intptr_t ThreadInterrupter::interrupt_period_ = 1000;
58 intptr_t ThreadInterrupter::current_wait_time_ = Monitor::kNoTimeout; 59 intptr_t ThreadInterrupter::current_wait_time_ = Monitor::kNoTimeout;
59 60
60 61
61 void ThreadInterrupter::InitOnce() { 62 void ThreadInterrupter::InitOnce() {
62 ASSERT(!initialized_); 63 ASSERT(!initialized_);
63 monitor_ = new Monitor(); 64 monitor_ = new Monitor();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 void ThreadInterrupter::SetInterruptPeriod(intptr_t period) { 117 void ThreadInterrupter::SetInterruptPeriod(intptr_t period) {
117 if (shutdown_) { 118 if (shutdown_) {
118 return; 119 return;
119 } 120 }
120 ASSERT(initialized_); 121 ASSERT(initialized_);
121 ASSERT(period > 0); 122 ASSERT(period > 0);
122 interrupt_period_ = period; 123 interrupt_period_ = period;
123 } 124 }
124 125
125 126
126 void ThreadInterrupter::WakeUp() { 127 void ThreadInterrupter::WakeUp() {
Ivan Posva 2015/10/28 08:27:47 It is not clear to me from this CL when the Thread
128 if (!initialized_) {
129 // Early call.
130 return;
131 }
127 ASSERT(initialized_); 132 ASSERT(initialized_);
128 { 133 {
129 MonitorLocker ml(monitor_); 134 MonitorLocker ml(monitor_);
135 woken_up_ = true;
130 if (!InDeepSleep()) { 136 if (!InDeepSleep()) {
131 // No need to notify, regularly waking up. 137 // No need to notify, regularly waking up.
132 return; 138 return;
133 } 139 }
134 // Notify the interrupter to wake it from its deep sleep. 140 // Notify the interrupter to wake it from its deep sleep.
135 ml.Notify(); 141 ml.Notify();
136 } 142 }
137 } 143 }
138 144
139 145
140 void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) { 146 void ThreadInterruptNoOp(Thread* thread, const InterruptedThreadState& state) {
Ivan Posva 2015/10/28 08:27:47 Where is this used?
Cutch 2015/10/28 14:39:19 Nowhere. It's gone now.
141 // NoOp. 147 // NoOp.
142 } 148 }
143 149
144 150
145 class ThreadInterrupterVisitIsolates : public IsolateVisitor {
146 public:
147 ThreadInterrupterVisitIsolates() {
148 profiled_thread_count_ = 0;
149 }
150
151 void VisitIsolate(Isolate* isolate) {
152 ASSERT(isolate != NULL);
153 profiled_thread_count_ += isolate->ProfileInterrupt();
154 }
155
156 intptr_t profiled_thread_count() const {
157 return profiled_thread_count_;
158 }
159
160 void set_profiled_thread_count(intptr_t profiled_thread_count) {
161 profiled_thread_count_ = profiled_thread_count;
162 }
163
164 private:
165 intptr_t profiled_thread_count_;
166 };
167
168
169 void ThreadInterrupter::ThreadMain(uword parameters) { 151 void ThreadInterrupter::ThreadMain(uword parameters) {
170 ASSERT(initialized_); 152 ASSERT(initialized_);
171 InstallSignalHandler(); 153 InstallSignalHandler();
172 if (FLAG_trace_thread_interrupter) { 154 if (FLAG_trace_thread_interrupter) {
173 OS::Print("ThreadInterrupter thread running.\n"); 155 OS::Print("ThreadInterrupter thread running.\n");
174 } 156 }
175 { 157 {
176 // Signal to main thread we are ready. 158 // Signal to main thread we are ready.
177 MonitorLocker startup_ml(monitor_); 159 MonitorLocker startup_ml(monitor_);
178 interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId(); 160 interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId();
179 thread_running_ = true; 161 thread_running_ = true;
180 startup_ml.Notify(); 162 startup_ml.Notify();
181 } 163 }
182 { 164 {
183 ThreadInterrupterVisitIsolates visitor; 165 intptr_t interrupted_thread_count = 0;
184 current_wait_time_ = interrupt_period_; 166 current_wait_time_ = interrupt_period_;
185 MonitorLocker wait_ml(monitor_); 167 MonitorLocker wait_ml(monitor_);
186 while (!shutdown_) { 168 while (!shutdown_) {
187 intptr_t r = wait_ml.WaitMicros(current_wait_time_); 169 intptr_t r = wait_ml.WaitMicros(current_wait_time_);
188 170
189 if ((r == Monitor::kNotified) && shutdown_) { 171 if ((r == Monitor::kNotified) && shutdown_) {
Ivan Posva 2015/10/28 08:27:47 Shouldn't we break out of the loop regardless whet
Cutch 2015/10/28 14:39:19 Done.
190 break; 172 break;
191 } 173 }
192 174
193 if ((r == Monitor::kNotified) && InDeepSleep()) { 175 if ((r == Monitor::kNotified) && InDeepSleep()) {
194 // Woken up from deep sleep. 176 // Woken up from deep sleep.
195 ASSERT(visitor.profiled_thread_count() == 0); 177 ASSERT(interrupted_thread_count == 0);
196 // Return to regular interrupts. 178 // Return to regular interrupts.
197 current_wait_time_ = interrupt_period_; 179 current_wait_time_ = interrupt_period_;
198 } 180 }
199 181
200 // Reset count before visiting isolates. 182 // Reset count before interrupting any threads.
201 visitor.set_profiled_thread_count(0); 183 interrupted_thread_count = 0;
202 Isolate::VisitIsolates(&visitor);
203 184
204 if (visitor.profiled_thread_count() == 0) { 185 // Temporarily drop the monitor while we interrupt threads.
205 // No isolates were profiled. In order to reduce unnecessary CPU 186 monitor_->Exit();
206 // load, we will wait until we are notified before attempting to 187
207 // interrupt again. 188 {
189 ThreadIterator it;
190 while (it.HasNext()) {
191 Thread* thread = it.Next();
192 if (thread->ThreadInterruptsEnabled()) {
193 interrupted_thread_count++;
194 InterruptThread(thread);
195 }
196 }
197 }
198
199 // Take the monitor lock again.
200 monitor_->Enter();
201
202 // Now that we have the lock, check if we were signal to wake up while
203 // interrupting threads.
204 const bool woken_up = woken_up_;
205 // Clear the state.
206 woken_up_ = false;
207
208 if (!woken_up && (interrupted_thread_count == 0)) {
209 // No threads were interrupted and we were not signaled to interrupt
210 // new threads. In order to reduce unnecessary CPU load, we will wait
211 // until we are notified before attempting to interrupt again.
208 current_wait_time_ = Monitor::kNoTimeout; 212 current_wait_time_ = Monitor::kNoTimeout;
209 continue; 213 continue;
210 } 214 }
211 215
212 ASSERT(current_wait_time_ != Monitor::kNoTimeout); 216 ASSERT(current_wait_time_ != Monitor::kNoTimeout);
213 } 217 }
214 } 218 }
215 RemoveSignalHandler(); 219 RemoveSignalHandler();
216 if (FLAG_trace_thread_interrupter) { 220 if (FLAG_trace_thread_interrupter) {
217 OS::Print("ThreadInterrupter thread exiting.\n"); 221 OS::Print("ThreadInterrupter thread exiting.\n");
218 } 222 }
219 { 223 {
220 // Signal to main thread we are exiting. 224 // Signal to main thread we are exiting.
221 MonitorLocker shutdown_ml(monitor_); 225 MonitorLocker shutdown_ml(monitor_);
222 thread_running_ = false; 226 thread_running_ = false;
223 shutdown_ml.Notify(); 227 shutdown_ml.Notify();
224 } 228 }
225 } 229 }
226 230
227 } // namespace dart 231 } // namespace dart
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698