Chromium Code Reviews| 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 |