⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 v8threads.cc.svn-base

📁 Google浏览器V8内核代码
💻 SVN-BASE
字号:
// Copyright 2008 the V8 project authors. All rights reserved.// Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:////     * Redistributions of source code must retain the above copyright//       notice, this list of conditions and the following disclaimer.//     * Redistributions in binary form must reproduce the above//       copyright notice, this list of conditions and the following//       disclaimer in the documentation and/or other materials provided//       with the distribution.//     * Neither the name of Google Inc. nor the names of its//       contributors may be used to endorse or promote products derived//       from this software without specific prior written permission.//// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#include "v8.h"#include "api.h"#include "debug.h"#include "execution.h"#include "v8threads.h"namespace v8 {static internal::Thread::LocalStorageKey thread_state_key =    internal::Thread::CreateThreadLocalKey();// 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) {  // Get the big lock if necessary.  if (!internal::ThreadManager::IsLockedByCurrentThread()) {    internal::ThreadManager::Lock();    has_lock_ = true;    // This may be a locker within an unlocker in which case we have to    // get the saved state for this thread and restore it.    if (internal::ThreadManager::RestoreThread()) {      top_level_ = false;    }  }  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());}bool Locker::IsLocked() {  return internal::ThreadManager::IsLockedByCurrentThread();}Locker::~Locker() {  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());  if (has_lock_) {    if (!top_level_) {      internal::ThreadManager::ArchiveThread();    }    internal::ThreadManager::Unlock();  }}Unlocker::Unlocker() {  ASSERT(internal::ThreadManager::IsLockedByCurrentThread());  internal::ThreadManager::ArchiveThread();  internal::ThreadManager::Unlock();}Unlocker::~Unlocker() {  ASSERT(!internal::ThreadManager::IsLockedByCurrentThread());  internal::ThreadManager::Lock();  internal::ThreadManager::RestoreThread();}void Locker::StartPreemption(int every_n_ms) {  v8::internal::ContextSwitcher::StartPreemption(every_n_ms);}void Locker::StopPreemption() {  v8::internal::ContextSwitcher::StopPreemption();}namespace internal {bool ThreadManager::RestoreThread() {  // First check whether the current thread has been 'lazily archived', ie  // not archived at all.  If that is the case we put the state storage we  // had prepared back in the free list, since we didn't need it after all.  if (lazily_archived_thread_.IsSelf()) {    lazily_archived_thread_.Initialize(ThreadHandle::INVALID);    ASSERT(Thread::GetThreadLocal(thread_state_key) ==           lazily_archived_thread_state_);    lazily_archived_thread_state_->LinkInto(ThreadState::FREE_LIST);    lazily_archived_thread_state_ = NULL;    Thread::SetThreadLocal(thread_state_key, NULL);    return true;  }  // If there is another thread that was lazily archived then we have to really  // archive it now.  if (lazily_archived_thread_.IsValid()) {    EagerlyArchiveThread();  }  ThreadState* state =      reinterpret_cast<ThreadState*>(Thread::GetThreadLocal(thread_state_key));  if (state == NULL) {    return false;  }  char* from = state->data();  from = HandleScopeImplementer::RestoreThread(from);  from = Top::RestoreThread(from);  from = Debug::RestoreDebug(from);  from = StackGuard::RestoreStackGuard(from);  Thread::SetThreadLocal(thread_state_key, NULL);  state->Unlink();  state->LinkInto(ThreadState::FREE_LIST);  return true;}void ThreadManager::Lock() {  mutex_->Lock();  mutex_owner_.Initialize(ThreadHandle::SELF);  ASSERT(IsLockedByCurrentThread());}void ThreadManager::Unlock() {  mutex_owner_.Initialize(ThreadHandle::INVALID);  mutex_->Unlock();}static int ArchiveSpacePerThread() {  return HandleScopeImplementer::ArchiveSpacePerThread() +                            Top::ArchiveSpacePerThread() +                          Debug::ArchiveSpacePerThread() +                     StackGuard::ArchiveSpacePerThread();}ThreadState* ThreadState::free_anchor_ = new ThreadState();ThreadState* ThreadState::in_use_anchor_ = new ThreadState();ThreadState::ThreadState() : next_(this), previous_(this) {}void ThreadState::AllocateSpace() {  data_ = NewArray<char>(ArchiveSpacePerThread());}void ThreadState::Unlink() {  next_->previous_ = previous_;  previous_->next_ = next_;}void ThreadState::LinkInto(List list) {  ThreadState* flying_anchor =      list == FREE_LIST ? free_anchor_ : in_use_anchor_;  next_ = flying_anchor->next_;  previous_ = flying_anchor;  flying_anchor->next_ = this;  next_->previous_ = this;}ThreadState* ThreadState::GetFree() {  ThreadState* gotten = free_anchor_->next_;  if (gotten == free_anchor_) {    ThreadState* new_thread_state = new ThreadState();    new_thread_state->AllocateSpace();    return new_thread_state;  }  return gotten;}// Gets the first in the list of archived threads.ThreadState* ThreadState::FirstInUse() {  return in_use_anchor_->Next();}ThreadState* ThreadState::Next() {  if (next_ == in_use_anchor_) return NULL;  return next_;}Mutex* ThreadManager::mutex_ = OS::CreateMutex();ThreadHandle ThreadManager::mutex_owner_(ThreadHandle::INVALID);ThreadHandle ThreadManager::lazily_archived_thread_(ThreadHandle::INVALID);ThreadState* ThreadManager::lazily_archived_thread_state_ = NULL;void ThreadManager::ArchiveThread() {  ASSERT(!lazily_archived_thread_.IsValid());  ASSERT(Thread::GetThreadLocal(thread_state_key) == NULL);  ThreadState* state = ThreadState::GetFree();  state->Unlink();  Thread::SetThreadLocal(thread_state_key, reinterpret_cast<void*>(state));  lazily_archived_thread_.Initialize(ThreadHandle::SELF);  lazily_archived_thread_state_ = state;}void ThreadManager::EagerlyArchiveThread() {  ThreadState* state = lazily_archived_thread_state_;  state->LinkInto(ThreadState::IN_USE_LIST);  char* to = state->data();  to = HandleScopeImplementer::ArchiveThread(to);  to = Top::ArchiveThread(to);  to = Debug::ArchiveDebug(to);  to = StackGuard::ArchiveStackGuard(to);  lazily_archived_thread_.Initialize(ThreadHandle::INVALID);  lazily_archived_thread_state_ = NULL;}void ThreadManager::Iterate(ObjectVisitor* v) {  // Expecting no threads during serialization/deserialization  for (ThreadState* state = ThreadState::FirstInUse();       state != NULL;       state = state->Next()) {    char* data = state->data();    data = HandleScopeImplementer::Iterate(v, data);    data = Top::Iterate(v, data);  }}void ThreadManager::MarkCompactPrologue() {  for (ThreadState* state = ThreadState::FirstInUse();       state != NULL;       state = state->Next()) {    char* data = state->data();    data += HandleScopeImplementer::ArchiveSpacePerThread();    Top::MarkCompactPrologue(data);  }}void ThreadManager::MarkCompactEpilogue() {  for (ThreadState* state = ThreadState::FirstInUse();       state != NULL;       state = state->Next()) {    char* data = state->data();    data += HandleScopeImplementer::ArchiveSpacePerThread();    Top::MarkCompactEpilogue(data);  }}ContextSwitcher::ContextSwitcher(int every_n_ms)  : preemption_semaphore_(OS::CreateSemaphore(0)),    keep_going_(true),    sleep_ms_(every_n_ms) {}static v8::internal::ContextSwitcher* switcher;void ContextSwitcher::StartPreemption(int every_n_ms) {  ASSERT(Locker::IsLocked());  if (switcher == NULL) {    switcher = new ContextSwitcher(every_n_ms);    switcher->Start();  } else {    switcher->sleep_ms_ = every_n_ms;  }}void ContextSwitcher::StopPreemption() {  ASSERT(Locker::IsLocked());  if (switcher != NULL) {    switcher->Stop();    delete(switcher);    switcher = NULL;  }}void ContextSwitcher::Run() {  while (keep_going_) {    OS::Sleep(sleep_ms_);    StackGuard::Preempt();    WaitForPreemption();  }}void ContextSwitcher::Stop() {  ASSERT(Locker::IsLocked());  keep_going_ = false;  preemption_semaphore_->Signal();  Join();}void ContextSwitcher::WaitForPreemption() {  preemption_semaphore_->Wait();}void ContextSwitcher::PreemptionReceived() {  ASSERT(Locker::IsLocked());  switcher->preemption_semaphore_->Signal();}}  // namespace internal}  // namespace v8

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -