Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Unified Diff: src/sampler.cc

Issue 422593003: Initial GetSample implementation. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Moved initialization of sample from the signal emitter to sigal handler thread. Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« src/api.cc ('K') | « src/sampler.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/sampler.cc
diff --git a/src/sampler.cc b/src/sampler.cc
index 0ed4b379626a9746038b6e05b1661cee522f4f1f..cd69c1cfe03067285b4eb3950dd2592295bed451 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.
-
#include "src/sampler.h"
#if V8_OS_POSIX && !V8_OS_CYGWIN
@@ -42,6 +41,8 @@
#endif
+#include "include/v8-sampler.h"
+
#include "src/v8.h"
#include "src/base/platform/platform.h"
@@ -269,8 +270,16 @@ class SimulatorHelper {
class SignalHandler : public AllStatic {
public:
- static void SetUp() { if (!mutex_) mutex_ = new base::Mutex(); }
- static void TearDown() { delete mutex_; }
+ static void SetUp() {
+ if (!mutex_) mutex_ = new base::Mutex();
+ if (!new_sample_semaphore_)
+ new_sample_semaphore_ = new base::Semaphore(0);
+ }
+
+ static void TearDown() {
+ delete mutex_;
+ delete new_sample_semaphore_;
+ }
static void IncreaseSamplerCount() {
base::LockGuard<base::Mutex> lock_guard(mutex_);
@@ -286,6 +295,7 @@ class SignalHandler : public AllStatic {
return signal_handler_installed_;
}
+
fmeawad 2014/07/29 18:30:50 Delete the added line.
gholap 2014/07/29 23:25:20 Done.
private:
static void Install() {
struct sigaction sa;
@@ -308,14 +318,43 @@ class SignalHandler : public AllStatic {
}
static void HandleProfilerSignal(int signal, siginfo_t* info, void* context);
+
+ // 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.
fmeawad 2014/07/29 18:30:50 Add a TODO that we will eventually have GetSample,
gholap 2014/07/29 23:25:20 Done.
+
+ // 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 bool called_from_get_sample_;
+
+ // GetSample waits synchronously till the SIGPROF handler returns.
+ // this semaphore is used to signal GetSample.
+ static base::Semaphore* new_sample_semaphore_;
fmeawad 2014/07/29 18:30:50 I would call it, sampling_semaphore instead.
gholap 2014/07/29 23:25:20 Done.
+
+ // 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 new_sample_available_;
fmeawad 2014/07/29 18:30:50 just sample_available_
gholap 2014/07/29 23:25:20 Done.
+
// 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_;
+bool SignalHandler::called_from_get_sample_ = false;
+base::Semaphore* SignalHandler::new_sample_semaphore_ = NULL;
+bool SignalHandler::new_sample_available_ = false;
+
base::Mutex* SignalHandler::mutex_ = NULL;
int SignalHandler::client_count_ = 0;
struct sigaction SignalHandler::old_signal_handler_;
@@ -329,32 +368,40 @@ void SignalHandler::HandleProfilerSignal(int signal, siginfo_t* info,
// is disabled.
return;
#else
+
+#define SIGNAL_AND_RETURN(GOT_NEW) \
fmeawad 2014/07/29 18:30:50 Explain why this macro is needed.
gholap 2014/07/29 23:25:20 Done.
+ { \
+ new_sample_available_ = GOT_NEW; \
+ new_sample_semaphore_->Signal(); \
+ return; \
+ }
+
USE(info);
- if (signal != SIGPROF) return;
+ if (signal != SIGPROF) SIGNAL_AND_RETURN(false);
Isolate* isolate = Isolate::UncheckedReentrantCurrent();
if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
// We require a fully initialized and entered isolate.
- return;
+ SIGNAL_AND_RETURN(false);
}
if (v8::Locker::IsActive() &&
!isolate->thread_manager()->IsLockedByCurrentThread()) {
- return;
+ SIGNAL_AND_RETURN(false);
}
Sampler* sampler = isolate->logger()->sampler();
- if (sampler == NULL) return;
+ if (sampler == NULL) SIGNAL_AND_RETURN(false);
RegisterState state;
#if defined(USE_SIMULATOR)
SimulatorHelper helper;
- if (!helper.Init(sampler, isolate)) return;
+ if (!helper.Init(sampler, isolate)) SIGNAL_AND_RETURN(false);
helper.FillRegisters(&state);
// It possible that the simulator is interrupted while it is updating
// the sp or fp register. ARM64 simulator does this in two steps:
// first setting it to zero and then setting it to the new value.
// Bailout if sp/fp doesn't contain the new value.
- if (state.sp == 0 || state.fp == 0) return;
+ if (state.sp == 0 || state.fp == 0) SIGNAL_AND_RETURN(false);
#else
// Extracting the sample from the context is extremely machine dependent.
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
@@ -466,7 +513,13 @@ 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);
+ }
+ SIGNAL_AND_RETURN(true);
+#undef SIGNAL_AND_RETURN
#endif // V8_OS_NACL
}
@@ -669,7 +722,7 @@ void Sampler::DecreaseProfilingDepth() {
}
-void Sampler::SampleStack(const RegisterState& state) {
+void Sampler::SampleStack(const RegisterState& state)
TickSample* sample = isolate_->cpu_profiler()->StartTickSample();
TickSample sample_obj;
if (sample == NULL) sample = &sample_obj;
@@ -693,19 +746,39 @@ void Sampler::DoSample() {
pthread_kill(platform_data()->vm_tid(), SIGPROF);
}
+
+TickSample* Sampler::GetSample(TickSample* sample) {
+ if (!SignalHandler::Installed()) return NULL;
+ SignalHandler::called_from_get_sample_ = true;
+ pthread_kill(platform_data()->vm_tid(), SIGPROF);
+ SignalHandler::new_sample_semaphore_->Wait();
+ if (SignalHandler::new_sample_available_) {
+ sample->state = SignalHandler::sample_.state;
+ for (int i = 0; i < SignalHandler::sample_.frames_count; i++) {
+ sample->stack[i] = SignalHandler::sample_.stack[i];
+ }
+ sample->frames_count = SignalHandler::sample_.frames_count;
+ } else {
+ sample = NULL;
+ }
+ SignalHandler::called_from_get_sample_ = false;
+ return sample;
+}
+
#elif V8_OS_WIN || V8_OS_CYGWIN
-void Sampler::DoSample() {
+TickSample* Sampler::GetSampleHelper_(TickSample * sample,
+ bool called_from_get_sample) {
HANDLE profiled_thread = platform_data()->profiled_thread();
- if (profiled_thread == NULL) return;
+ if (profiled_thread == NULL) return NULL;
#if defined(USE_SIMULATOR)
SimulatorHelper helper;
- if (!helper.Init(this, isolate())) return;
+ if (!helper.Init(this, isolate())) return NULL;
#endif
const DWORD kSuspendFailed = static_cast<DWORD>(-1);
- if (SuspendThread(profiled_thread) == kSuspendFailed) return;
+ if (SuspendThread(profiled_thread) == kSuspendFailed) return NULL;
// Context used for sampling the register state of the profiled thread.
CONTEXT context;
@@ -726,9 +799,24 @@ void Sampler::DoSample() {
state.fp = reinterpret_cast<Address>(context.Ebp);
#endif
#endif // USE_SIMULATOR
- SampleStack(state);
+ if (called_from_get_sample) {
+ sample->Init(sampler->isolate(), state);
+ } else {
+ SampleStack(state);
+ }
}
ResumeThread(profiled_thread);
+ return sample;
+}
+
+
+void Sampler::DoSample() {
+ GetSampleHelper_(NULL, false);
+}
+
+
+TickSample* Sampler::GetSample(TickSample* sample) {
+ return GetSampleHelper_(sample, true);
}
#endif // USE_SIGNALS
« src/api.cc ('K') | « src/sampler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698