Index: src/sampler.cc |
diff --git a/src/sampler.cc b/src/sampler.cc |
index 277462977d2ae68cafca1a0426edf1bdb81eee36..79c871b391008eb6eeea8e008ba62f939b257caf 100644 |
--- a/src/sampler.cc |
+++ b/src/sampler.cc |
@@ -65,12 +65,6 @@ |
#include "v8threads.h" |
-namespace v8 { |
-namespace internal { |
- |
- |
-#if defined(USE_SIGNALS) |
- |
#if defined(__ANDROID__) && !defined(__BIONIC_HAVE_UCONTEXT_T) |
// Not all versions of Android's C library provide ucontext_t. |
@@ -146,6 +140,11 @@ enum { REG_EBP = 6, REG_ESP = 7, REG_EIP = 14 }; |
#endif // __ANDROID__ && !defined(__BIONIC_HAVE_UCONTEXT_T) |
+namespace v8 { |
+namespace internal { |
+ |
+#if defined(USE_SIGNALS) |
+ |
class Sampler::PlatformData : public Malloced { |
public: |
PlatformData() |
@@ -161,7 +160,41 @@ class Sampler::PlatformData : public Malloced { |
}; |
-static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) { |
+class SignalHandler : public AllStatic { |
+ public: |
+ static inline void EnsureInstalled() { |
+ if (signal_handler_installed_) return; |
+ struct sigaction sa; |
+ sa.sa_sigaction = &HandleProfilerSignal; |
+ sigemptyset(&sa.sa_mask); |
+ sa.sa_flags = SA_RESTART | SA_SIGINFO; |
+ signal_handler_installed_ = |
+ (sigaction(SIGPROF, &sa, &old_signal_handler_) == 0); |
+ } |
+ |
+ static inline void Restore() { |
+ if (signal_handler_installed_) { |
+ sigaction(SIGPROF, &old_signal_handler_, 0); |
+ signal_handler_installed_ = false; |
+ } |
+ } |
+ |
+ static inline bool Installed() { |
+ return signal_handler_installed_; |
+ } |
+ |
+ private: |
+ static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
+ static bool signal_handler_installed_; |
+ static struct sigaction old_signal_handler_; |
+}; |
+ |
+struct sigaction SignalHandler::old_signal_handler_; |
+bool SignalHandler::signal_handler_installed_ = false; |
+ |
+ |
+void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
+ void* context) { |
#if defined(__native_client__) |
// As Native Client does not support signal handling, profiling |
// is disabled. |
@@ -361,82 +394,77 @@ class SamplerThread : public Thread { |
static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); } |
static void TearDown() { delete mutex_; } |
-#if defined(USE_SIGNALS) |
- 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; |
- } |
- } |
-#endif |
- |
static void AddActiveSampler(Sampler* sampler) { |
+ bool need_to_start = false; |
ScopedLock lock(mutex_); |
- SamplerRegistry::AddActiveSampler(sampler); |
if (instance_ == NULL) { |
// Start a thread that will send SIGPROF signal to VM threads, |
// when CPU profiling will be enabled. |
instance_ = new SamplerThread(sampler->interval()); |
- instance_->StartSynchronously(); |
- } else { |
- ASSERT(instance_->interval_ == sampler->interval()); |
+ need_to_start = true; |
} |
+ |
+ ASSERT(sampler->IsActive()); |
+ ASSERT(!instance_->active_samplers_.Contains(sampler)); |
+ ASSERT(instance_->interval_ == sampler->interval()); |
+ instance_->active_samplers_.Add(sampler); |
+ |
+#if defined(USE_SIGNALS) |
+ SignalHandler::EnsureInstalled(); |
+#endif |
+ if (need_to_start) instance_->StartSynchronously(); |
} |
static void RemoveActiveSampler(Sampler* sampler) { |
- ScopedLock lock(mutex_); |
- SamplerRegistry::RemoveActiveSampler(sampler); |
- if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) { |
- instance_->Join(); |
- delete instance_; |
- instance_ = NULL; |
+ SamplerThread* instance_to_remove = NULL; |
+ { |
+ ScopedLock lock(mutex_); |
+ |
+ ASSERT(sampler->IsActive()); |
+ bool removed = instance_->active_samplers_.RemoveElement(sampler); |
+ ASSERT(removed); |
+ USE(removed); |
+ |
+ // We cannot delete the instance immediately as we need to Join() the |
+ // thread but we are holding mutex_ and the thread may try to acquire it. |
+ if (instance_->active_samplers_.is_empty()) { |
+ instance_to_remove = instance_; |
+ instance_ = NULL; |
#if defined(USE_SIGNALS) |
- RestoreSignalHandler(); |
+ SignalHandler::Restore(); |
#endif |
+ } |
} |
+ |
+ if (!instance_to_remove) return; |
+ instance_to_remove->Join(); |
+ delete instance_to_remove; |
} |
// Implement Thread::Run(). |
virtual void Run() { |
- SamplerRegistry::State state; |
- while ((state = SamplerRegistry::GetState()) != |
- SamplerRegistry::HAS_NO_SAMPLERS) { |
- // When CPU profiling is enabled both JavaScript and C++ code is |
- // profiled. We must not suspend. |
- if (state == SamplerRegistry::HAS_CPU_PROFILING_SAMPLERS) { |
-#if defined(USE_SIGNALS) |
- if (!signal_handler_installed_) InstallSignalHandler(); |
-#endif |
- SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this); |
- } else { |
-#if defined(USE_SIGNALS) |
- if (signal_handler_installed_) RestoreSignalHandler(); |
-#endif |
+ while (true) { |
+ { |
+ ScopedLock lock(mutex_); |
+ if (active_samplers_.is_empty()) break; |
+ // When CPU profiling is enabled both JavaScript and C++ code is |
+ // profiled. We must not suspend. |
+ for (int i = 0; i < active_samplers_.length(); ++i) { |
+ Sampler* sampler = active_samplers_.at(i); |
+ if (!sampler->isolate()->IsInitialized()) continue; |
+ if (!sampler->IsProfiling()) continue; |
+ SampleContext(sampler); |
+ } |
} |
OS::Sleep(interval_); |
} |
} |
- static void DoCpuProfile(Sampler* sampler, void* raw_sender) { |
- if (!sampler->isolate()->IsInitialized()) return; |
- if (!sampler->IsProfiling()) return; |
- SamplerThread* sender = reinterpret_cast<SamplerThread*>(raw_sender); |
- sender->SampleContext(sampler); |
- } |
- |
+ private: |
#if defined(USE_SIGNALS) |
void SampleContext(Sampler* sampler) { |
- if (!signal_handler_installed_) return; |
+ if (!SignalHandler::Installed()) return; |
pthread_t tid = sampler->platform_data()->vm_tid(); |
int result = pthread_kill(tid, SIGPROF); |
USE(result); |
@@ -575,27 +603,20 @@ class SamplerThread : public Thread { |
#endif // USE_SIGNALS |
- const int interval_; |
// Protects the process wide state below. |
static Mutex* mutex_; |
static SamplerThread* instance_; |
-#if defined(USE_SIGNALS) |
- static bool signal_handler_installed_; |
- static struct sigaction old_signal_handler_; |
-#endif |
- private: |
+ const int interval_; |
+ List<Sampler*> active_samplers_; |
+ |
DISALLOW_COPY_AND_ASSIGN(SamplerThread); |
}; |
Mutex* SamplerThread::mutex_ = NULL; |
SamplerThread* SamplerThread::instance_ = NULL; |
-#if defined(USE_SIGNALS) |
-struct sigaction SamplerThread::old_signal_handler_; |
-bool SamplerThread::signal_handler_installed_ = false; |
-#endif |
void Sampler::SetUp() { |