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