Fix a few issues breaking cctest/test-lockers/Regress1433:
o The thread local state in an isolate has to be initialized before it's used. o v8::Locker was incorrectly tracking whether it's the topmost one. o Waking the profiler thread on shutdown should not leave the semaphore counter in an inconsitent state. R=fschneider@chromium.org BUG=v8:1522 TEST=cctest/test-lockers/Regress1433 Review URL: http://codereview.chromium.org/7309013 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@8537 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
798009cf1a
commit
bbaed5b82e
@ -452,8 +452,9 @@ char* StackGuard::RestoreStackGuard(char* from) {
|
||||
|
||||
|
||||
void StackGuard::FreeThreadResources() {
|
||||
Isolate::CurrentPerIsolateThreadData()->set_stack_limit(
|
||||
thread_local_.real_climit_);
|
||||
Isolate::PerIsolateThreadData* per_thread =
|
||||
isolate_->FindOrAllocatePerThreadDataForThisThread();
|
||||
per_thread->set_stack_limit(thread_local_.real_climit_);
|
||||
}
|
||||
|
||||
|
||||
@ -502,7 +503,7 @@ void StackGuard::InitThread(const ExecutionAccess& lock) {
|
||||
uintptr_t stored_limit = per_thread->stack_limit();
|
||||
// You should hold the ExecutionAccess lock when you call this.
|
||||
if (stored_limit != 0) {
|
||||
StackGuard::SetStackLimit(stored_limit);
|
||||
SetStackLimit(stored_limit);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1731,11 +1731,11 @@ bool Isolate::Init(Deserializer* des) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InitializeThreadLocal();
|
||||
|
||||
bootstrapper_->Initialize(create_heap_objects);
|
||||
builtins_.Setup(create_heap_objects);
|
||||
|
||||
InitializeThreadLocal();
|
||||
|
||||
// Only preallocate on the first initialization.
|
||||
if (FLAG_preallocate_message_memory && preallocated_message_space_ == NULL) {
|
||||
// Start the thread which will set aside some memory.
|
||||
|
@ -961,6 +961,8 @@ class Isolate {
|
||||
|
||||
void SetCurrentVMState(StateTag state) {
|
||||
if (RuntimeProfiler::IsEnabled()) {
|
||||
// Make sure thread local top is initialized.
|
||||
ASSERT(thread_local_top_.isolate_ == this);
|
||||
StateTag current_state = thread_local_top_.current_vm_state_;
|
||||
if (current_state != JS && state == JS) {
|
||||
// Non-JS -> JS transition.
|
||||
|
@ -646,8 +646,7 @@ class SamplerThread : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
}
|
||||
|
@ -684,8 +684,7 @@ class SignalSender : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
|
||||
|
@ -1008,8 +1008,7 @@ class SignalSender : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
RestoreSignalHandler();
|
||||
|
@ -685,8 +685,7 @@ class SamplerThread : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
}
|
||||
|
@ -685,8 +685,7 @@ class SignalSender : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
|
||||
|
@ -683,8 +683,7 @@ class SignalSender : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
RestoreSignalHandler();
|
||||
|
@ -1888,8 +1888,7 @@ class SamplerThread : public Thread {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
instance_->Join();
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
}
|
||||
|
@ -323,9 +323,26 @@ bool RuntimeProfiler::WaitForSomeIsolateToEnterJS() {
|
||||
}
|
||||
|
||||
|
||||
void RuntimeProfiler::WakeUpRuntimeProfilerThreadBeforeShutdown() {
|
||||
void RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(Thread* thread) {
|
||||
#ifdef ENABLE_LOGGING_AND_PROFILING
|
||||
semaphore_->Signal();
|
||||
// Do a fake increment. If the profiler is waiting on the semaphore,
|
||||
// the returned state is 0, which can be left as an initial state in
|
||||
// case profiling is restarted later. If the profiler is not
|
||||
// waiting, the increment will prevent it from waiting, but has to
|
||||
// be undone after the profiler is stopped.
|
||||
Atomic32 new_state = NoBarrier_AtomicIncrement(&state_, 1);
|
||||
ASSERT(new_state >= 0);
|
||||
if (new_state == 0) {
|
||||
// The profiler thread is waiting. Wake it up. It must check for
|
||||
// stop conditions before attempting to wait again.
|
||||
semaphore_->Signal();
|
||||
}
|
||||
thread->Join();
|
||||
// The profiler thread is now stopped. Undo the increment in case it
|
||||
// was not waiting.
|
||||
if (new_state != 0) {
|
||||
NoBarrier_AtomicIncrement(&state_, -1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -84,10 +84,9 @@ class RuntimeProfiler {
|
||||
static bool IsSomeIsolateInJS();
|
||||
static bool WaitForSomeIsolateToEnterJS();
|
||||
|
||||
// When shutting down we join the profiler thread. Doing so while
|
||||
// it's waiting on a semaphore will cause a deadlock, so we have to
|
||||
// wake it up first.
|
||||
static void WakeUpRuntimeProfilerThreadBeforeShutdown();
|
||||
// Stops the runtime profiler thread when profiling support is being
|
||||
// turned off.
|
||||
static void StopRuntimeProfilerThreadBeforeShutdown(Thread* thread);
|
||||
|
||||
void UpdateSamplesAfterScavenge();
|
||||
void RemoveDeadSamples();
|
||||
|
@ -46,7 +46,7 @@ bool Locker::active_ = false;
|
||||
// current thread will be guaranteed to have the lock for a given isolate.
|
||||
Locker::Locker(v8::Isolate* isolate)
|
||||
: has_lock_(false),
|
||||
top_level_(false),
|
||||
top_level_(true),
|
||||
isolate_(reinterpret_cast<i::Isolate*>(isolate)) {
|
||||
if (isolate_ == NULL) {
|
||||
isolate_ = i::Isolate::GetDefaultIsolateForLocking();
|
||||
|
Loading…
Reference in New Issue
Block a user