Simplify implementation of Mutex.
authorbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 30 Jul 2013 17:12:49 +0000 (17:12 +0000)
committerbmeurer@chromium.org <bmeurer@chromium.org@ce2b1a6d-e550-0410-aec6-3dcde31c8c00>
Tue, 30 Jul 2013 17:12:49 +0000 (17:12 +0000)
Also moves Mutex to its own file mutex.{cc,h}.

R=svenpanne@chromium.org

Review URL: https://codereview.chromium.org/21087012

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15964 ce2b1a6d-e550-0410-aec6-3dcde31c8c00

40 files changed:
src/assembler.cc
src/d8-debug.cc
src/d8-debug.h
src/d8.cc
src/d8.h
src/debug-agent.cc
src/debug-agent.h
src/debug.cc
src/debug.h
src/heap.cc
src/isolate.cc
src/isolate.h
src/log-utils.cc
src/mutex.cc [new file with mode: 0644]
src/mutex.h [new file with mode: 0644]
src/optimizing-compiler-thread.cc
src/optimizing-compiler-thread.h
src/platform-cygwin.cc
src/platform-freebsd.cc
src/platform-linux.cc
src/platform-macos.cc
src/platform-nullos.cc
src/platform-openbsd.cc
src/platform-posix.cc
src/platform-solaris.cc
src/platform-win32.cc
src/platform.h
src/sampler.cc
src/spaces.cc
src/spaces.h
src/v8threads.cc
src/v8threads.h
src/win32-headers.h
test/cctest/cctest.gyp
test/cctest/test-debug.cc
test/cctest/test-mutex.cc [new file with mode: 0644]
test/cctest/test-platform-linux.cc
test/cctest/test-platform-nullos.cc
test/cctest/test-semaphore.cc [moved from test/cctest/test-lock.cc with 74% similarity]
tools/gyp/v8.gyp

index ae8a0b5..ab957be 100644 (file)
@@ -891,7 +891,7 @@ void ExternalReference::SetUp() {
   double_constants.the_hole_nan = BitCast<double>(kHoleNanInt64);
   double_constants.negative_infinity = -V8_INFINITY;
 
-  math_exp_data_mutex = OS::CreateMutex();
+  math_exp_data_mutex = new Mutex;
 }
 
 
@@ -899,7 +899,7 @@ void ExternalReference::InitializeMathExpData() {
   // Early return?
   if (math_exp_data_initialized) return;
 
-  math_exp_data_mutex->Lock();
+  ScopedLock with(math_exp_data_mutex);
   if (!math_exp_data_initialized) {
     // If this is changed, generated code must be adapted too.
     const int kTableSizeBits = 11;
@@ -935,7 +935,6 @@ void ExternalReference::InitializeMathExpData() {
 
     math_exp_data_initialized = true;
   }
-  math_exp_data_mutex->Unlock();
 }
 
 
index 9a72518..5499d20 100644 (file)
@@ -248,7 +248,7 @@ void RemoteDebugger::ConnectionClosed() {
 
 
 void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
-  i::ScopedLock lock(event_access_);
+  i::ScopedLock lock(&event_access_);
   if (head_ == NULL) {
     ASSERT(tail_ == NULL);
     head_ = event;
@@ -263,7 +263,7 @@ void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
 
 
 RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
-  i::ScopedLock lock(event_access_);
+  i::ScopedLock lock(&event_access_);
   ASSERT(head_ != NULL);
   RemoteDebuggerEvent* result = head_;
   head_ = head_->next();
index 2386b6b..276cbd8 100644 (file)
@@ -53,7 +53,6 @@ class RemoteDebugger {
   explicit RemoteDebugger(Isolate* isolate, int port)
       : isolate_(isolate),
         port_(port),
-        event_access_(i::OS::CreateMutex()),
         event_available_(i::OS::CreateSemaphore(0)),
         head_(NULL), tail_(NULL) {}
   void Run();
@@ -84,7 +83,7 @@ class RemoteDebugger {
   // Linked list of events from debugged V8 and from keyboard input. Access to
   // the list is guarded by a mutex and a semaphore signals new items in the
   // list.
-  i::Mutex* event_access_;
+  i::Mutex event_access_;
   i::Semaphore* event_available_;
   RemoteDebuggerEvent* head_;
   RemoteDebuggerEvent* tail_;
index 1efe2ae..4cdafee 100644 (file)
--- a/src/d8.cc
+++ b/src/d8.cc
@@ -157,7 +157,7 @@ CounterMap* Shell::counter_map_;
 i::OS::MemoryMappedFile* Shell::counters_file_ = NULL;
 CounterCollection Shell::local_counters_;
 CounterCollection* Shell::counters_ = &local_counters_;
-i::Mutex* Shell::context_mutex_(i::OS::CreateMutex());
+i::Mutex Shell::context_mutex_;
 Persistent<Context> Shell::utility_context_;
 #endif  // V8_SHARED
 
@@ -925,7 +925,7 @@ void Shell::InitializeDebugger(Isolate* isolate) {
 Local<Context> Shell::CreateEvaluationContext(Isolate* isolate) {
 #ifndef V8_SHARED
   // This needs to be a critical section since this is not thread-safe
-  i::ScopedLock lock(context_mutex_);
+  i::ScopedLock lock(&context_mutex_);
 #endif  // V8_SHARED
   // Initialize the global objects
   Handle<ObjectTemplate> global_template = CreateGlobalTemplate(isolate);
@@ -1011,7 +1011,6 @@ void Shell::OnExit() {
            "-------------+\n");
     delete [] counters;
   }
-  delete context_mutex_;
   delete counters_file_;
   delete counter_map_;
 #endif  // V8_SHARED
index 4f04342..7e5e3d5 100644 (file)
--- a/src/d8.h
+++ b/src/d8.h
@@ -388,7 +388,7 @@ class Shell : public i::AllStatic {
   static CounterCollection local_counters_;
   static CounterCollection* counters_;
   static i::OS::MemoryMappedFile* counters_file_;
-  static i::Mutex* context_mutex_;
+  static i::Mutex context_mutex_;
 
   static Counter* GetCounter(const char* name, bool is_histogram);
   static void InstallUtilityScript(Isolate* isolate);
index 811c00e..fc16bf9 100644 (file)
@@ -106,7 +106,7 @@ static const char* kCreateSessionMessage =
     "Remote debugging session already active\r\n";
 
 void DebuggerAgent::CreateSession(Socket* client) {
-  ScopedLock with(session_access_);
+  ScopedLock with(&session_access_);
 
   // If another session is already established terminate this one.
   if (session_ != NULL) {
@@ -123,7 +123,7 @@ void DebuggerAgent::CreateSession(Socket* client) {
 
 
 void DebuggerAgent::CloseSession() {
-  ScopedLock with(session_access_);
+  ScopedLock with(&session_access_);
 
   // Terminate the session.
   if (session_ != NULL) {
@@ -136,7 +136,7 @@ void DebuggerAgent::CloseSession() {
 
 
 void DebuggerAgent::DebuggerMessage(const v8::Debug::Message& message) {
-  ScopedLock with(session_access_);
+  ScopedLock with(&session_access_);
 
   // Forward the message handling to the session.
   if (session_ != NULL) {
@@ -154,7 +154,7 @@ void DebuggerAgent::OnSessionClosed(DebuggerAgentSession* session) {
   }
 
   // Terminate the session.
-  ScopedLock with(session_access_);
+  ScopedLock with(&session_access_);
   ASSERT(session == session_);
   if (session == session_) {
     session_->Shutdown();
index 6115190..577239c 100644 (file)
@@ -48,7 +48,7 @@ class DebuggerAgent: public Thread {
         isolate_(Isolate::Current()),
         name_(StrDup(name)), port_(port),
         server_(OS::CreateSocket()), terminate_(false),
-        session_access_(OS::CreateMutex()), session_(NULL),
+        session_(NULL),
         terminate_now_(OS::CreateSemaphore(0)),
         listening_(OS::CreateSemaphore(0)) {
     ASSERT(isolate_->debugger_agent_instance() == NULL);
@@ -76,7 +76,7 @@ class DebuggerAgent: public Thread {
   int port_;  // Port to use for the agent.
   Socket* server_;  // Server socket for listen/accept.
   bool terminate_;  // Termination flag.
-  Mutex* session_access_;  // Mutex guarging access to session_.
+  Mutex session_access_;  // Mutex guarging access to session_.
   DebuggerAgentSession* session_;  // Current active session if any.
   Semaphore* terminate_now_;  // Semaphore to signal termination.
   Semaphore* listening_;
index a0b9884..80885da 100644 (file)
@@ -2606,7 +2606,6 @@ Debugger::Debugger(Isolate* isolate)
       message_handler_(NULL),
       debugger_unload_pending_(false),
       host_dispatch_handler_(NULL),
-      dispatch_handler_access_(OS::CreateMutex()),
       debug_message_dispatch_handler_(NULL),
       message_dispatch_helper_thread_(NULL),
       host_dispatch_micros_(100 * 1000),
@@ -2619,8 +2618,6 @@ Debugger::Debugger(Isolate* isolate)
 
 
 Debugger::~Debugger() {
-  delete dispatch_handler_access_;
-  dispatch_handler_access_ = 0;
   delete command_received_;
   command_received_ = 0;
 }
@@ -3303,7 +3300,7 @@ void Debugger::SetHostDispatchHandler(v8::Debug::HostDispatchHandler handler,
 
 void Debugger::SetDebugMessageDispatchHandler(
     v8::Debug::DebugMessageDispatchHandler handler, bool provide_locker) {
-  ScopedLock with(dispatch_handler_access_);
+  ScopedLock with(&dispatch_handler_access_);
   debug_message_dispatch_handler_ = handler;
 
   if (provide_locker && message_dispatch_helper_thread_ == NULL) {
@@ -3346,7 +3343,7 @@ void Debugger::ProcessCommand(Vector<const uint16_t> command,
 
   MessageDispatchHelperThread* dispatch_thread;
   {
-    ScopedLock with(dispatch_handler_access_);
+    ScopedLock with(&dispatch_handler_access_);
     dispatch_thread = message_dispatch_helper_thread_;
   }
 
@@ -3466,7 +3463,7 @@ void Debugger::WaitForAgent() {
 void Debugger::CallMessageDispatchHandler() {
   v8::Debug::DebugMessageDispatchHandler handler;
   {
-    ScopedLock with(dispatch_handler_access_);
+    ScopedLock with(&dispatch_handler_access_);
     handler = Debugger::debug_message_dispatch_handler_;
   }
   if (handler != NULL) {
@@ -3787,24 +3784,20 @@ void CommandMessageQueue::Expand() {
 
 
 LockingCommandMessageQueue::LockingCommandMessageQueue(Logger* logger, int size)
-    : logger_(logger), queue_(size) {
-  lock_ = OS::CreateMutex();
-}
+    : logger_(logger), queue_(size) {}
 
 
-LockingCommandMessageQueue::~LockingCommandMessageQueue() {
-  delete lock_;
-}
+LockingCommandMessageQueue::~LockingCommandMessageQueue() {}
 
 
-bool LockingCommandMessageQueue::IsEmpty() const {
-  ScopedLock sl(lock_);
+bool LockingCommandMessageQueue::IsEmpty() {
+  ScopedLock sl(&lock_);
   return queue_.IsEmpty();
 }
 
 
 CommandMessage LockingCommandMessageQueue::Get() {
-  ScopedLock sl(lock_);
+  ScopedLock sl(&lock_);
   CommandMessage result = queue_.Get();
   logger_->DebugEvent("Get", result.text());
   return result;
@@ -3812,14 +3805,14 @@ CommandMessage LockingCommandMessageQueue::Get() {
 
 
 void LockingCommandMessageQueue::Put(const CommandMessage& message) {
-  ScopedLock sl(lock_);
+  ScopedLock sl(&lock_);
   queue_.Put(message);
   logger_->DebugEvent("Put", message.text());
 }
 
 
 void LockingCommandMessageQueue::Clear() {
-  ScopedLock sl(lock_);
+  ScopedLock sl(&lock_);
   queue_.Clear();
 }
 
@@ -3827,19 +3820,17 @@ void LockingCommandMessageQueue::Clear() {
 MessageDispatchHelperThread::MessageDispatchHelperThread(Isolate* isolate)
     : Thread("v8:MsgDispHelpr"),
       isolate_(isolate), sem_(OS::CreateSemaphore(0)),
-      mutex_(OS::CreateMutex()), already_signalled_(false) {
-}
+      already_signalled_(false) {}
 
 
 MessageDispatchHelperThread::~MessageDispatchHelperThread() {
-  delete mutex_;
   delete sem_;
 }
 
 
 void MessageDispatchHelperThread::Schedule() {
   {
-    ScopedLock lock(mutex_);
+    ScopedLock lock(&mutex_);
     if (already_signalled_) {
       return;
     }
@@ -3853,7 +3844,7 @@ void MessageDispatchHelperThread::Run() {
   while (true) {
     sem_->Wait();
     {
-      ScopedLock lock(mutex_);
+      ScopedLock lock(&mutex_);
       already_signalled_ = false;
     }
     {
index 67debc7..e7b919e 100644 (file)
@@ -763,14 +763,15 @@ class LockingCommandMessageQueue BASE_EMBEDDED {
  public:
   LockingCommandMessageQueue(Logger* logger, int size);
   ~LockingCommandMessageQueue();
-  bool IsEmpty() const;
+  bool IsEmpty();
   CommandMessage Get();
   void Put(const CommandMessage& message);
   void Clear();
+
  private:
   Logger* logger_;
   CommandMessageQueue queue_;
-  Mutex* lock_;
+  Mutex lock_;
   DISALLOW_COPY_AND_ASSIGN(LockingCommandMessageQueue);
 };
 
@@ -929,7 +930,7 @@ class Debugger {
   v8::Debug::MessageHandler2 message_handler_;
   bool debugger_unload_pending_;  // Was message handler cleared?
   v8::Debug::HostDispatchHandler host_dispatch_handler_;
-  Mutex* dispatch_handler_access_;  // Mutex guarding dispatch handler.
+  Mutex dispatch_handler_access_;  // Mutex guarding dispatch handler.
   v8::Debug::DebugMessageDispatchHandler debug_message_dispatch_handler_;
   MessageDispatchHelperThread* message_dispatch_helper_thread_;
   int host_dispatch_micros_;
@@ -1056,7 +1057,7 @@ class MessageDispatchHelperThread: public Thread {
 
   Isolate* isolate_;
   Semaphore* const sem_;
-  Mutex* const mutex_;
+  Mutex mutex_;
   bool already_signalled_;
 
   DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
index 692ec21..6a18fbb 100644 (file)
@@ -6877,7 +6877,7 @@ bool Heap::SetUp() {
 
   store_buffer()->SetUp();
 
-  if (FLAG_parallel_recompilation) relocation_mutex_ = OS::CreateMutex();
+  if (FLAG_parallel_recompilation) relocation_mutex_ = new Mutex;
 #ifdef DEBUG
   relocation_mutex_locked_by_optimizer_thread_ = false;
 #endif  // DEBUG
index 61f1e2d..f1af6d3 100644 (file)
@@ -343,7 +343,7 @@ Thread::LocalStorageKey Isolate::per_isolate_thread_data_key_;
 #ifdef DEBUG
 Thread::LocalStorageKey PerThreadAssertScopeBase::thread_local_key;
 #endif  // DEBUG
-Mutex* Isolate::process_wide_mutex_ = OS::CreateMutex();
+Mutex Isolate::process_wide_mutex_;
 Isolate::ThreadDataTable* Isolate::thread_data_table_ = NULL;
 Atomic32 Isolate::isolate_counter_ = 0;
 
@@ -352,7 +352,7 @@ Isolate::PerIsolateThreadData* Isolate::AllocatePerIsolateThreadData(
   ASSERT(!thread_id.Equals(ThreadId::Invalid()));
   PerIsolateThreadData* per_thread = new PerIsolateThreadData(this, thread_id);
   {
-    ScopedLock lock(process_wide_mutex_);
+    ScopedLock lock(&process_wide_mutex_);
     ASSERT(thread_data_table_->Lookup(this, thread_id) == NULL);
     thread_data_table_->Insert(per_thread);
     ASSERT(thread_data_table_->Lookup(this, thread_id) == per_thread);
@@ -366,11 +366,11 @@ Isolate::PerIsolateThreadData*
   ThreadId thread_id = ThreadId::Current();
   PerIsolateThreadData* per_thread = NULL;
   {
-    ScopedLock lock(process_wide_mutex_);
+    ScopedLock lock(&process_wide_mutex_);
     per_thread = thread_data_table_->Lookup(this, thread_id);
-    if (per_thread == NULL) {
-      per_thread = AllocatePerIsolateThreadData(thread_id);
-    }
+  }
+  if (per_thread == NULL) {
+    per_thread = AllocatePerIsolateThreadData(thread_id);
   }
   return per_thread;
 }
@@ -386,7 +386,7 @@ Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
     ThreadId thread_id) {
   PerIsolateThreadData* per_thread = NULL;
   {
-    ScopedLock lock(process_wide_mutex_);
+    ScopedLock lock(&process_wide_mutex_);
     per_thread = thread_data_table_->Lookup(this, thread_id);
   }
   return per_thread;
@@ -394,7 +394,7 @@ Isolate::PerIsolateThreadData* Isolate::FindPerThreadDataForThread(
 
 
 void Isolate::EnsureDefaultIsolate() {
-  ScopedLock lock(process_wide_mutex_);
+  ScopedLock lock(&process_wide_mutex_);
   if (default_isolate_ == NULL) {
     isolate_key_ = Thread::CreateThreadLocalKey();
     thread_id_key_ = Thread::CreateThreadLocalKey();
@@ -1749,10 +1749,8 @@ Isolate::Isolate()
       counters_(NULL),
       code_range_(NULL),
       // Must be initialized early to allow v8::SetResourceConstraints calls.
-      break_access_(OS::CreateMutex()),
       debugger_initialized_(false),
       // Must be initialized early to allow v8::Debug calls.
-      debugger_access_(OS::CreateMutex()),
       logger_(NULL),
       stats_table_(NULL),
       stub_cache_(NULL),
@@ -1853,7 +1851,7 @@ void Isolate::TearDown() {
 
   Deinit();
 
-  { ScopedLock lock(process_wide_mutex_);
+  { ScopedLock lock(&process_wide_mutex_);
     thread_data_table_->RemoveAllThreads(this);
   }
 
@@ -2024,10 +2022,6 @@ Isolate::~Isolate() {
 
   delete handle_scope_implementer_;
   handle_scope_implementer_ = NULL;
-  delete break_access_;
-  break_access_ = NULL;
-  delete debugger_access_;
-  debugger_access_ = NULL;
 
   delete compilation_cache_;
   compilation_cache_ = NULL;
@@ -2127,7 +2121,7 @@ void Isolate::InitializeLoggingAndCounters() {
 
 void Isolate::InitializeDebugger() {
 #ifdef ENABLE_DEBUGGER_SUPPORT
-  ScopedLock lock(debugger_access_);
+  ScopedLock lock(&debugger_access_);
   if (NoBarrier_Load(&debugger_initialized_)) return;
   InitializeLoggingAndCounters();
   debug_ = new Debug(this);
index c008317..009ff78 100644 (file)
@@ -544,10 +544,10 @@ class Isolate {
   static void EnterDefaultIsolate();
 
   // Mutex for serializing access to break control structures.
-  Mutex* break_access() { return break_access_; }
+  Mutex* break_access() { return &break_access_; }
 
   // Mutex for serializing access to debugger.
-  Mutex* debugger_access() { return debugger_access_; }
+  Mutex* debugger_access() { return &debugger_access_; }
 
   Address get_address_from_id(AddressId id);
 
@@ -1200,7 +1200,7 @@ class Isolate {
 
   // This mutex protects highest_thread_id_, thread_data_table_ and
   // default_isolate_.
-  static Mutex* process_wide_mutex_;
+  static Mutex process_wide_mutex_;
 
   static Thread::LocalStorageKey per_isolate_thread_data_key_;
   static Thread::LocalStorageKey isolate_key_;
@@ -1268,9 +1268,9 @@ class Isolate {
   CompilationCache* compilation_cache_;
   Counters* counters_;
   CodeRange* code_range_;
-  Mutex* break_access_;
+  Mutex break_access_;
   Atomic32 debugger_initialized_;
-  Mutex* debugger_access_;
+  Mutex debugger_access_;
   Logger* logger_;
   StackGuard stack_guard_;
   StatsTable* stats_table_;
@@ -1462,11 +1462,11 @@ class ExecutionAccess BASE_EMBEDDED {
   }
   ~ExecutionAccess() { Unlock(isolate_); }
 
-  static void Lock(Isolate* isolate) { isolate->break_access_->Lock(); }
-  static void Unlock(Isolate* isolate) { isolate->break_access_->Unlock(); }
+  static void Lock(Isolate* isolate) { isolate->break_access()->Lock(); }
+  static void Unlock(Isolate* isolate) { isolate->break_access()->Unlock(); }
 
   static bool TryLock(Isolate* isolate) {
-    return isolate->break_access_->TryLock();
+    return isolate->break_access()->TryLock();
   }
 
  private:
index 6bba882..0a94ca9 100644 (file)
@@ -48,7 +48,7 @@ Log::Log(Logger* logger)
 
 
 void Log::Initialize(const char* log_file_name) {
-  mutex_ = OS::CreateMutex();
+  mutex_ = new Mutex;
   message_buffer_ = NewArray<char>(kMessageBufferSize);
 
   // --log-all enables all the log flags.
diff --git a/src/mutex.cc b/src/mutex.cc
new file mode 100644 (file)
index 0000000..e02ace5
--- /dev/null
@@ -0,0 +1,110 @@
+// Copyright 2013 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 "mutex.h"
+
+#include <errno.h>
+
+#include "checks.h"
+
+namespace v8 {
+namespace internal {
+
+#if V8_OS_UNIX
+
+Mutex::Mutex() {
+  pthread_mutexattr_t attr;
+  int result = pthread_mutexattr_init(&attr);
+  ASSERT_EQ(0, result);
+  result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+  ASSERT_EQ(0, result);
+  result = pthread_mutex_init(&mutex_, &attr);
+  ASSERT_EQ(0, result);
+  result = pthread_mutexattr_destroy(&attr);
+  ASSERT_EQ(0, result);
+  USE(result);
+}
+
+
+Mutex::~Mutex() {
+  pthread_mutex_destroy(&mutex_);
+}
+
+
+void Mutex::Lock() {
+  int result = pthread_mutex_lock(&mutex_);
+  ASSERT_EQ(0, result);
+  USE(result);
+}
+
+
+void Mutex::Unlock() {
+  int result = pthread_mutex_unlock(&mutex_);
+  ASSERT_EQ(0, result);
+  USE(result);
+}
+
+
+bool Mutex::TryLock() {
+  int result = pthread_mutex_trylock(&mutex_);
+  // Return false if the lock is busy and locking failed.
+  if (result == EBUSY) {
+    return false;
+  }
+  ASSERT_EQ(0, result);
+  return true;
+}
+
+#elif V8_OS_WIN32
+
+Mutex::Mutex() {
+  InitializeCriticalSection(&cs_);
+}
+
+
+Mutex::~Mutex() {
+  DeleteCriticalSection(&cs_);
+}
+
+
+void Mutex::Lock() {
+  EnterCriticalSection(&cs_);
+}
+
+
+void Mutex::Unlock() {
+  LeaveCriticalSection(&cs_);
+}
+
+
+bool Mutex::TryLock() {
+  return TryEnterCriticalSection(&cs_);
+}
+
+#endif  // V8_OS_WIN32
+
+} }  // namespace v8::internal
diff --git a/src/mutex.h b/src/mutex.h
new file mode 100644 (file)
index 0000000..94a202e
--- /dev/null
@@ -0,0 +1,130 @@
+// Copyright 2013 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.
+
+#ifndef V8_MUTEX_H_
+#define V8_MUTEX_H_
+
+#include "globals.h"
+
+#if V8_OS_UNIX
+#include <pthread.h>  // NOLINT
+#elif V8_OS_WIN32
+#include "win32-headers.h"
+#endif
+
+#include "checks.h"
+#include "lazy-instance.h"
+
+namespace v8 {
+namespace internal {
+
+// ----------------------------------------------------------------------------
+// Mutex
+//
+// Mutexes are used for serializing access to non-reentrant sections of code.
+// The implementations of mutex should allow for nested/recursive locking.
+//
+class Mutex {
+ public:
+  Mutex();
+  ~Mutex();
+
+  // Locks the given mutex. If the mutex is currently unlocked, it becomes
+  // locked and owned by the calling thread. If the mutex is already locked
+  // by another thread, suspends the calling thread until the mutex is
+  // unlocked.
+  void Lock();
+
+  // Unlocks the given mutex. The mutex is assumed to be locked and owned
+  // by the calling thread on entrance.
+  void Unlock();
+
+  // Tries to lock the given mutex. Returns true if the mutex was locked
+  // successfully.
+  bool TryLock();
+
+ private:
+#if V8_OS_UNIX
+  pthread_mutex_t mutex_;
+#elif V8_OS_WIN32
+  CRITICAL_SECTION cs_;
+#endif
+
+  DISALLOW_COPY_AND_ASSIGN(Mutex);
+};
+
+
+// ----------------------------------------------------------------------------
+// LazyMutex
+//
+// POD Mutex initialized lazily (i.e. the first time Pointer() is called).
+// Usage:
+//   static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
+//
+//   void my_function() {
+//     ScopedLock my_lock(&my_mutex);
+//     // Do something.
+//   }
+//
+typedef LazyDynamicInstance<Mutex,
+                            DefaultCreateTrait<Mutex>,
+                            ThreadSafeInitOnceTrait>::type LazyMutex;
+
+#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
+
+
+// ----------------------------------------------------------------------------
+// ScopedLock
+//
+// Stack-allocated ScopedLocks provide block-scoped locking and
+// unlocking of a mutex.
+//
+class ScopedLock {
+ public:
+  explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
+    ASSERT(mutex_ != NULL);
+    mutex_->Lock();
+  }
+
+  explicit ScopedLock(LazyMutex* lazy_mutex) : mutex_(lazy_mutex->Pointer()) {
+    ASSERT(mutex_ != NULL);
+    mutex_->Lock();
+  }
+
+  ~ScopedLock() {
+    mutex_->Unlock();
+  }
+
+ private:
+  Mutex* mutex_;
+
+  DISALLOW_COPY_AND_ASSIGN(ScopedLock);
+};
+
+} }  // namespace v8::internal
+
+#endif  // V8_MUTEX_H_
index 21ef237..39fc191 100644 (file)
@@ -39,7 +39,7 @@ namespace internal {
 
 void OptimizingCompilerThread::Run() {
 #ifdef DEBUG
-  { ScopedLock lock(thread_id_mutex_);
+  { ScopedLock lock(&thread_id_mutex_);
     thread_id_ = ThreadId::Current().ToInteger();
   }
 #endif
@@ -93,7 +93,7 @@ void OptimizingCompilerThread::CompileNext() {
   // The function may have already been optimized by OSR.  Simply continue.
   // Use a mutex to make sure that functions marked for install
   // are always also queued.
-  ScopedLock mark_and_queue(install_mutex_);
+  ScopedLock mark_and_queue(&install_mutex_);
   { Heap::RelocationLock relocation_lock(isolate_->heap());
     AllowHandleDereference ahd;
     optimizing_compiler->info()->closure()->MarkForInstallingRecompiledCode();
@@ -141,7 +141,7 @@ void OptimizingCompilerThread::InstallOptimizedFunctions() {
   OptimizingCompiler* compiler;
   while (true) {
     { // Memory barrier to ensure marked functions are queued.
-      ScopedLock marked_and_queued(install_mutex_);
+      ScopedLock marked_and_queued(&install_mutex_);
       if (!output_queue_.Dequeue(&compiler)) return;
     }
     Compiler::InstallOptimizedCode(compiler);
@@ -163,7 +163,7 @@ void OptimizingCompilerThread::QueueForOptimization(
 #ifdef DEBUG
 bool OptimizingCompilerThread::IsOptimizerThread() {
   if (!FLAG_parallel_recompilation) return false;
-  ScopedLock lock(thread_id_mutex_);
+  ScopedLock lock(&thread_id_mutex_);
   return ThreadId::Current().ToInteger() == thread_id_;
 }
 #endif
index 275ceb4..336522f 100644 (file)
@@ -46,12 +46,10 @@ class OptimizingCompilerThread : public Thread {
       Thread("OptimizingCompilerThread"),
 #ifdef DEBUG
       thread_id_(0),
-      thread_id_mutex_(OS::CreateMutex()),
 #endif
       isolate_(isolate),
       stop_semaphore_(OS::CreateSemaphore(0)),
       input_queue_semaphore_(OS::CreateSemaphore(0)),
-      install_mutex_(OS::CreateMutex()),
       time_spent_compiling_(0),
       time_spent_total_(0) {
     NoBarrier_Store(&stop_thread_, static_cast<AtomicWord>(false));
@@ -83,18 +81,14 @@ class OptimizingCompilerThread : public Thread {
 #endif
 
   ~OptimizingCompilerThread() {
-    delete install_mutex_;
     delete input_queue_semaphore_;
     delete stop_semaphore_;
-#ifdef DEBUG
-    delete thread_id_mutex_;
-#endif
   }
 
  private:
 #ifdef DEBUG
   int thread_id_;
-  Mutex* thread_id_mutex_;
+  Mutex thread_id_mutex_;
 #endif
 
   Isolate* isolate_;
@@ -102,7 +96,7 @@ class OptimizingCompilerThread : public Thread {
   Semaphore* input_queue_semaphore_;
   UnboundQueue<OptimizingCompiler*> input_queue_;
   UnboundQueue<OptimizingCompiler*> output_queue_;
-  Mutex* install_mutex_;
+  Mutex install_mutex_;
   volatile AtomicWord stop_thread_;
   volatile Atomic32 queue_length_;
   int64_t time_spent_compiling_;
index 4c7b017..f6412ae 100644 (file)
@@ -471,7 +471,7 @@ void OS::SetUp() {
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srandom(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index e0917fa..5da6eca 100644 (file)
@@ -436,7 +436,7 @@ void OS::SetUp() {
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srandom(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index 5c252bb..800c20a 100644 (file)
@@ -757,7 +757,7 @@ void OS::SetUp() {
   // Seed the random number generator. We preserve microsecond resolution.
   uint64_t seed = Ticks() ^ (getpid() << 16);
   srandom(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index 6135cd1..b2d92d5 100644 (file)
@@ -443,7 +443,7 @@ void OS::SetUp() {
   // Seed the random number generator. We preserve microsecond resolution.
   uint64_t seed = Ticks() ^ (getpid() << 16);
   srandom(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index dd5a3dd..eadb300 100644 (file)
@@ -477,37 +477,6 @@ void Thread::YieldCPU() {
 }
 
 
-class NullMutex : public Mutex {
- public:
-  NullMutex() : data_(NULL) {
-    UNIMPLEMENTED();
-  }
-
-  virtual ~NullMutex() {
-    UNIMPLEMENTED();
-  }
-
-  virtual int Lock() {
-    UNIMPLEMENTED();
-    return 0;
-  }
-
-  virtual int Unlock() {
-    UNIMPLEMENTED();
-    return 0;
-  }
-
- private:
-  void* data_;
-};
-
-
-Mutex* OS::CreateMutex() {
-  UNIMPLEMENTED();
-  return new NullMutex();
-}
-
-
 class NullSemaphore : public Semaphore {
  public:
   explicit NullSemaphore(int count) : data_(NULL) {
index e591601..4771671 100644 (file)
@@ -502,7 +502,7 @@ void OS::SetUp() {
   // Seed the random number generator. We preserve microsecond resolution.
   uint64_t seed = Ticks() ^ (getpid() << 16);
   srandom(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index 13b819b..31fc7a6 100644 (file)
@@ -756,48 +756,6 @@ void Thread::SetThreadLocal(LocalStorageKey key, void* value) {
 }
 
 
-class POSIXMutex : public Mutex {
- public:
-  POSIXMutex() {
-    pthread_mutexattr_t attr;
-    memset(&attr, 0, sizeof(attr));
-    int result = pthread_mutexattr_init(&attr);
-    ASSERT(result == 0);
-    result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
-    ASSERT(result == 0);
-    result = pthread_mutex_init(&mutex_, &attr);
-    ASSERT(result == 0);
-    result = pthread_mutexattr_destroy(&attr);
-    ASSERT(result == 0);
-    USE(result);
-  }
-
-  virtual ~POSIXMutex() { pthread_mutex_destroy(&mutex_); }
-
-  virtual int Lock() { return pthread_mutex_lock(&mutex_); }
-
-  virtual int Unlock() { return pthread_mutex_unlock(&mutex_); }
-
-  virtual bool TryLock() {
-    int result = pthread_mutex_trylock(&mutex_);
-    // Return false if the lock is busy and locking failed.
-    if (result == EBUSY) {
-      return false;
-    }
-    ASSERT(result == 0);  // Verify no other errors.
-    return true;
-  }
-
- private:
-  pthread_mutex_t mutex_;   // Pthread mutex for POSIX platforms.
-};
-
-
-Mutex* OS::CreateMutex() {
-  return new POSIXMutex();
-}
-
-
 // ----------------------------------------------------------------------------
 // POSIX socket support.
 //
index b1d88af..654d98b 100644 (file)
@@ -479,7 +479,7 @@ void OS::SetUp() {
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srandom(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index 292c24a..c0f049c 100644 (file)
@@ -1705,46 +1705,6 @@ void Thread::YieldCPU() {
 
 
 // ----------------------------------------------------------------------------
-// Win32 mutex support.
-//
-// On Win32 mutexes are implemented using CRITICAL_SECTION objects. These are
-// faster than Win32 Mutex objects because they are implemented using user mode
-// atomic instructions. Therefore we only do ring transitions if there is lock
-// contention.
-
-class Win32Mutex : public Mutex {
- public:
-  Win32Mutex() { InitializeCriticalSection(&cs_); }
-
-  virtual ~Win32Mutex() { DeleteCriticalSection(&cs_); }
-
-  virtual int Lock() {
-    EnterCriticalSection(&cs_);
-    return 0;
-  }
-
-  virtual int Unlock() {
-    LeaveCriticalSection(&cs_);
-    return 0;
-  }
-
-
-  virtual bool TryLock() {
-    // Returns non-zero if critical section is entered successfully entered.
-    return TryEnterCriticalSection(&cs_);
-  }
-
- private:
-  CRITICAL_SECTION cs_;  // Critical section used for mutex
-};
-
-
-Mutex* OS::CreateMutex() {
-  return new Win32Mutex();
-}
-
-
-// ----------------------------------------------------------------------------
 // Win32 semaphore support.
 //
 // On Win32 semaphores are implemented using Win32 Semaphore objects. The
@@ -1987,7 +1947,7 @@ void OS::SetUp() {
   // call this setup code within the same millisecond.
   uint64_t seed = static_cast<uint64_t>(TimeCurrentMillis());
   srand(static_cast<unsigned int>(seed));
-  limit_mutex = CreateMutex();
+  limit_mutex = new Mutex;
 }
 
 
index 8b27c19..51d5698 100644 (file)
@@ -100,7 +100,7 @@ int random();
 
 #endif  // WIN32
 
-#include "lazy-instance.h"
+#include "mutex.h"
 #include "utils.h"
 #include "v8globals.h"
 
@@ -309,10 +309,6 @@ class OS {
 
   static int StackWalk(Vector<StackFrame> frames);
 
-  // Factory method for creating platform dependent Mutex.
-  // Please use delete to reclaim the storage for the returned Mutex.
-  static Mutex* CreateMutex();
-
   // Factory method for creating platform dependent Semaphore.
   // Please use delete to reclaim the storage for the returned Semaphore.
   static Semaphore* CreateSemaphore(int count);
@@ -716,72 +712,6 @@ class Thread {
 
 
 // ----------------------------------------------------------------------------
-// Mutex
-//
-// Mutexes are used for serializing access to non-reentrant sections of code.
-// The implementations of mutex should allow for nested/recursive locking.
-
-class Mutex {
- public:
-  virtual ~Mutex() {}
-
-  // Locks the given mutex. If the mutex is currently unlocked, it becomes
-  // locked and owned by the calling thread, and immediately. If the mutex
-  // is already locked by another thread, suspends the calling thread until
-  // the mutex is unlocked.
-  virtual int Lock() = 0;
-
-  // Unlocks the given mutex. The mutex is assumed to be locked and owned by
-  // the calling thread on entrance.
-  virtual int Unlock() = 0;
-
-  // Tries to lock the given mutex. Returns whether the mutex was
-  // successfully locked.
-  virtual bool TryLock() = 0;
-};
-
-struct CreateMutexTrait {
-  static Mutex* Create() {
-    return OS::CreateMutex();
-  }
-};
-
-// POD Mutex initialized lazily (i.e. the first time Pointer() is called).
-// Usage:
-//   static LazyMutex my_mutex = LAZY_MUTEX_INITIALIZER;
-//
-//   void my_function() {
-//     ScopedLock my_lock(my_mutex.Pointer());
-//     // Do something.
-//   }
-//
-typedef LazyDynamicInstance<
-    Mutex, CreateMutexTrait, ThreadSafeInitOnceTrait>::type LazyMutex;
-
-#define LAZY_MUTEX_INITIALIZER LAZY_DYNAMIC_INSTANCE_INITIALIZER
-
-// ----------------------------------------------------------------------------
-// ScopedLock
-//
-// Stack-allocated ScopedLocks provide block-scoped locking and
-// unlocking of a mutex.
-class ScopedLock {
- public:
-  explicit ScopedLock(Mutex* mutex): mutex_(mutex) {
-    ASSERT(mutex_ != NULL);
-    mutex_->Lock();
-  }
-  ~ScopedLock() {
-    mutex_->Unlock();
-  }
-
- private:
-  Mutex* mutex_;
-  DISALLOW_COPY_AND_ASSIGN(ScopedLock);
-};
-
-
-// ----------------------------------------------------------------------------
 // Socket
 //
 
index d72ed1a..db7a54e 100644 (file)
@@ -415,7 +415,7 @@ class SamplerThread : public Thread {
       : Thread(Thread::Options("SamplerThread", kSamplerThreadStackSize)),
         interval_(interval) {}
 
-  static void SetUp() { if (!mutex_) mutex_ = OS::CreateMutex(); }
+  static void SetUp() { if (!mutex_) mutex_ = new Mutex; }
   static void TearDown() { delete mutex_; }
 
   static void AddActiveSampler(Sampler* sampler) {
index 5935c4a..539b77e 100644 (file)
@@ -2043,7 +2043,7 @@ intptr_t FreeListCategory::Concatenate(FreeListCategory* category) {
     // This is safe (not going to deadlock) since Concatenate operations
     // are never performed on the same free lists at the same time in
     // reverse order.
-    ScopedLock lock_target(mutex_);
+    ScopedLock lock_target(mutex());
     ScopedLock lock_source(category->mutex());
     free_bytes = category->available();
     if (end_ == NULL) {
index b47452e..165a226 100644 (file)
@@ -1444,12 +1444,9 @@ class FreeListCategory {
   FreeListCategory() :
       top_(NULL),
       end_(NULL),
-      mutex_(OS::CreateMutex()),
       available_(0) {}
 
-  ~FreeListCategory() {
-    delete mutex_;
-  }
+  ~FreeListCategory() {}
 
   intptr_t Concatenate(FreeListCategory* category);
 
@@ -1476,7 +1473,7 @@ class FreeListCategory {
   int available() const { return available_; }
   void set_available(int available) { available_ = available; }
 
-  Mutex* mutex() { return mutex_; }
+  Mutex* mutex() { return &mutex_; }
 
 #ifdef DEBUG
   intptr_t SumFreeList();
@@ -1486,7 +1483,7 @@ class FreeListCategory {
  private:
   FreeListNode* top_;
   FreeListNode* end_;
-  Mutex* mutex_;
+  Mutex mutex_;
 
   // Total available bytes in all blocks of this free list category.
   int available_;
index 2df187a..c1f20b1 100644 (file)
@@ -214,7 +214,7 @@ bool ThreadManager::RestoreThread() {
 
 
 void ThreadManager::Lock() {
-  mutex_->Lock();
+  mutex_.Lock();
   mutex_owner_ = ThreadId::Current();
   ASSERT(IsLockedByCurrentThread());
 }
@@ -222,7 +222,7 @@ void ThreadManager::Lock() {
 
 void ThreadManager::Unlock() {
   mutex_owner_ = ThreadId::Invalid();
-  mutex_->Unlock();
+  mutex_.Unlock();
 }
 
 
@@ -303,8 +303,7 @@ ThreadState* ThreadState::Next() {
 // be distinguished from not having a thread id at all (since NULL is
 // defined as 0.)
 ThreadManager::ThreadManager()
-    : mutex_(OS::CreateMutex()),
-      mutex_owner_(ThreadId::Invalid()),
+    : mutex_owner_(ThreadId::Invalid()),
       lazily_archived_thread_(ThreadId::Invalid()),
       lazily_archived_thread_state_(NULL),
       free_anchor_(NULL),
@@ -315,7 +314,6 @@ ThreadManager::ThreadManager()
 
 
 ThreadManager::~ThreadManager() {
-  delete mutex_;
   DeleteThreadStateList(free_anchor_);
   DeleteThreadStateList(in_use_anchor_);
 }
index 8dce860..b8ed817 100644 (file)
@@ -119,7 +119,7 @@ class ThreadManager {
 
   void EagerlyArchiveThread();
 
-  Mutex* mutex_;
+  Mutex mutex_;
   ThreadId mutex_owner_;
   ThreadId lazily_archived_thread_;
   ThreadState* lazily_archived_thread_state_;
index 2b5d7d7..bf568b3 100644 (file)
@@ -94,5 +94,4 @@
 #undef ANY
 #undef IGNORE
 #undef GetObject
-#undef CreateMutex
 #undef CreateSemaphore
index 9df5c7b..1cdf9f4 100644 (file)
         'test-heap-profiler.cc',
         'test-list.cc',
         'test-liveedit.cc',
-        'test-lock.cc',
         'test-lockers.cc',
         'test-log.cc',
         'test-mark-compact.cc',
+        'test-mutex.cc',
         'test-object-observe.cc',
         'test-parsing.cc',
         'test-platform.cc',
@@ -91,6 +91,7 @@
         'test-random.cc',
         'test-regexp.cc',
         'test-reloc-info.cc',
+        'test-semaphore.cc',
         'test-serialize.cc',
         'test-sockets.cc',
         'test-spaces.cc',
index 484eb8e..90453f7 100644 (file)
@@ -4714,7 +4714,7 @@ class ThreadBarrier {
 
 ThreadBarrier::ThreadBarrier(int num_threads)
     : num_threads_(num_threads), num_blocked_(0) {
-  lock_ = OS::CreateMutex();
+  lock_ = new v8::internal::Mutex;
   sem_ = OS::CreateSemaphore(0);
   invalid_ = false;  // A barrier may only be used once.  Then it is invalid.
 }
diff --git a/test/cctest/test-mutex.cc b/test/cctest/test-mutex.cc
new file mode 100644 (file)
index 0000000..935bacc
--- /dev/null
@@ -0,0 +1,70 @@
+// Copyright 2006-2013 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.
+//
+// Tests of the Mutex class from mutex.h
+
+#include "v8.h"
+
+#include "mutex.h"
+#include "cctest.h"
+
+
+using namespace ::v8::internal;
+
+
+TEST(Simple) {
+  Mutex mutex;
+  mutex.Lock();
+  mutex.Unlock();
+}
+
+
+TEST(Recursive) {
+  Mutex mutex;
+  mutex.Lock();
+  mutex.Lock();
+  mutex.Unlock();
+  mutex.Unlock();
+}
+
+
+TEST(SimpleScopedLock) {
+  Mutex mutex;
+  {
+    ScopedLock fst(&mutex);
+  }
+  {
+    ScopedLock snd(&mutex);
+  }
+}
+
+
+TEST(RecursiveScopedLock) {
+  Mutex mutex;
+  ScopedLock fst(&mutex);
+  ScopedLock snd(&mutex);
+}
index 6bb2902..5945241 100644 (file)
@@ -52,18 +52,18 @@ static void LoopIncrement(Mutex* mutex, int rem) {
     int count = 0;
     int last_count = -1;
     do {
-      CHECK_EQ(0, mutex->Lock());
+      mutex->Lock();
       count = busy_lock_counter;
-      CHECK_EQ(0, mutex->Unlock());
+      mutex->Unlock();
       yield();
     } while (count % 2 == rem && count < kLockCounterLimit);
     if (count >= kLockCounterLimit) break;
-    CHECK_EQ(0, mutex->Lock());
+    mutex->Lock();
     CHECK_EQ(count, busy_lock_counter);
     CHECK(last_count == -1 || count == last_count + 1);
     busy_lock_counter++;
     last_count = count;
-    CHECK_EQ(0, mutex->Unlock());
+    mutex->Unlock();
     yield();
   }
 }
@@ -79,15 +79,14 @@ static void* RunTestBusyLock(void* arg) {
 // increment a variable.
 TEST(BusyLock) {
   pthread_t other;
-  Mutex* mutex = OS::CreateMutex();
+  Mutex mutex;
   int thread_created = pthread_create(&other,
                                       NULL,
                                       &RunTestBusyLock,
-                                      mutex);
+                                      &mutex);
   CHECK_EQ(0, thread_created);
-  LoopIncrement(mutex, 1);
+  LoopIncrement(&mutex, 1);
   pthread_join(other, NULL);
-  delete mutex;
 }
 
 
index 3afbd90..0ad67be 100644 (file)
@@ -52,18 +52,18 @@ static void LoopIncrement(Mutex* mutex, int rem) {
     int count = 0;
     int last_count = -1;
     do {
-      CHECK_EQ(0, mutex->Lock());
+      mutex->Lock();
       count = busy_lock_counter;
-      CHECK_EQ(0, mutex->Unlock());
+      mutex->Unlock();
       yield();
     } while (count % 2 == rem && count < kLockCounterLimit);
     if (count >= kLockCounterLimit) break;
-    CHECK_EQ(0, mutex->Lock());
+    mutex->Lock();
     CHECK_EQ(count, busy_lock_counter);
     CHECK(last_count == -1 || count == last_count + 1);
     busy_lock_counter++;
     last_count = count;
-    CHECK_EQ(0, mutex->Unlock());
+    mutex->Unlock();
     yield();
   }
 }
similarity index 74%
rename from test/cctest/test-lock.cc
rename to test/cctest/test-semaphore.cc
index d4387d0..e06d52d 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2006-2008 the V8 project authors. All rights reserved.
+// Copyright 2006-2013 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:
@@ -25,9 +25,7 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //
-// Tests of the TokenLock class from lock.h
-
-#include <stdlib.h>
+// Tests of the Semaphore class from platform.h
 
 #include "v8.h"
 
 using namespace ::v8::internal;
 
 
-// Simple test of locking logic
-TEST(Simple) {
-  Mutex* mutex = OS::CreateMutex();
-  CHECK_EQ(0, mutex->Lock());  // acquire the lock with the right token
-  CHECK_EQ(0, mutex->Unlock());  // can unlock with the right token
-  delete mutex;
-}
-
-
-TEST(MultiLock) {
-  Mutex* mutex = OS::CreateMutex();
-  CHECK_EQ(0, mutex->Lock());
-  CHECK_EQ(0, mutex->Unlock());
-  delete mutex;
-}
-
-
-TEST(ShallowLock) {
-  Mutex* mutex = OS::CreateMutex();
-  CHECK_EQ(0, mutex->Lock());
-  CHECK_EQ(0, mutex->Unlock());
-  CHECK_EQ(0, mutex->Lock());
-  CHECK_EQ(0, mutex->Unlock());
-  delete mutex;
-}
-
-
 TEST(SemaphoreTimeout) {
   bool ok;
   Semaphore* sem = OS::CreateSemaphore(0);
index bdbc716..8a7e06d 100644 (file)
         '../../src/marking-thread.cc',
         '../../src/messages.cc',
         '../../src/messages.h',
+        '../../src/mutex.cc',
+        '../../src/mutex.h',
         '../../src/natives.h',
         '../../src/objects-debug.cc',
         '../../src/objects-inl.h',