Commit 64bfd42a authored by bmeurer@chromium.org's avatar bmeurer@chromium.org

Simplify implementation of Mutex.

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
parent 96fc677d
......@@ -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();
}
......
......@@ -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();
......
......@@ -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_;
......
......@@ -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
......
......@@ -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);
......
......@@ -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();
......
......@@ -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_;
......
......@@ -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;
}
{
......
......@@ -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);
......
......@@ -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
......
......@@ -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);
......
......@@ -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:
......
......@@ -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.
......
// 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
// 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_
......@@ -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
......
......@@ -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_;
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -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) {
......
......@@ -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;
}
......
......@@ -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.
//
......
......@@ -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;
}
......
......@@ -1704,46 +1704,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.
//
......@@ -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;
}
......
......@@ -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);
......@@ -715,72 +711,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
//
......
......@@ -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) {
......
......@@ -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) {
......
......@@ -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_;
......
......@@ -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_);
}
......
......@@ -119,7 +119,7 @@ class ThreadManager {
void EagerlyArchiveThread();
Mutex* mutex_;
Mutex mutex_;
ThreadId mutex_owner_;
ThreadId lazily_archived_thread_;
ThreadState* lazily_archived_thread_state_;
......
......@@ -94,5 +94,4 @@
#undef ANY
#undef IGNORE
#undef GetObject
#undef CreateMutex
#undef CreateSemaphore
......@@ -79,10 +79,10 @@
'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',
......
......@@ -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.
}
......
// 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);
}
......@@ -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;
}
......
......@@ -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();
}
}
......
// 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"
......@@ -38,33 +36,6 @@
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);
......
......@@ -419,6 +419,8 @@
'../../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',
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment