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;
}
// 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;
math_exp_data_initialized = true;
}
- math_exp_data_mutex->Unlock();
}
void RemoteDebugger::AddEvent(RemoteDebuggerEvent* event) {
- i::ScopedLock lock(event_access_);
+ i::ScopedLock lock(&event_access_);
if (head_ == NULL) {
ASSERT(tail_ == NULL);
head_ = event;
RemoteDebuggerEvent* RemoteDebugger::GetEvent() {
- i::ScopedLock lock(event_access_);
+ i::ScopedLock lock(&event_access_);
ASSERT(head_ != NULL);
RemoteDebuggerEvent* result = head_;
head_ = head_->next();
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();
// 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_;
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
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);
"-------------+\n");
delete [] counters;
}
- delete context_mutex_;
delete counters_file_;
delete counter_map_;
#endif // V8_SHARED
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);
"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) {
void DebuggerAgent::CloseSession() {
- ScopedLock with(session_access_);
+ ScopedLock with(&session_access_);
// Terminate the session.
if (session_ != NULL) {
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) {
}
// Terminate the session.
- ScopedLock with(session_access_);
+ ScopedLock with(&session_access_);
ASSERT(session == session_);
if (session == session_) {
session_->Shutdown();
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);
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_;
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),
Debugger::~Debugger() {
- delete dispatch_handler_access_;
- dispatch_handler_access_ = 0;
delete command_received_;
command_received_ = 0;
}
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) {
MessageDispatchHelperThread* dispatch_thread;
{
- ScopedLock with(dispatch_handler_access_);
+ ScopedLock with(&dispatch_handler_access_);
dispatch_thread = message_dispatch_helper_thread_;
}
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) {
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;
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();
}
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;
}
while (true) {
sem_->Wait();
{
- ScopedLock lock(mutex_);
+ ScopedLock lock(&mutex_);
already_signalled_ = false;
}
{
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);
};
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_;
Isolate* isolate_;
Semaphore* const sem_;
- Mutex* const mutex_;
+ Mutex mutex_;
bool already_signalled_;
DISALLOW_COPY_AND_ASSIGN(MessageDispatchHelperThread);
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
#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;
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);
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;
}
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;
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();
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),
Deinit();
- { ScopedLock lock(process_wide_mutex_);
+ { ScopedLock lock(&process_wide_mutex_);
thread_data_table_->RemoveAllThreads(this);
}
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;
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);
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);
// 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_;
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_;
}
~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:
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.
--- /dev/null
+// 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
--- /dev/null
+// 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_
void OptimizingCompilerThread::Run() {
#ifdef DEBUG
- { ScopedLock lock(thread_id_mutex_);
+ { ScopedLock lock(&thread_id_mutex_);
thread_id_ = ThreadId::Current().ToInteger();
}
#endif
// 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();
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);
#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
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));
#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_;
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_;
// 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;
}
// 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;
}
// 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;
}
// 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;
}
}
-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) {
// 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;
}
}
-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.
//
// 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;
}
// ----------------------------------------------------------------------------
-// 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
// 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;
}
#endif // WIN32
-#include "lazy-instance.h"
+#include "mutex.h"
#include "utils.h"
#include "v8globals.h"
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);
// ----------------------------------------------------------------------------
-// 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
//
: 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) {
// 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) {
FreeListCategory() :
top_(NULL),
end_(NULL),
- mutex_(OS::CreateMutex()),
available_(0) {}
- ~FreeListCategory() {
- delete mutex_;
- }
+ ~FreeListCategory() {}
intptr_t Concatenate(FreeListCategory* category);
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();
private:
FreeListNode* top_;
FreeListNode* end_;
- Mutex* mutex_;
+ Mutex mutex_;
// Total available bytes in all blocks of this free list category.
int available_;
void ThreadManager::Lock() {
- mutex_->Lock();
+ mutex_.Lock();
mutex_owner_ = ThreadId::Current();
ASSERT(IsLockedByCurrentThread());
}
void ThreadManager::Unlock() {
mutex_owner_ = ThreadId::Invalid();
- mutex_->Unlock();
+ mutex_.Unlock();
}
// 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),
ThreadManager::~ThreadManager() {
- delete mutex_;
DeleteThreadStateList(free_anchor_);
DeleteThreadStateList(in_use_anchor_);
}
void EagerlyArchiveThread();
- Mutex* mutex_;
+ Mutex mutex_;
ThreadId mutex_owner_;
ThreadId lazily_archived_thread_;
ThreadState* lazily_archived_thread_state_;
#undef ANY
#undef IGNORE
#undef GetObject
-#undef CreateMutex
#undef CreateSemaphore
'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',
'test-random.cc',
'test-regexp.cc',
'test-reloc-info.cc',
+ 'test-semaphore.cc',
'test-serialize.cc',
'test-sockets.cc',
'test-spaces.cc',
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.
}
--- /dev/null
+// 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);
+}
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();
}
}
// 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;
}
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:
// (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);
'../../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',