Fix platform-solaris after isolate changes.
Patch from http://code.google.com/p/v8/issues/detail?id=1509. R=ager@chromium.org BUG= TEST= Review URL: http://codereview.chromium.org/7273092 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8476 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
2b286a3128
commit
3a5788915f
@ -88,6 +88,7 @@ double ceiling(double x) {
|
||||
}
|
||||
|
||||
|
||||
static Mutex* limit_mutex = NULL;
|
||||
void OS::Setup() {
|
||||
// Seed the random number generator.
|
||||
// Convert the current time to a 64-bit integer first, before converting it
|
||||
@ -96,6 +97,7 @@ void OS::Setup() {
|
||||
// call this setup code within the same millisecond.
|
||||
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
|
||||
srandom(static_cast<unsigned int>(seed));
|
||||
limit_mutex = CreateMutex();
|
||||
}
|
||||
|
||||
|
||||
@ -145,6 +147,9 @@ static void* highest_ever_allocated = reinterpret_cast<void*>(0);
|
||||
|
||||
|
||||
static void UpdateAllocatedSpaceLimits(void* address, int size) {
|
||||
ASSERT(limit_mutex != NULL);
|
||||
ScopedLock lock(limit_mutex);
|
||||
|
||||
lowest_ever_allocated = Min(lowest_ever_allocated, address);
|
||||
highest_ever_allocated =
|
||||
Max(highest_ever_allocated,
|
||||
@ -407,7 +412,6 @@ static void* ThreadEntry(void* arg) {
|
||||
// one) so we initialize it here too.
|
||||
thread->data()->thread_ = pthread_self();
|
||||
ASSERT(thread->data()->thread_ != kNoThread);
|
||||
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
|
||||
thread->Run();
|
||||
return NULL;
|
||||
}
|
||||
@ -587,78 +591,162 @@ Semaphore* OS::CreateSemaphore(int count) {
|
||||
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
|
||||
static Sampler* active_sampler_ = NULL;
|
||||
static pthread_t vm_tid_ = 0;
|
||||
|
||||
|
||||
static pthread_t GetThreadID() {
|
||||
return pthread_self();
|
||||
}
|
||||
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
public:
|
||||
PlatformData() : vm_tid_(GetThreadID()) {}
|
||||
|
||||
pthread_t vm_tid() const { return vm_tid_; }
|
||||
|
||||
private:
|
||||
pthread_t vm_tid_;
|
||||
};
|
||||
|
||||
|
||||
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||
USE(info);
|
||||
if (signal != SIGPROF) return;
|
||||
if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
|
||||
if (vm_tid_ != GetThreadID()) return;
|
||||
Isolate* isolate = Isolate::UncheckedCurrent();
|
||||
if (isolate == NULL || !isolate->IsInitialized() || !isolate->IsInUse()) {
|
||||
// We require a fully initialized and entered isolate.
|
||||
return;
|
||||
}
|
||||
if (v8::Locker::IsActive() &&
|
||||
!isolate->thread_manager()->IsLockedByCurrentThread()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Sampler* sampler = isolate->logger()->sampler();
|
||||
if (sampler == NULL || !sampler->IsActive()) return;
|
||||
|
||||
TickSample sample_obj;
|
||||
TickSample* sample = CpuProfiler::TickSampleEvent();
|
||||
TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
|
||||
if (sample == NULL) sample = &sample_obj;
|
||||
|
||||
// Extracting the sample from the context is extremely machine dependent.
|
||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
||||
sample->state = Top::current_vm_state();
|
||||
sample->state = isolate->current_vm_state();
|
||||
|
||||
sample->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
|
||||
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
|
||||
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
|
||||
|
||||
active_sampler_->SampleStack(sample);
|
||||
active_sampler_->Tick(sample);
|
||||
sampler->SampleStack(sample);
|
||||
sampler->Tick(sample);
|
||||
}
|
||||
|
||||
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
class SignalSender : public Thread {
|
||||
public:
|
||||
enum SleepInterval {
|
||||
FULL_INTERVAL,
|
||||
HALF_INTERVAL
|
||||
HALF_INTERVAL,
|
||||
FULL_INTERVAL
|
||||
};
|
||||
|
||||
explicit PlatformData(Sampler* sampler)
|
||||
: sampler_(sampler),
|
||||
signal_handler_installed_(false),
|
||||
vm_tgid_(getpid()),
|
||||
signal_sender_launched_(false) {
|
||||
explicit SignalSender(int interval)
|
||||
: Thread("SignalSender"),
|
||||
interval_(interval) {}
|
||||
|
||||
static void AddActiveSampler(Sampler* sampler) {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::AddActiveSampler(sampler);
|
||||
if (instance_ == NULL) {
|
||||
// Install a signal handler.
|
||||
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);
|
||||
|
||||
// Start a thread that sends SIGPROF signal to VM threads.
|
||||
instance_ = new SignalSender(sampler->interval());
|
||||
instance_->Start();
|
||||
} else {
|
||||
ASSERT(instance_->interval_ == sampler->interval());
|
||||
}
|
||||
}
|
||||
|
||||
void SignalSender() {
|
||||
while (sampler_->IsActive()) {
|
||||
if (rate_limiter_.SuspendIfNecessary()) continue;
|
||||
if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
|
||||
SendProfilingSignal();
|
||||
static void RemoveActiveSampler(Sampler* sampler) {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
|
||||
// Restore the old signal handler.
|
||||
if (signal_handler_installed_) {
|
||||
sigaction(SIGPROF, &old_signal_handler_, 0);
|
||||
signal_handler_installed_ = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Implement Thread::Run().
|
||||
virtual void Run() {
|
||||
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();
|
||||
// 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);
|
||||
RuntimeProfiler::NotifyTick();
|
||||
if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
|
||||
return;
|
||||
}
|
||||
Sleep(HALF_INTERVAL);
|
||||
} else {
|
||||
if (sampler_->IsProfiling()) SendProfilingSignal();
|
||||
if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
|
||||
if (cpu_profiling_enabled) {
|
||||
if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
|
||||
this)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (runtime_profiler_enabled) {
|
||||
if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
|
||||
NULL)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Sleep(FULL_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SendProfilingSignal() {
|
||||
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(pthread_t tid) {
|
||||
if (!signal_handler_installed_) return;
|
||||
pthread_kill(vm_tid_, SIGPROF);
|
||||
pthread_kill(tid, SIGPROF);
|
||||
}
|
||||
|
||||
void Sleep(SleepInterval full_or_half) {
|
||||
// Convert ms to us and subtract 100 us to compensate delays
|
||||
// occuring during signal delivery.
|
||||
useconds_t interval = sampler_->interval_ * 1000 - 100;
|
||||
useconds_t interval = interval_ * 1000 - 100;
|
||||
if (full_or_half == HALF_INTERVAL) interval /= 2;
|
||||
int result = usleep(interval);
|
||||
#ifdef DEBUG
|
||||
@ -673,22 +761,22 @@ class Sampler::PlatformData : public Malloced {
|
||||
USE(result);
|
||||
}
|
||||
|
||||
Sampler* sampler_;
|
||||
bool signal_handler_installed_;
|
||||
struct sigaction old_signal_handler_;
|
||||
int vm_tgid_;
|
||||
bool signal_sender_launched_;
|
||||
pthread_t signal_sender_thread_;
|
||||
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_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SignalSender);
|
||||
};
|
||||
|
||||
|
||||
static void* SenderEntry(void* arg) {
|
||||
Sampler::PlatformData* data =
|
||||
reinterpret_cast<Sampler::PlatformData*>(arg);
|
||||
data->SignalSender();
|
||||
return 0;
|
||||
}
|
||||
Mutex* SignalSender::mutex_ = OS::CreateMutex();
|
||||
SignalSender* SignalSender::instance_ = NULL;
|
||||
struct sigaction SignalSender::old_signal_handler_;
|
||||
bool SignalSender::signal_handler_installed_ = false;
|
||||
|
||||
|
||||
Sampler::Sampler(Isolate* isolate, int interval)
|
||||
@ -697,63 +785,27 @@ Sampler::Sampler(Isolate* isolate, int interval)
|
||||
profiling_(false),
|
||||
active_(false),
|
||||
samples_taken_(0) {
|
||||
data_ = new PlatformData(this);
|
||||
data_ = new PlatformData;
|
||||
}
|
||||
|
||||
|
||||
Sampler::~Sampler() {
|
||||
ASSERT(!data_->signal_sender_launched_);
|
||||
ASSERT(!IsActive());
|
||||
delete data_;
|
||||
}
|
||||
|
||||
|
||||
void Sampler::Start() {
|
||||
// There can only be one active sampler at the time on POSIX
|
||||
// platforms.
|
||||
ASSERT(!IsActive());
|
||||
vm_tid_ = GetThreadID();
|
||||
|
||||
// Request profiling signals.
|
||||
struct sigaction sa;
|
||||
sa.sa_sigaction = ProfilerSignalHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
sa.sa_flags = SA_RESTART | SA_SIGINFO;
|
||||
data_->signal_handler_installed_ =
|
||||
sigaction(SIGPROF, &sa, &data_->old_signal_handler_) == 0;
|
||||
|
||||
// Start a thread that sends SIGPROF signal to VM thread.
|
||||
// Sending the signal ourselves instead of relying on itimer provides
|
||||
// much better accuracy.
|
||||
SetActive(true);
|
||||
if (pthread_create(
|
||||
&data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
|
||||
data_->signal_sender_launched_ = true;
|
||||
}
|
||||
|
||||
// Set this sampler as the active sampler.
|
||||
active_sampler_ = this;
|
||||
SignalSender::AddActiveSampler(this);
|
||||
}
|
||||
|
||||
|
||||
void Sampler::Stop() {
|
||||
ASSERT(IsActive());
|
||||
SignalSender::RemoveActiveSampler(this);
|
||||
SetActive(false);
|
||||
|
||||
// Wait for signal sender termination (it will exit after setting
|
||||
// active_ to false).
|
||||
if (data_->signal_sender_launched_) {
|
||||
Top::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
pthread_join(data_->signal_sender_thread_, NULL);
|
||||
data_->signal_sender_launched_ = false;
|
||||
}
|
||||
|
||||
// Restore old signal handler
|
||||
if (data_->signal_handler_installed_) {
|
||||
sigaction(SIGPROF, &data_->old_signal_handler_, 0);
|
||||
data_->signal_handler_installed_ = false;
|
||||
}
|
||||
|
||||
// This sampler is no longer the active sampler.
|
||||
active_sampler_ = NULL;
|
||||
}
|
||||
|
||||
#endif // ENABLE_LOGGING_AND_PROFILING
|
||||
|
Loading…
Reference in New Issue
Block a user