OLD | NEW |
---|---|
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/devtools/devtools_cpu_throttler.h" | 5 #include "content/renderer/devtools/devtools_cpu_throttler.h" |
6 | 6 |
7 #include "base/atomicops.h" | 7 #include "base/atomicops.h" |
8 #include "base/macros.h" | 8 #include "base/macros.h" |
9 #include "base/synchronization/cancellation_flag.h" | 9 #include "base/synchronization/cancellation_flag.h" |
10 #include "base/threading/platform_thread.h" | 10 #include "base/threading/platform_thread.h" |
11 #include "build/build_config.h" | 11 #include "build/build_config.h" |
12 | 12 |
13 #if defined(OS_POSIX) | 13 #if defined(OS_POSIX) |
14 #include <signal.h> | 14 #include <signal.h> |
15 #define USE_SIGNALS | 15 #define USE_SIGNALS 1 |
16 #endif | 16 #endif |
17 | 17 |
18 using base::subtle::Atomic32; | 18 using base::subtle::Atomic32; |
19 using base::subtle::Acquire_Load; | 19 using base::subtle::Acquire_Load; |
20 using base::subtle::Release_Store; | 20 using base::subtle::Release_Store; |
21 | 21 |
22 namespace content { | 22 namespace content { |
23 | 23 |
24 class CPUThrottlingThread final : public base::PlatformThread::Delegate { | 24 class CPUThrottlingThread final : public base::PlatformThread::Delegate { |
25 public: | 25 public: |
26 explicit CPUThrottlingThread(double rate); | 26 explicit CPUThrottlingThread(double rate); |
27 ~CPUThrottlingThread() override; | 27 ~CPUThrottlingThread() override; |
28 | 28 |
29 void SetThrottlingRate(double rate); | 29 void SetThrottlingRate(double rate); |
30 | 30 |
31 private: | 31 private: |
32 void ThreadMain() override; | 32 void ThreadMain() override; |
33 | 33 |
34 void Start(); | 34 void Start(); |
35 void Stop(); | 35 void Stop(); |
36 void Throttle(); | 36 void Throttle(); |
37 | 37 |
38 static void SuspendThread(base::PlatformThreadHandle thread_handle); | 38 static void SuspendThread(base::PlatformThreadHandle thread_handle); |
39 static void ResumeThread(base::PlatformThreadHandle thread_handle); | 39 static void ResumeThread(base::PlatformThreadHandle thread_handle); |
40 static void Sleep(base::TimeDelta duration); | |
40 | 41 |
41 #ifdef USE_SIGNALS | 42 #ifdef USE_SIGNALS |
42 void InstallSignalHandler(); | 43 void InstallSignalHandler(); |
43 void RestoreSignalHandler(); | 44 void RestoreSignalHandler(); |
44 static void HandleSignal(int signal); | 45 static void HandleSignal(int signal); |
45 | 46 |
46 static bool signal_handler_installed_; | 47 static bool signal_handler_installed_; |
47 static struct sigaction old_signal_handler_; | 48 static struct sigaction old_signal_handler_; |
48 static Atomic32 suspended_; | 49 static Atomic32 suspended_; |
49 #endif | 50 #endif |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
115 return; | 116 return; |
116 while (Acquire_Load(&suspended_)) { | 117 while (Acquire_Load(&suspended_)) { |
117 } | 118 } |
118 } | 119 } |
119 | 120 |
120 #endif // USE_SIGNALS | 121 #endif // USE_SIGNALS |
121 | 122 |
122 // static | 123 // static |
123 void CPUThrottlingThread::SuspendThread( | 124 void CPUThrottlingThread::SuspendThread( |
124 base::PlatformThreadHandle thread_handle) { | 125 base::PlatformThreadHandle thread_handle) { |
125 #ifdef USE_SIGNALS | 126 #if defined(USE_SIGNALS) |
126 Release_Store(&suspended_, 1); | 127 Release_Store(&suspended_, 1); |
127 pthread_kill(thread_handle.platform_handle(), SIGUSR2); | 128 pthread_kill(thread_handle.platform_handle(), SIGUSR2); |
129 #elif OS_WIN | |
caseq
2016/05/13 01:49:07
defined(OS_WIN)?
alph
2016/05/13 21:00:59
Done.
| |
130 ::SuspendThread(thread_handle.platform_handle()); | |
128 #endif | 131 #endif |
129 } | 132 } |
130 | 133 |
131 // static | 134 // static |
132 void CPUThrottlingThread::ResumeThread( | 135 void CPUThrottlingThread::ResumeThread( |
133 base::PlatformThreadHandle thread_handle) { | 136 base::PlatformThreadHandle thread_handle) { |
134 #ifdef USE_SIGNALS | 137 #if defined(USE_SIGNALS) |
135 Release_Store(&suspended_, 0); | 138 Release_Store(&suspended_, 0); |
139 #elif OS_WIN | |
caseq
2016/05/13 01:49:07
ditto
alph
2016/05/13 21:00:59
Done.
| |
140 ::ResumeThread(thread_handle.platform_handle()); | |
136 #endif | 141 #endif |
137 } | 142 } |
138 | 143 |
139 void CPUThrottlingThread::Start() { | 144 void CPUThrottlingThread::Start() { |
140 #ifdef USE_SIGNALS | 145 #ifdef USE_SIGNALS |
141 InstallSignalHandler(); | 146 InstallSignalHandler(); |
142 #endif | 147 #endif |
143 if (!base::PlatformThread::Create(0, this, &throttling_thread_handle_)) { | 148 if (!base::PlatformThread::Create(0, this, &throttling_thread_handle_)) { |
144 LOG(ERROR) << "Failed to create throttling thread."; | 149 LOG(ERROR) << "Failed to create throttling thread."; |
145 } | 150 } |
146 } | 151 } |
147 | 152 |
153 void CPUThrottlingThread::Sleep(base::TimeDelta duration) { | |
154 #if defined(USE_SIGNALS) | |
155 base::PlatformThread::Sleep(duration); | |
156 #elif OS_WIN | |
caseq
2016/05/13 01:49:07
ditto
alph
2016/05/13 21:00:59
Done.
| |
157 // We cannot rely on ::Sleep function as it's precision is not enough for | |
158 // the purpose. Could be up to 16ms jitter. | |
159 base::TimeTicks wakeup_time = base::TimeTicks::Now() + duration; | |
160 while (base::TimeTicks::Now() < wakeup_time) {} | |
161 #endif | |
caseq
2016/05/13 01:49:07
What do we do #else?
alph
2016/05/13 21:00:59
I don't want it to break the build if CPU throttli
| |
162 } | |
163 | |
148 void CPUThrottlingThread::Stop() { | 164 void CPUThrottlingThread::Stop() { |
149 cancellation_flag_.Set(); | 165 cancellation_flag_.Set(); |
150 base::PlatformThread::Join(throttling_thread_handle_); | 166 base::PlatformThread::Join(throttling_thread_handle_); |
151 #ifdef USE_SIGNALS | 167 #ifdef USE_SIGNALS |
152 RestoreSignalHandler(); | 168 RestoreSignalHandler(); |
153 #endif | 169 #endif |
154 } | 170 } |
155 | 171 |
156 void CPUThrottlingThread::Throttle() { | 172 void CPUThrottlingThread::Throttle() { |
157 const int quant_time_us = 200; | 173 const int quant_time_us = 200; |
158 double rate = Acquire_Load(&throttling_rate_percent_) / 100.; | 174 double rate = Acquire_Load(&throttling_rate_percent_) / 100.; |
159 base::TimeDelta run_duration = | 175 base::TimeDelta run_duration = |
160 base::TimeDelta::FromMicroseconds(static_cast<int>(quant_time_us / rate)); | 176 base::TimeDelta::FromMicroseconds(static_cast<int>(quant_time_us / rate)); |
161 base::TimeDelta sleep_duration = | 177 base::TimeDelta sleep_duration = |
162 base::TimeDelta::FromMicroseconds(quant_time_us) - run_duration; | 178 base::TimeDelta::FromMicroseconds(quant_time_us) - run_duration; |
163 base::PlatformThread::Sleep(run_duration); | 179 Sleep(run_duration); |
164 SuspendThread(throttled_thread_handle_); | 180 SuspendThread(throttled_thread_handle_); |
165 base::PlatformThread::Sleep(sleep_duration); | 181 Sleep(sleep_duration); |
166 ResumeThread(throttled_thread_handle_); | 182 ResumeThread(throttled_thread_handle_); |
167 } | 183 } |
168 | 184 |
169 DevToolsCPUThrottler::DevToolsCPUThrottler() {} | 185 DevToolsCPUThrottler::DevToolsCPUThrottler() {} |
170 | 186 |
171 DevToolsCPUThrottler::~DevToolsCPUThrottler() {} | 187 DevToolsCPUThrottler::~DevToolsCPUThrottler() {} |
172 | 188 |
173 void DevToolsCPUThrottler::SetThrottlingRate(double rate) { | 189 void DevToolsCPUThrottler::SetThrottlingRate(double rate) { |
174 if (rate <= 1) { | 190 if (rate <= 1) { |
175 if (throttling_thread_) { | 191 if (throttling_thread_) { |
176 throttling_thread_.reset(); | 192 throttling_thread_.reset(); |
177 } | 193 } |
178 return; | 194 return; |
179 } | 195 } |
180 if (throttling_thread_) { | 196 if (throttling_thread_) { |
181 throttling_thread_->SetThrottlingRate(rate); | 197 throttling_thread_->SetThrottlingRate(rate); |
182 } else { | 198 } else { |
183 throttling_thread_.reset(new CPUThrottlingThread(rate)); | 199 throttling_thread_.reset(new CPUThrottlingThread(rate)); |
184 } | 200 } |
185 } | 201 } |
186 | 202 |
187 } // namespace content | 203 } // namespace content |
OLD | NEW |