Index: src/v8threads.cc |
diff --git a/src/v8threads.cc b/src/v8threads.cc |
index 80a7cd94fb8ce3b3e6e004b12c9f49e5bd001fcc..15512c06fa55ddd3e84d2656d4f5dea268f3d51e 100644 |
--- a/src/v8threads.cc |
+++ b/src/v8threads.cc |
@@ -46,15 +46,28 @@ static internal::Thread::LocalStorageKey thread_id_key = |
// API code to verify that the lock is always held when V8 is being entered. |
bool Locker::active_ = false; |
- |
// Constructor for the Locker object. Once the Locker is constructed the |
// current thread will be guaranteed to have the big V8 lock. |
-Locker::Locker() : has_lock_(false), top_level_(true) { |
+Locker::Locker(LockParameters* lock_parameters) : has_lock_(false), top_level_(true) { |
// Record that the Locker has been used at least once. |
active_ = true; |
+ effective_ = false; |
// Get the big lock if necessary. |
if (!internal::ThreadManager::IsLockedByCurrentThread()) { |
+ |
+#ifdef ENABLE_DEBUGGER_SUPPORT |
+ if (lock_parameters == NULL) { |
+ internal::ThreadManager::Lock(); |
+ } else { |
+ bool res = internal::ThreadManager::LockOrAsk(&internal::Promises::promise_to_process_debug_commands); |
+ if (!res) { |
+ lock_parameters->successfully_relaied = true; |
+ return; |
+ } |
+ } |
+#else |
internal::ThreadManager::Lock(); |
+#endif |
has_lock_ = true; |
// Make sure that V8 is initialized. Archiving of threads interferes |
// with deserialization by adding additional root pointers, so we must |
@@ -76,6 +89,7 @@ Locker::Locker() : has_lock_(false), top_level_(true) { |
// Make sure this thread is assigned a thread id. |
internal::ThreadManager::AssignId(); |
+ effective_ = true; |
} |
@@ -85,6 +99,9 @@ bool Locker::IsLocked() { |
Locker::~Locker() { |
+ if (!effective_) { |
+ return; |
+ } |
ASSERT(internal::ThreadManager::IsLockedByCurrentThread()); |
if (has_lock_) { |
if (top_level_) { |
@@ -176,6 +193,81 @@ bool ThreadManager::RestoreThread() { |
return true; |
} |
+#ifdef ENABLE_DEBUGGER_SUPPORT |
+ |
+class PromisesHandler { |
+ public: |
+ static bool CanUnlock(Promises* promises) { |
+ return !promises->promise_to_process_debug_commands; |
+ } |
+ static void KeepPromises(const Promises* promises) { |
+ v8::Debug::ProcessDebuggerCommands(); |
+ } |
+}; |
+ |
+ |
+MutexWithResponsibilities::MutexWithResponsibilities() |
+: flag_mutex_(OS::CreateMutex()), |
+ sem_(OS::CreateSemaphore(1)), // Am I accurate with semaphore? |
+ locked_(false) |
+{ |
+} |
+ |
+MutexWithResponsibilities::~MutexWithResponsibilities() { |
+ delete sem_; |
+ delete flag_mutex_; |
+} |
+ |
+ |
+void MutexWithResponsibilities::Lock() { |
+ while (true) { |
+ { |
+ ScopedLock lock(flag_mutex_); |
+ if (!locked_) { |
+ locked_ = true; |
+ has_promises_ = true; |
+ return; |
+ } |
+ } |
+ sem_->Wait(); |
+ } |
+} |
+ |
+bool MutexWithResponsibilities::LockOrAsk(bool Promises::* promise) { |
+ ScopedLock lock(flag_mutex_); |
+ if (locked_) { |
+ ASSERT(has_promises_); |
+ promises_.*promise = true; |
+ return false; |
+ } else { |
+ locked_ = true; |
+ has_promises_ = false; |
+ return true; |
+ } |
+} |
+ |
+void MutexWithResponsibilities::Unlock() { |
+ while (true) { |
+ Promises promises_copy; |
+ { |
+ ScopedLock lock(flag_mutex_); |
+ ASSERT(locked_); |
+ bool has_to_do = has_promises_ && PromisesHandler::CanUnlock(&promises_); |
+ if (!has_to_do) { |
+ locked_ = false; |
+ break; |
+ } |
+ promises_copy = promises_; |
+ promises_.Reset(); |
+ } |
+ PromisesHandler::KeepPromises(&promises_copy); |
+ } |
+ sem_->Signal(); |
+} |
+ |
+#endif |
+ |
+ |
void ThreadManager::Lock() { |
mutex_->Lock(); |
@@ -189,6 +281,17 @@ void ThreadManager::Unlock() { |
mutex_->Unlock(); |
} |
+#ifdef ENABLE_DEBUGGER_SUPPORT |
+bool ThreadManager::LockOrAsk(bool Promises::* promise) { |
+ bool res = mutex_->LockOrAsk(promise); |
+ if (res) { |
+ mutex_owner_.Initialize(ThreadHandle::SELF); |
+ ASSERT(IsLockedByCurrentThread()); |
+ } |
+ return res; |
+} |
+#endif |
+ |
static int ArchiveSpacePerThread() { |
return HandleScopeImplementer::ArchiveSpacePerThread() + |
@@ -261,7 +364,11 @@ ThreadState* ThreadState::Next() { |
// be distinguished from not having a thread id at all (since NULL is |
// defined as 0.) |
int ThreadManager::last_id_ = 0; |
+#ifdef ENABLE_DEBUGGER_SUPPORT |
+MutexWithResponsibilities* ThreadManager::mutex_ = new MutexWithResponsibilities; |
+#else |
Mutex* ThreadManager::mutex_ = OS::CreateMutex(); |
+#endif |
ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID); |
ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID); |
ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL; |