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

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

Issue 1423473004: Switch profiler from isolates to threads [second landing] (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
« no previous file with comments | « runtime/vm/thread_interrupter.h ('k') | runtime/vm/thread_interrupter_android.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 if (shutdown_) { 119 if (shutdown_) {
119 return; 120 return;
120 } 121 }
121 ASSERT(initialized_); 122 ASSERT(initialized_);
122 ASSERT(period > 0); 123 ASSERT(period > 0);
123 interrupt_period_ = period; 124 interrupt_period_ = period;
124 } 125 }
125 126
126 127
127 void ThreadInterrupter::WakeUp() { 128 void ThreadInterrupter::WakeUp() {
129 if (!initialized_) {
130 // Early call.
131 return;
132 }
128 ASSERT(initialized_); 133 ASSERT(initialized_);
129 { 134 {
130 MonitorLocker ml(monitor_); 135 MonitorLocker ml(monitor_);
136 woken_up_ = true;
131 if (!InDeepSleep()) { 137 if (!InDeepSleep()) {
132 // No need to notify, regularly waking up. 138 // No need to notify, regularly waking up.
133 return; 139 return;
134 } 140 }
135 // Notify the interrupter to wake it from its deep sleep. 141 // Notify the interrupter to wake it from its deep sleep.
136 ml.Notify(); 142 ml.Notify();
137 } 143 }
138 } 144 }
139 145
140 146
141 void ThreadInterruptNoOp(const InterruptedThreadState& state, void* data) {
142 // NoOp.
143 }
144
145
146 class ThreadInterrupterVisitIsolates : public IsolateVisitor {
147 public:
148 ThreadInterrupterVisitIsolates() {
149 profiled_thread_count_ = 0;
150 }
151
152 void VisitIsolate(Isolate* isolate) {
153 ASSERT(isolate != NULL);
154 profiled_thread_count_ += isolate->ProfileInterrupt();
155 }
156
157 intptr_t profiled_thread_count() const {
158 return profiled_thread_count_;
159 }
160
161 void set_profiled_thread_count(intptr_t profiled_thread_count) {
162 profiled_thread_count_ = profiled_thread_count;
163 }
164
165 private:
166 intptr_t profiled_thread_count_;
167 };
168
169
170 void ThreadInterrupter::ThreadMain(uword parameters) { 147 void ThreadInterrupter::ThreadMain(uword parameters) {
171 ASSERT(initialized_); 148 ASSERT(initialized_);
172 InstallSignalHandler(); 149 InstallSignalHandler();
173 if (FLAG_trace_thread_interrupter) { 150 if (FLAG_trace_thread_interrupter) {
174 OS::Print("ThreadInterrupter thread running.\n"); 151 OS::Print("ThreadInterrupter thread running.\n");
175 } 152 }
176 { 153 {
177 // Signal to main thread we are ready. 154 // Signal to main thread we are ready.
178 MonitorLocker startup_ml(monitor_); 155 MonitorLocker startup_ml(monitor_);
179 interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId(); 156 interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId();
180 thread_running_ = true; 157 thread_running_ = true;
181 startup_ml.Notify(); 158 startup_ml.Notify();
182 } 159 }
183 { 160 {
184 ThreadInterrupterVisitIsolates visitor; 161 intptr_t interrupted_thread_count = 0;
185 current_wait_time_ = interrupt_period_; 162 current_wait_time_ = interrupt_period_;
186 MonitorLocker wait_ml(monitor_); 163 MonitorLocker wait_ml(monitor_);
187 while (!shutdown_) { 164 while (!shutdown_) {
188 intptr_t r = wait_ml.WaitMicros(current_wait_time_); 165 intptr_t r = wait_ml.WaitMicros(current_wait_time_);
189 166
190 if ((r == Monitor::kNotified) && shutdown_) { 167 if (shutdown_) {
191 break; 168 break;
192 } 169 }
193 170
194 if ((r == Monitor::kNotified) && InDeepSleep()) { 171 if ((r == Monitor::kNotified) && InDeepSleep()) {
195 // Woken up from deep sleep. 172 // Woken up from deep sleep.
196 ASSERT(visitor.profiled_thread_count() == 0); 173 ASSERT(interrupted_thread_count == 0);
197 // Return to regular interrupts. 174 // Return to regular interrupts.
198 current_wait_time_ = interrupt_period_; 175 current_wait_time_ = interrupt_period_;
199 } 176 }
200 177
201 // Reset count before visiting isolates. 178 // Reset count before interrupting any threads.
202 visitor.set_profiled_thread_count(0); 179 interrupted_thread_count = 0;
203 Isolate::VisitIsolates(&visitor);
204 180
205 if (visitor.profiled_thread_count() == 0) { 181 // Temporarily drop the monitor while we interrupt threads.
206 // No isolates were profiled. In order to reduce unnecessary CPU 182 monitor_->Exit();
207 // load, we will wait until we are notified before attempting to 183
208 // interrupt again. 184 {
185 ThreadIterator it;
186 while (it.HasNext()) {
187 Thread* thread = it.Next();
188 if (thread->ThreadInterruptsEnabled()) {
189 interrupted_thread_count++;
190 InterruptThread(thread);
191 }
192 }
193 }
194
195 // Take the monitor lock again.
196 monitor_->Enter();
197
198 // Now that we have the lock, check if we were signaled to wake up while
199 // interrupting threads.
200 if (!woken_up_ && (interrupted_thread_count == 0)) {
201 // No threads were interrupted and we were not signaled to interrupt
202 // new threads. In order to reduce unnecessary CPU load, we will wait
203 // until we are notified before attempting to interrupt again.
209 current_wait_time_ = Monitor::kNoTimeout; 204 current_wait_time_ = Monitor::kNoTimeout;
210 continue; 205 continue;
211 } 206 }
212 207
208 woken_up_ = false;
209
213 ASSERT(current_wait_time_ != Monitor::kNoTimeout); 210 ASSERT(current_wait_time_ != Monitor::kNoTimeout);
214 } 211 }
215 } 212 }
216 RemoveSignalHandler(); 213 RemoveSignalHandler();
217 if (FLAG_trace_thread_interrupter) { 214 if (FLAG_trace_thread_interrupter) {
218 OS::Print("ThreadInterrupter thread exiting.\n"); 215 OS::Print("ThreadInterrupter thread exiting.\n");
219 } 216 }
220 { 217 {
221 // Signal to main thread we are exiting. 218 // Signal to main thread we are exiting.
222 MonitorLocker shutdown_ml(monitor_); 219 MonitorLocker shutdown_ml(monitor_);
223 thread_running_ = false; 220 thread_running_ = false;
224 shutdown_ml.Notify(); 221 shutdown_ml.Notify();
225 } 222 }
226 } 223 }
227 224
228 } // namespace dart 225 } // namespace dart
OLDNEW
« no previous file with comments | « runtime/vm/thread_interrupter.h ('k') | runtime/vm/thread_interrupter_android.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698