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() {
|
void OS::Setup() {
|
||||||
// Seed the random number generator.
|
// Seed the random number generator.
|
||||||
// Convert the current time to a 64-bit integer first, before converting it
|
// 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.
|
// call this setup code within the same millisecond.
|
||||||
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
|
uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
|
||||||
srandom(static_cast<unsigned int>(seed));
|
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) {
|
static void UpdateAllocatedSpaceLimits(void* address, int size) {
|
||||||
|
ASSERT(limit_mutex != NULL);
|
||||||
|
ScopedLock lock(limit_mutex);
|
||||||
|
|
||||||
lowest_ever_allocated = Min(lowest_ever_allocated, address);
|
lowest_ever_allocated = Min(lowest_ever_allocated, address);
|
||||||
highest_ever_allocated =
|
highest_ever_allocated =
|
||||||
Max(highest_ever_allocated,
|
Max(highest_ever_allocated,
|
||||||
@ -407,7 +412,6 @@ static void* ThreadEntry(void* arg) {
|
|||||||
// one) so we initialize it here too.
|
// one) so we initialize it here too.
|
||||||
thread->data()->thread_ = pthread_self();
|
thread->data()->thread_ = pthread_self();
|
||||||
ASSERT(thread->data()->thread_ != kNoThread);
|
ASSERT(thread->data()->thread_ != kNoThread);
|
||||||
Thread::SetThreadLocal(Isolate::isolate_key(), thread->isolate());
|
|
||||||
thread->Run();
|
thread->Run();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -587,78 +591,162 @@ Semaphore* OS::CreateSemaphore(int count) {
|
|||||||
|
|
||||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||||
|
|
||||||
static Sampler* active_sampler_ = NULL;
|
|
||||||
static pthread_t vm_tid_ = 0;
|
|
||||||
|
|
||||||
|
|
||||||
static pthread_t GetThreadID() {
|
static pthread_t GetThreadID() {
|
||||||
return pthread_self();
|
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) {
|
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
|
||||||
USE(info);
|
USE(info);
|
||||||
if (signal != SIGPROF) return;
|
if (signal != SIGPROF) return;
|
||||||
if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
|
Isolate* isolate = Isolate::UncheckedCurrent();
|
||||||
if (vm_tid_ != GetThreadID()) return;
|
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_obj;
|
||||||
TickSample* sample = CpuProfiler::TickSampleEvent();
|
TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
|
||||||
if (sample == NULL) sample = &sample_obj;
|
if (sample == NULL) sample = &sample_obj;
|
||||||
|
|
||||||
// Extracting the sample from the context is extremely machine dependent.
|
// Extracting the sample from the context is extremely machine dependent.
|
||||||
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
ucontext_t* ucontext = reinterpret_cast<ucontext_t*>(context);
|
||||||
mcontext_t& mcontext = ucontext->uc_mcontext;
|
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->pc = reinterpret_cast<Address>(mcontext.gregs[REG_PC]);
|
||||||
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
|
sample->sp = reinterpret_cast<Address>(mcontext.gregs[REG_SP]);
|
||||||
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
|
sample->fp = reinterpret_cast<Address>(mcontext.gregs[REG_FP]);
|
||||||
|
|
||||||
active_sampler_->SampleStack(sample);
|
sampler->SampleStack(sample);
|
||||||
active_sampler_->Tick(sample);
|
sampler->Tick(sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SignalSender : public Thread {
|
||||||
class Sampler::PlatformData : public Malloced {
|
|
||||||
public:
|
public:
|
||||||
enum SleepInterval {
|
enum SleepInterval {
|
||||||
FULL_INTERVAL,
|
HALF_INTERVAL,
|
||||||
HALF_INTERVAL
|
FULL_INTERVAL
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit PlatformData(Sampler* sampler)
|
explicit SignalSender(int interval)
|
||||||
: sampler_(sampler),
|
: Thread("SignalSender"),
|
||||||
signal_handler_installed_(false),
|
interval_(interval) {}
|
||||||
vm_tgid_(getpid()),
|
|
||||||
signal_sender_launched_(false) {
|
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() {
|
static void RemoveActiveSampler(Sampler* sampler) {
|
||||||
while (sampler_->IsActive()) {
|
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 (rate_limiter_.SuspendIfNecessary()) continue;
|
||||||
if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
|
}
|
||||||
SendProfilingSignal();
|
if (cpu_profiling_enabled && runtime_profiler_enabled) {
|
||||||
|
if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile, this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Sleep(HALF_INTERVAL);
|
Sleep(HALF_INTERVAL);
|
||||||
RuntimeProfiler::NotifyTick();
|
if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Sleep(HALF_INTERVAL);
|
Sleep(HALF_INTERVAL);
|
||||||
} else {
|
} else {
|
||||||
if (sampler_->IsProfiling()) SendProfilingSignal();
|
if (cpu_profiling_enabled) {
|
||||||
if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
|
if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
|
||||||
|
this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (runtime_profiler_enabled) {
|
||||||
|
if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
|
||||||
|
NULL)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
Sleep(FULL_INTERVAL);
|
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;
|
if (!signal_handler_installed_) return;
|
||||||
pthread_kill(vm_tid_, SIGPROF);
|
pthread_kill(tid, SIGPROF);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Sleep(SleepInterval full_or_half) {
|
void Sleep(SleepInterval full_or_half) {
|
||||||
// Convert ms to us and subtract 100 us to compensate delays
|
// Convert ms to us and subtract 100 us to compensate delays
|
||||||
// occuring during signal delivery.
|
// 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;
|
if (full_or_half == HALF_INTERVAL) interval /= 2;
|
||||||
int result = usleep(interval);
|
int result = usleep(interval);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -673,22 +761,22 @@ class Sampler::PlatformData : public Malloced {
|
|||||||
USE(result);
|
USE(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sampler* sampler_;
|
const int interval_;
|
||||||
bool signal_handler_installed_;
|
|
||||||
struct sigaction old_signal_handler_;
|
|
||||||
int vm_tgid_;
|
|
||||||
bool signal_sender_launched_;
|
|
||||||
pthread_t signal_sender_thread_;
|
|
||||||
RuntimeProfilerRateLimiter rate_limiter_;
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Mutex* SignalSender::mutex_ = OS::CreateMutex();
|
||||||
static void* SenderEntry(void* arg) {
|
SignalSender* SignalSender::instance_ = NULL;
|
||||||
Sampler::PlatformData* data =
|
struct sigaction SignalSender::old_signal_handler_;
|
||||||
reinterpret_cast<Sampler::PlatformData*>(arg);
|
bool SignalSender::signal_handler_installed_ = false;
|
||||||
data->SignalSender();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Sampler::Sampler(Isolate* isolate, int interval)
|
Sampler::Sampler(Isolate* isolate, int interval)
|
||||||
@ -697,63 +785,27 @@ Sampler::Sampler(Isolate* isolate, int interval)
|
|||||||
profiling_(false),
|
profiling_(false),
|
||||||
active_(false),
|
active_(false),
|
||||||
samples_taken_(0) {
|
samples_taken_(0) {
|
||||||
data_ = new PlatformData(this);
|
data_ = new PlatformData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Sampler::~Sampler() {
|
Sampler::~Sampler() {
|
||||||
ASSERT(!data_->signal_sender_launched_);
|
ASSERT(!IsActive());
|
||||||
delete data_;
|
delete data_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Sampler::Start() {
|
void Sampler::Start() {
|
||||||
// There can only be one active sampler at the time on POSIX
|
|
||||||
// platforms.
|
|
||||||
ASSERT(!IsActive());
|
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);
|
SetActive(true);
|
||||||
if (pthread_create(
|
SignalSender::AddActiveSampler(this);
|
||||||
&data_->signal_sender_thread_, NULL, SenderEntry, data_) == 0) {
|
|
||||||
data_->signal_sender_launched_ = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set this sampler as the active sampler.
|
|
||||||
active_sampler_ = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Sampler::Stop() {
|
void Sampler::Stop() {
|
||||||
|
ASSERT(IsActive());
|
||||||
|
SignalSender::RemoveActiveSampler(this);
|
||||||
SetActive(false);
|
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
|
#endif // ENABLE_LOGGING_AND_PROFILING
|
||||||
|
Loading…
Reference in New Issue
Block a user