Index: src/sampler.cc |
diff --git a/src/sampler.cc b/src/sampler.cc |
index 394efeb7640764870b6f768a9d11a1b879955416..b155bb1b0dd64eabc1c898909e9d460c8b3a6271 100644 |
--- a/src/sampler.cc |
+++ b/src/sampler.cc |
@@ -1,7 +1,6 @@ |
// Copyright 2013 the V8 project authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
- |
alph
2014/09/09 13:54:37
Please revert
|
#include "src/sampler.h" |
#if V8_OS_POSIX && !V8_OS_CYGWIN |
@@ -44,6 +43,7 @@ |
#include "src/v8.h" |
+#include "src/base/logging.h" |
#include "src/base/platform/platform.h" |
#include "src/cpu-profiler-inl.h" |
#include "src/flags.h" |
@@ -275,8 +275,21 @@ class SimulatorHelper { |
class SignalHandler : public AllStatic { |
public: |
- static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); } |
- static void TearDown() { delete mutex_; mutex_ = NULL; } |
+ static void SetUp() { |
+ CHECK_EQ(NULL, mutex_); |
+ CHECK_EQ(NULL, sampling_semaphore_); |
+ |
+ mutex_ = new base::Mutex(); |
+ sampling_semaphore_ = new base::Semaphore(0); |
+ } |
+ |
+ static void TearDown() { |
+ delete mutex_; |
+ delete sampling_semaphore_; |
+ |
+ mutex_ = NULL; |
+ sampling_semaphore_ = NULL; |
+ } |
static void IncreaseSamplerCount() { |
base::LockGuard<base::Mutex> lock_guard(mutex_); |
@@ -320,14 +333,45 @@ class SignalHandler : public AllStatic { |
#if !V8_OS_NACL |
static void HandleProfilerSignal(int signal, siginfo_t* info, void* context); |
#endif |
+ |
+ // The SIGPROF could have come from DoSample or from GetSample. |
+ // GetSample is the internal endpoint for the public |
+ // GetSample API, which aims to bypass all the internal buffers |
+ // and return just one sample instead, rightaway. |
+ // TODO(gholap): Eventually, get rid of DoSample. |
+ // Only GetSample should remain. |
+ |
+ // This is the sample which will be filled by the call from GetSample. |
+ static TickSample sample_; |
+ |
+ // For the SIGPROF handler to know whether the call was from GetSample. |
+ static volatile bool called_from_get_sample_; |
+ |
+ // GetSample waits synchronously till the SIGPROF handler returns. |
+ // this semaphore is used to signal GetSample. |
+ static base::Semaphore* sampling_semaphore_; |
+ |
+ // It is not that every time HandleProfilerSignal is invoked, |
+ // it succeeds in obtaining a sample. |
+ // This provides GetSample with the information whether |
+ // the handler finished with or without getting the sample. |
+ static bool sample_available_; |
+ |
// Protects the process wide state below. |
static base::Mutex* mutex_; |
static int client_count_; |
static bool signal_handler_installed_; |
static struct sigaction old_signal_handler_; |
+ |
+ friend class Sampler; |
}; |
+TickSample SignalHandler::sample_; |
+volatile bool SignalHandler::called_from_get_sample_ = false; |
+base::Semaphore* SignalHandler::sampling_semaphore_ = NULL; |
+bool SignalHandler::sample_available_ = false; |
+ |
base::Mutex* SignalHandler::mutex_ = NULL; |
int SignalHandler::client_count_ = 0; |
struct sigaction SignalHandler::old_signal_handler_; |
@@ -338,6 +382,11 @@ bool SignalHandler::signal_handler_installed_ = false; |
#if !V8_OS_NACL |
void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
void* context) { |
+ // Even if we return prematurely, |
+ // we need to signal the sampling_semaphore_ |
+ sample_available_ = false; |
+ ScopedSemaphore scoped_semaphore(sampling_semaphore_); |
+ |
USE(info); |
if (signal != SIGPROF) return; |
Isolate* isolate = Isolate::UnsafeCurrent(); |
@@ -479,7 +528,12 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info, |
#endif // V8_HOST_ARCH_* |
#endif // V8_OS_QNX |
#endif // USE_SIMULATOR |
- sampler->SampleStack(state); |
+ if (called_from_get_sample_) { |
+ sample_.Init(sampler->isolate(), state); |
+ } else { |
+ sampler->SampleStack(state); |
+ } |
+ sample_available_ = true; |
} |
#endif // V8_OS_NACL |
@@ -582,6 +636,7 @@ DISABLE_ASAN void TickSample::Init(Isolate* isolate, |
timestamp = base::TimeTicks::HighResolutionNow(); |
pc = regs.pc; |
state = isolate->current_vm_state(); |
+ frames_count = 0; |
// Avoid collecting traces while doing GC. |
if (state == GC) return; |
@@ -706,9 +761,22 @@ void Sampler::DoSample() { |
pthread_kill(platform_data()->vm_tid(), SIGPROF); |
} |
+ |
+void Sampler::GetSample(v8::Sample* sample) { |
+ SignalHandler::called_from_get_sample_ = true; |
+ pthread_kill(platform_data()->vm_tid(), SIGPROF); |
+ SignalHandler::sampling_semaphore_->Wait(); |
+ if (SignalHandler::sample_available_) { |
+ sample = new (sample) v8::Sample( |
+ &SignalHandler::sample_.stack[0], |
+ &SignalHandler::sample_.stack[SignalHandler::sample_.frames_count]); |
+ } |
+ SignalHandler::called_from_get_sample_ = false; |
+} |
+ |
#elif V8_OS_WIN || V8_OS_CYGWIN |
-void Sampler::DoSample() { |
+void Sampler::GetSampleHelper(TickSample* sample, bool called_from_get_sample) { |
alph
2014/09/09 13:54:37
nit: you can get rid of the called_from_get_sample
gholap
2014/09/17 02:35:06
Done.
|
HANDLE profiled_thread = platform_data()->profiled_thread(); |
if (profiled_thread == NULL) return; |
@@ -739,11 +807,29 @@ void Sampler::DoSample() { |
state.fp = reinterpret_cast<Address>(context.Ebp); |
#endif |
#endif // USE_SIMULATOR |
- SampleStack(state); |
+ if (called_from_get_sample) { |
+ sample->Init(isolate_, state); |
+ } else { |
+ SampleStack(state); |
+ } |
} |
ResumeThread(profiled_thread); |
} |
+ |
+void Sampler::DoSample() { GetSampleHelper(NULL, false); } |
+ |
+ |
+void Sampler::GetSample(v8::Sample* sample) { |
+ // We need this tick_sample because, |
+ // GetSampleHelper calls Init, which must be called on |
+ // a TickSample and never on Sample. |
alph
2014/09/09 13:54:37
nit: I don't think this comment adds something her
gholap
2014/09/17 02:35:06
Acknowledged.
|
+ TickSample tick_sample; |
+ GetSampleHelper(&tick_sample, true); |
+ sample = new (sample) v8::Sample( |
+ &tick_sample.stack[0], &tick_sample.stack[tick_sample.frames_count]); |
+} |
+ |
#endif // USE_SIGNALS |