summaryrefslogtreecommitdiff
path: root/deps/v8/src/platform-solaris.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/platform-solaris.cc')
-rw-r--r--deps/v8/src/platform-solaris.cc306
1 files changed, 133 insertions, 173 deletions
diff --git a/deps/v8/src/platform-solaris.cc b/deps/v8/src/platform-solaris.cc
index bbd982c31..0ee2e7cdb 100644
--- a/deps/v8/src/platform-solaris.cc
+++ b/deps/v8/src/platform-solaris.cc
@@ -88,7 +88,6 @@ 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
@@ -97,7 +96,6 @@ 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();
}
@@ -147,9 +145,6 @@ 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,
@@ -175,7 +170,7 @@ void* OS::Allocate(const size_t requested,
void* mbase = mmap(NULL, msize, prot, MAP_PRIVATE | MAP_ANON, -1, 0);
if (mbase == MAP_FAILED) {
- LOG(ISOLATE, StringEvent("OS::Allocate", "mmap failed"));
+ LOG(StringEvent("OS::Allocate", "mmap failed"));
return NULL;
}
*allocated = msize;
@@ -379,29 +374,59 @@ bool VirtualMemory::Uncommit(void* address, size_t size) {
}
-class Thread::PlatformData : public Malloced {
+class ThreadHandle::PlatformData : public Malloced {
public:
- PlatformData() : thread_(kNoThread) { }
+ explicit PlatformData(ThreadHandle::Kind kind) {
+ Initialize(kind);
+ }
+
+ void Initialize(ThreadHandle::Kind kind) {
+ switch (kind) {
+ case ThreadHandle::SELF: thread_ = pthread_self(); break;
+ case ThreadHandle::INVALID: thread_ = kNoThread; break;
+ }
+ }
pthread_t thread_; // Thread handle for pthread.
};
-Thread::Thread(const Options& options)
- : data_(new PlatformData()),
- stack_size_(options.stack_size) {
- set_name(options.name);
+
+ThreadHandle::ThreadHandle(Kind kind) {
+ data_ = new PlatformData(kind);
+}
+
+
+void ThreadHandle::Initialize(ThreadHandle::Kind kind) {
+ data_->Initialize(kind);
+}
+
+
+ThreadHandle::~ThreadHandle() {
+ delete data_;
+}
+
+
+bool ThreadHandle::IsSelf() const {
+ return pthread_equal(data_->thread_, pthread_self());
+}
+
+
+bool ThreadHandle::IsValid() const {
+ return data_->thread_ != kNoThread;
+}
+
+
+Thread::Thread() : ThreadHandle(ThreadHandle::INVALID) {
+ set_name("v8:<unknown>");
}
-Thread::Thread(const char* name)
- : data_(new PlatformData()),
- stack_size_(0) {
+Thread::Thread(const char* name) : ThreadHandle(ThreadHandle::INVALID) {
set_name(name);
}
Thread::~Thread() {
- delete data_;
}
@@ -410,8 +435,8 @@ static void* ThreadEntry(void* arg) {
// This is also initialized by the first argument to pthread_create() but we
// don't know which thread will run first (the original thread or the new
// one) so we initialize it here too.
- thread->data()->thread_ = pthread_self();
- ASSERT(thread->data()->thread_ != kNoThread);
+ thread->thread_handle_data()->thread_ = pthread_self();
+ ASSERT(thread->IsValid());
thread->Run();
return NULL;
}
@@ -424,20 +449,13 @@ void Thread::set_name(const char* name) {
void Thread::Start() {
- pthread_attr_t* attr_ptr = NULL;
- pthread_attr_t attr;
- if (stack_size_ > 0) {
- pthread_attr_init(&attr);
- pthread_attr_setstacksize(&attr, static_cast<size_t>(stack_size_));
- attr_ptr = &attr;
- }
- pthread_create(&data_->thread_, NULL, ThreadEntry, this);
- ASSERT(data_->thread_ != kNoThread);
+ pthread_create(&thread_handle_data()->thread_, NULL, ThreadEntry, this);
+ ASSERT(IsValid());
}
void Thread::Join() {
- pthread_join(data_->thread_, NULL);
+ pthread_join(thread_handle_data()->thread_, NULL);
}
@@ -591,172 +609,78 @@ 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();
}
+
static void ProfilerSignalHandler(int signal, siginfo_t* info, void* context) {
USE(info);
if (signal != SIGPROF) 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;
+ if (active_sampler_ == NULL || !active_sampler_->IsActive()) return;
+ if (vm_tid_ != GetThreadID()) return;
TickSample sample_obj;
- TickSample* sample = CpuProfiler::TickSampleEvent(isolate);
+ TickSample* sample = CpuProfiler::TickSampleEvent();
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 = isolate->current_vm_state();
+ sample->state = Top::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]);
- sampler->SampleStack(sample);
- sampler->Tick(sample);
+ active_sampler_->SampleStack(sample);
+ active_sampler_->Tick(sample);
}
-class Sampler::PlatformData : public Malloced {
- public:
- PlatformData() : vm_tid_(GetThreadID()) {}
-
- pthread_t vm_tid() const { return vm_tid_; }
-
- private:
- pthread_t vm_tid_;
-};
-
-class SignalSender : public Thread {
+class Sampler::PlatformData : public Malloced {
public:
enum SleepInterval {
- HALF_INTERVAL,
- FULL_INTERVAL
+ FULL_INTERVAL,
+ HALF_INTERVAL
};
- explicit SignalSender(int interval)
- : Thread("SignalSender"),
- interval_(interval) {}
-
- 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);
+ explicit PlatformData(Sampler* sampler)
+ : sampler_(sampler),
+ signal_handler_installed_(false),
+ vm_tgid_(getpid()),
+ signal_sender_launched_(false) {
}
- static void RestoreSignalHandler() {
- if (signal_handler_installed_) {
- sigaction(SIGPROF, &old_signal_handler_, 0);
- signal_handler_installed_ = false;
- }
- }
-
- static void AddActiveSampler(Sampler* sampler) {
- 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 SignalSender(sampler->interval());
- instance_->Start();
- } else {
- ASSERT(instance_->interval_ == sampler->interval());
- }
- }
-
- 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;
- RestoreSignalHandler();
- }
- }
-
- // 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();
- if (cpu_profiling_enabled && !signal_handler_installed_) {
- InstallSignalHandler();
- } else if (!cpu_profiling_enabled && signal_handler_installed_) {
- RestoreSignalHandler();
- }
-
- // 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;
- }
+ void SignalSender() {
+ while (sampler_->IsActive()) {
+ if (rate_limiter_.SuspendIfNecessary()) continue;
+ if (sampler_->IsProfiling() && RuntimeProfiler::IsEnabled()) {
+ SendProfilingSignal();
Sleep(HALF_INTERVAL);
- if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile, NULL)) {
- return;
- }
+ RuntimeProfiler::NotifyTick();
Sleep(HALF_INTERVAL);
} else {
- if (cpu_profiling_enabled) {
- if (!SamplerRegistry::IterateActiveSamplers(&DoCpuProfile,
- this)) {
- return;
- }
- }
- if (runtime_profiler_enabled) {
- if (!SamplerRegistry::IterateActiveSamplers(&DoRuntimeProfile,
- NULL)) {
- return;
- }
- }
+ if (sampler_->IsProfiling()) SendProfilingSignal();
+ if (RuntimeProfiler::IsEnabled()) RuntimeProfiler::NotifyTick();
Sleep(FULL_INTERVAL);
}
}
}
- 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) {
+ void SendProfilingSignal() {
if (!signal_handler_installed_) return;
- pthread_kill(tid, SIGPROF);
+ pthread_kill(vm_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 = interval_ * 1000 - 100;
+ useconds_t interval = sampler_->interval_ * 1000 - 100;
if (full_or_half == HALF_INTERVAL) interval /= 2;
int result = usleep(interval);
#ifdef DEBUG
@@ -771,53 +695,89 @@ class SignalSender : public Thread {
USE(result);
}
- const int interval_;
+ Sampler* sampler_;
+ bool signal_handler_installed_;
+ struct sigaction old_signal_handler_;
+ int vm_tgid_;
+ bool signal_sender_launched_;
+ pthread_t signal_sender_thread_;
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();
-SignalSender* SignalSender::instance_ = NULL;
-struct sigaction SignalSender::old_signal_handler_;
-bool SignalSender::signal_handler_installed_ = false;
+static void* SenderEntry(void* arg) {
+ Sampler::PlatformData* data =
+ reinterpret_cast<Sampler::PlatformData*>(arg);
+ data->SignalSender();
+ return 0;
+}
-Sampler::Sampler(Isolate* isolate, int interval)
- : isolate_(isolate),
- interval_(interval),
+
+Sampler::Sampler(int interval)
+ : interval_(interval),
profiling_(false),
active_(false),
samples_taken_(0) {
- data_ = new PlatformData;
+ data_ = new PlatformData(this);
}
Sampler::~Sampler() {
- ASSERT(!IsActive());
+ ASSERT(!data_->signal_sender_launched_);
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);
- SignalSender::AddActiveSampler(this);
+ 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;
}
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
} } // namespace v8::internal