Chromium Code Reviews| Index: src/platform-linux.cc |
| diff --git a/src/platform-linux.cc b/src/platform-linux.cc |
| index d02244896bcf8930ecd895a92a7b2ab5a5365b32..09488a9a0bc0f6d45ba2a51e395104f2cee08c13 100644 |
| --- a/src/platform-linux.cc |
| +++ b/src/platform-linux.cc |
| @@ -1055,13 +1055,54 @@ static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
| } |
| +class CpuProfilerSignalHandler { |
| + public: |
| + static void InstallSignalHandler() { |
| + struct sigaction sa; |
| + sa.sa_sigaction = ProfilerSignalHandler; |
| + sigemptyset(&sa.sa_mask); |
| + sa.sa_flags = SA_RESTART | SA_SIGINFO; |
| + signal_handler_installed_ = |
| + (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
| + } |
| + |
| + static void RestoreSignalHandler() { |
| + if (signal_handler_installed_) { |
| + sigaction(SIGPROF, &old_signal_handler_, 0); |
| + signal_handler_installed_ = false; |
| + } |
| + } |
| + |
| + static bool signal_handler_installed() { return signal_handler_installed_; } |
| + |
| + private: |
| + static bool signal_handler_installed_; |
| + static struct sigaction old_signal_handler_; |
| +}; |
| + |
| + |
| +bool CpuProfilerSignalHandler::signal_handler_installed_ = false; |
| +struct sigaction CpuProfilerSignalHandler::old_signal_handler_; |
| + |
| + |
| class Sampler::PlatformData : public Malloced { |
| public: |
| - PlatformData() : vm_tid_(GetThreadID()) {} |
| + PlatformData() |
| + : vm_tgid_(getpid()), |
| + vm_tid_(GetThreadID()) {} |
| - int vm_tid() const { return vm_tid_; } |
| + void SendProfilingSignal() { |
| + if (!CpuProfilerSignalHandler::signal_handler_installed()) return; |
| + // Glibc doesn't provide a wrapper for tgkill(2). |
| +#if defined(ANDROID) |
| + syscall(__NR_tgkill, vm_tgid_, vm_tid_, SIGPROF); |
| +#else |
| + syscall(SYS_tgkill, vm_tgid_, vm_tid_, SIGPROF); |
| +#endif |
| + } |
| private: |
| + const int vm_tgid_; |
| const int vm_tid_; |
| }; |
| @@ -1077,28 +1118,11 @@ class SignalSender : public Thread { |
| explicit SignalSender(int interval) |
| : Thread(Thread::Options("SignalSender", kSignalSenderStackSize)), |
| - vm_tgid_(getpid()), |
| interval_(interval) {} |
| static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } |
| static void TearDown() { delete mutex_; } |
| - static void InstallSignalHandler() { |
| - struct sigaction sa; |
| - sa.sa_sigaction = ProfilerSignalHandler; |
| - sigemptyset(&sa.sa_mask); |
| - sa.sa_flags = SA_RESTART | SA_SIGINFO; |
| - signal_handler_installed_ = |
| - (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
| - } |
| - |
| - static void RestoreSignalHandler() { |
| - if (signal_handler_installed_) { |
| - sigaction(SIGPROF, &old_signal_handler_, 0); |
| - signal_handler_installed_ = false; |
| - } |
| - } |
| - |
| static void AddActiveSampler(Sampler* sampler) { |
| ScopedLock lock(mutex_); |
| SamplerRegistry::AddActiveSampler(sampler); |
| @@ -1119,7 +1143,6 @@ class SignalSender : public Thread { |
| RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_); |
| delete instance_; |
| instance_ = NULL; |
| - RestoreSignalHandler(); |
| } |
| } |
| @@ -1128,67 +1151,23 @@ class SignalSender : public Thread { |
| SamplerRegistry::State state; |
| while ((state = SamplerRegistry::GetState()) != |
| SamplerRegistry::HAS_NO_SAMPLERS) { |
| - bool cpu_profiling_enabled = |
| - (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS); |
| bool runtime_profiler_enabled = RuntimeProfiler::IsEnabled(); |
| - if (cpu_profiling_enabled && !signal_handler_installed_) { |
| - InstallSignalHandler(); |
| - } else if (!cpu_profiling_enabled && signal_handler_installed_) { |
| - RestoreSignalHandler(); |
| - } |
| - // When CPU profiling is enabled both JavaScript and C++ code is |
| - // profiled. We must not suspend. |
| - if (!cpu_profiling_enabled) { |
| - if (rate_limiter_.SuspendIfNecessary()) continue; |
| - } |
| - if (cpu_profiling_enabled && runtime_profiler_enabled) { |
| - if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) { |
| - return; |
| - } |
| - Sleep(HALF_INTERVAL); |
| - if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) { |
| + if (rate_limiter_.SuspendIfNecessary()) continue; |
| + if (runtime_profiler_enabled) { |
| + if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, |
| + NULL)) { |
| return; |
| } |
| - Sleep(HALF_INTERVAL); |
| - } else { |
| - if (cpu_profiling_enabled) { |
| - if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, |
| - this)) { |
| - return; |
| - } |
| - } |
| - if (runtime_profiler_enabled) { |
| - if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, |
| - NULL)) { |
| - return; |
| - } |
| - } |
| - Sleep(FULL_INTERVAL); |
| } |
| + Sleep(FULL_INTERVAL); |
| } |
| } |
| - static void DoCpuProfile(Sampler* sampler, void* raw_sender) { |
| - if (!sampler->IsProfiling()) return; |
| - SignalSender* sender = reinterpret_cast<SignalSender*>(raw_sender); |
| - sender->SendProfilingSignal(sampler->platform_data()->vm_tid()); |
| - } |
| - |
| static void DoRuntimeProfile(Sampler* sampler, void* ignored) { |
| if (!sampler->isolate()->IsInitialized()) return; |
| sampler->isolate()->runtime_profiler()->NotifyTick(); |
| } |
| - void SendProfilingSignal(int tid) { |
| - if (!signal_handler_installed_) return; |
| - // Glibc doesn't provide a wrapper for tgkill(2). |
| -#if defined(ANDROID) |
| - syscall(__NR_tgkill, vm_tgid_, tid, SIGPROF); |
| -#else |
| - syscall(SYS_tgkill, vm_tgid_, tid, SIGPROF); |
| -#endif |
| - } |
| - |
| void Sleep(SleepInterval full_or_half) { |
| // Convert ms to us and subtract 100 us to compensate delays |
| // occuring during signal delivery. |
| @@ -1211,15 +1190,12 @@ class SignalSender : public Thread { |
| #endif // ANDROID |
| } |
| - const int vm_tgid_; |
| const int interval_; |
| RuntimeProfilerRateLimiter rate_limiter_; |
| // Protects the process wide state below. |
| static Mutex* mutex_; |
| static SignalSender* instance_; |
| - static bool signal_handler_installed_; |
| - static struct sigaction old_signal_handler_; |
| private: |
| DISALLOW_COPY_AND_ASSIGN(SignalSender); |
| @@ -1228,8 +1204,6 @@ class SignalSender : public Thread { |
| Mutex* SignalSender::mutex_ = NULL; |
| SignalSender* SignalSender::instance_ = NULL; |
| -struct sigaction SignalSender::old_signal_handler_; |
| -bool SignalSender::signal_handler_installed_ = false; |
| void OS::SetUp() { |
| @@ -1257,11 +1231,13 @@ void OS::SetUp() { |
| } |
| #endif |
| SignalSender::SetUp(); |
| + CpuProfilerSignalHandler::InstallSignalHandler(); |
|
caseq
2012/09/03 11:59:58
Can we do this as necessary -- e.g. when a first p
|
| } |
| void OS::TearDown() { |
| SignalSender::TearDown(); |
| + CpuProfilerSignalHandler::RestoreSignalHandler(); |
|
caseq
2012/09/03 11:59:58
ditto
|
| delete limit_mutex; |
| } |
| @@ -1282,6 +1258,11 @@ Sampler::~Sampler() { |
| } |
| +void Sampler::DoSample() { |
| + platform_data()->SendProfilingSignal(); |
| +} |
| + |
| + |
| void Sampler::Start() { |
| ASSERT(!IsActive()); |
| SetActive(true); |