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

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
« 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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
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() {
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) {
141 // NoOp.
142 }
143
144
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) { 146 void ThreadInterrupter::ThreadMain(uword parameters) {
170 ASSERT(initialized_); 147 ASSERT(initialized_);
171 InstallSignalHandler(); 148 InstallSignalHandler();
172 if (FLAG_trace_thread_interrupter) { 149 if (FLAG_trace_thread_interrupter) {
173 OS::Print("ThreadInterrupter thread running.\n"); 150 OS::Print("ThreadInterrupter thread running.\n");
174 } 151 }
175 { 152 {
176 // Signal to main thread we are ready. 153 // Signal to main thread we are ready.
177 MonitorLocker startup_ml(monitor_); 154 MonitorLocker startup_ml(monitor_);
178 interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId(); 155 interrupter_thread_id_ = OSThread::GetCurrentThreadJoinId();
179 thread_running_ = true; 156 thread_running_ = true;
180 startup_ml.Notify(); 157 startup_ml.Notify();
181 } 158 }
182 { 159 {
183 ThreadInterrupterVisitIsolates visitor; 160 intptr_t interrupted_thread_count = 0;
184 current_wait_time_ = interrupt_period_; 161 current_wait_time_ = interrupt_period_;
185 MonitorLocker wait_ml(monitor_); 162 MonitorLocker wait_ml(monitor_);
186 while (!shutdown_) { 163 while (!shutdown_) {
187 intptr_t r = wait_ml.WaitMicros(current_wait_time_); 164 intptr_t r = wait_ml.WaitMicros(current_wait_time_);
188 165
189 if ((r == Monitor::kNotified) && shutdown_) { 166 if (shutdown_) {
190 break; 167 break;
191 } 168 }
192 169
193 if ((r == Monitor::kNotified) && InDeepSleep()) { 170 if ((r == Monitor::kNotified) && InDeepSleep()) {
194 // Woken up from deep sleep. 171 // Woken up from deep sleep.
195 ASSERT(visitor.profiled_thread_count() == 0); 172 ASSERT(interrupted_thread_count == 0);
196 // Return to regular interrupts. 173 // Return to regular interrupts.
197 current_wait_time_ = interrupt_period_; 174 current_wait_time_ = interrupt_period_;
198 } 175 }
199 176
200 // Reset count before visiting isolates. 177 // Reset count before interrupting any threads.
201 visitor.set_profiled_thread_count(0); 178 interrupted_thread_count = 0;
202 Isolate::VisitIsolates(&visitor);
203 179
204 if (visitor.profiled_thread_count() == 0) { 180 // Temporarily drop the monitor while we interrupt threads.
205 // No isolates were profiled. In order to reduce unnecessary CPU 181 monitor_->Exit();
206 // load, we will wait until we are notified before attempting to 182
207 // interrupt again. 183 {
184 ThreadIterator it;
185 while (it.HasNext()) {
186 Thread* thread = it.Next();
187 if (thread->ThreadInterruptsEnabled()) {
188 interrupted_thread_count++;
189 InterruptThread(thread);
190 }
191 }
192 }
193
194 // Take the monitor lock again.
195 monitor_->Enter();
196
197 // Now that we have the lock, check if we were signaled to wake up while
198 // interrupting threads.
199 if (!woken_up_ && (interrupted_thread_count == 0)) {
200 // No threads were interrupted and we were not signaled to interrupt
201 // new threads. In order to reduce unnecessary CPU load, we will wait
202 // until we are notified before attempting to interrupt again.
208 current_wait_time_ = Monitor::kNoTimeout; 203 current_wait_time_ = Monitor::kNoTimeout;
209 continue; 204 continue;
210 } 205 }
211 206
207 woken_up_ = false;
208
212 ASSERT(current_wait_time_ != Monitor::kNoTimeout); 209 ASSERT(current_wait_time_ != Monitor::kNoTimeout);
213 } 210 }
214 } 211 }
215 RemoveSignalHandler(); 212 RemoveSignalHandler();
216 if (FLAG_trace_thread_interrupter) { 213 if (FLAG_trace_thread_interrupter) {
217 OS::Print("ThreadInterrupter thread exiting.\n"); 214 OS::Print("ThreadInterrupter thread exiting.\n");
218 } 215 }
219 { 216 {
220 // Signal to main thread we are exiting. 217 // Signal to main thread we are exiting.
221 MonitorLocker shutdown_ml(monitor_); 218 MonitorLocker shutdown_ml(monitor_);
222 thread_running_ = false; 219 thread_running_ = false;
223 shutdown_ml.Notify(); 220 shutdown_ml.Notify();
224 } 221 }
225 } 222 }
226 223
227 } // namespace dart 224 } // 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