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:
vitalyr@chromium.org 2011-07-05 15:49:39 +00:00
parent 798009cf1a
commit bbaed5b82e
13 changed files with 38 additions and 26 deletions

View File

@ -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);
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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;
}

View File

@ -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
}

View File

@ -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();

View File

@ -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();