[vm] Move synchronization primitives to platform

This CL also removes ability to assign names to mutexes which was
added in c25ebfff96 but did not yield
any interesting data.

TEST=ci

CoreLibraryReviewExempt: Changes to dart:concurrent only.
Cq-Include-Trybots: luci.dart.try:vm-fuchsia-release-x64-try,vm-win-debug-x64-try,vm-win-release-x64-try,vm-aot-linux-product-x64-try
Change-Id: Id41e1d29832f6008e02f0a571ee67564e1a84224
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/375300
Reviewed-by: Martin Kustermann <kustermann@google.com>
This commit is contained in:
Vyacheslav Egorov
2024-08-07 12:59:35 +00:00
committed by Commit Queue
parent b3c4471f82
commit e105029f62
41 changed files with 694 additions and 3241 deletions
-5
View File
@@ -42,15 +42,10 @@ builtin_impl_sources = [
"lockers.h",
"thread.h",
"thread_absl.cc",
"thread_absl.h",
"thread_fuchsia.cc",
"thread_fuchsia.h",
"thread_linux.cc",
"thread_linux.h",
"thread_macos.cc",
"thread_macos.h",
"thread_win.cc",
"thread_win.h",
"uri.cc",
"uri.h",
"utils.cc",
+23 -28
View File
@@ -190,15 +190,7 @@ Handle::Handle(intptr_t handle,
monitor_(),
type_(type),
handle_(reinterpret_cast<HANDLE>(handle)),
data_ready_(),
pending_read_(nullptr),
pending_write_(nullptr),
last_error_(NOERROR),
read_thread_id_(Thread::kInvalidThreadId),
read_thread_handle_(nullptr),
read_thread_starting_(false),
read_thread_finished_(false),
flags_(0) {
data_ready_() {
if (supports_overlapped_io == SupportsOverlappedIO::kYes) {
EventHandler::delegate()->AssociateWithCompletionPort(this);
} else {
@@ -256,14 +248,13 @@ void Handle::WaitForReadThreadFinished() {
HANDLE to_join = nullptr;
{
MonitorLocker ml(&monitor_);
if (read_thread_id_ != Thread::kInvalidThreadId) {
if (read_thread_ != INVALID_HANDLE_VALUE) {
while (!read_thread_finished_) {
ml.Wait();
}
read_thread_finished_ = false;
read_thread_id_ = Thread::kInvalidThreadId;
to_join = read_thread_handle_;
read_thread_handle_ = nullptr;
to_join = read_thread_;
read_thread_ = INVALID_HANDLE_VALUE;
}
}
if (to_join != nullptr) {
@@ -296,12 +287,22 @@ void Handle::WriteComplete(std::unique_ptr<OverlappedBuffer> buffer) {
pending_write_ = nullptr;
}
// Helper method which returns a real HANDLE for the current thread.
static HANDLE GetCurrentThreadHandle() {
HANDLE thread_handle = INVALID_HANDLE_VALUE;
if (!DuplicateHandle(GetCurrentProcess(), GetCurrentThread(),
GetCurrentProcess(), &thread_handle,
/*dwDesiredAccess=*/0, FALSE, DUPLICATE_SAME_ACCESS)) {
FATAL("Failed to obtain thread handle");
}
return thread_handle;
}
void Handle::NotifyReadThreadStarted() {
MonitorLocker ml(&monitor_);
ASSERT(read_thread_starting_);
ASSERT(read_thread_id_ == Thread::kInvalidThreadId);
read_thread_id_ = Thread::GetCurrentThreadId();
read_thread_handle_ = OpenThread(SYNCHRONIZE, false, read_thread_id_);
ASSERT(read_thread_ == INVALID_HANDLE_VALUE);
read_thread_ = GetCurrentThreadHandle();
read_thread_starting_ = false;
ml.Notify();
}
@@ -309,7 +310,7 @@ void Handle::NotifyReadThreadStarted() {
void Handle::NotifyReadThreadFinished() {
MonitorLocker ml(&monitor_);
ASSERT(!read_thread_finished_);
ASSERT(read_thread_id_ != Thread::kInvalidThreadId);
ASSERT(read_thread_ != INVALID_HANDLE_VALUE);
read_thread_finished_ = true;
ml.Notify();
}
@@ -747,8 +748,7 @@ StdHandle* StdHandle::Stdin(HANDLE handle) {
void StdHandle::RunWriteLoop() {
MonitorLocker ml(&monitor_);
write_thread_running_ = true;
thread_id_ = Thread::GetCurrentThreadId();
thread_handle_ = OpenThread(SYNCHRONIZE, false, thread_id_);
thread_handle_ = GetCurrentThreadHandle();
// Notify we have started.
ml.Notify();
@@ -1339,14 +1339,11 @@ void EventHandlerImplementation::HandleCompletionOrInterrupt(
}
EventHandlerImplementation::EventHandlerImplementation() {
handler_thread_id_ = Thread::kInvalidThreadId;
handler_thread_handle_ = nullptr;
completion_port_ =
CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, NULL, 1);
if (completion_port_ == nullptr) {
FATAL("Completion port creation failed");
}
shutdown_ = false;
}
namespace {
@@ -1380,8 +1377,8 @@ void EventHandlerImplementation::InitializeSocketExtensions() {
EventHandlerImplementation::~EventHandlerImplementation() {
// Join the handler thread.
DWORD res = WaitForSingleObject(handler_thread_handle_, INFINITE);
CloseHandle(handler_thread_handle_);
DWORD res = WaitForSingleObject(handler_thread_, INFINITE);
CloseHandle(handler_thread_);
ASSERT(res == WAIT_OBJECT_0);
CloseHandle(completion_port_);
}
@@ -1425,9 +1422,7 @@ void EventHandlerImplementation::EventHandlerEntry(uword args) {
{
MonitorLocker ml(&handler_impl->monitor_);
handler_impl->handler_thread_id_ = Thread::GetCurrentThreadId();
handler_impl->handler_thread_handle_ =
OpenThread(SYNCHRONIZE, false, handler_impl->handler_thread_id_);
handler_impl->handler_thread_ = GetCurrentThreadHandle();
ml.Notify();
}
@@ -1499,7 +1494,7 @@ void EventHandlerImplementation::Start(EventHandler* handler) {
{
MonitorLocker ml(&monitor_);
while (handler_thread_id_ == Thread::kInvalidThreadId) {
while (handler_thread_ == INVALID_HANDLE_VALUE) {
ml.Wait();
}
}
+16 -24
View File
@@ -254,16 +254,15 @@ class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {
HANDLE handle_;
std::unique_ptr<OverlappedBuffer>
data_ready_; // Buffer for data ready to be read.
OverlappedBuffer* pending_read_; // Buffer for pending read.
OverlappedBuffer* pending_write_; // Buffer for pending write
data_ready_; // Buffer for data ready to be read.
OverlappedBuffer* pending_read_ = nullptr; // Buffer for pending read.
OverlappedBuffer* pending_write_ = nullptr; // Buffer for pending write
DWORD last_error_;
DWORD last_error_ = NOERROR;
ThreadId read_thread_id_;
HANDLE read_thread_handle_;
bool read_thread_starting_;
bool read_thread_finished_;
HANDLE read_thread_ = INVALID_HANDLE_VALUE;
bool read_thread_starting_ = false;
bool read_thread_finished_ = false;
private:
void WaitForReadThreadStarted();
@@ -278,7 +277,7 @@ class Handle : public ReferenceCounted<Handle>, public DescriptorInfoBase {
struct sockaddr* sa,
socklen_t sa_len);
int flags_;
int flags_ = 0;
friend class ReferenceCounted<Handle>;
DISALLOW_COPY_AND_ASSIGN(Handle);
@@ -324,18 +323,12 @@ class StdHandle : public FileHandle {
static StdHandle* stdin_;
explicit StdHandle(HANDLE handle)
: FileHandle(handle, kStd, SupportsOverlappedIO::kNo),
thread_id_(Thread::kInvalidThreadId),
thread_handle_(nullptr),
thread_wrote_(0),
write_thread_exists_(false),
write_thread_running_(false) {}
: FileHandle(handle, kStd, SupportsOverlappedIO::kNo) {}
ThreadId thread_id_;
HANDLE thread_handle_;
intptr_t thread_wrote_;
bool write_thread_exists_;
bool write_thread_running_;
HANDLE thread_handle_ = INVALID_HANDLE_VALUE;
intptr_t thread_wrote_ = 0;
bool write_thread_exists_ = false;
bool write_thread_running_ = false;
DISALLOW_COPY_AND_ASSIGN(StdHandle);
};
@@ -590,12 +583,11 @@ class EventHandlerImplementation {
std::unique_ptr<OverlappedBuffer> buffer);
Monitor monitor_;
ThreadId handler_thread_id_;
HANDLE handler_thread_handle_;
HANDLE handler_thread_ = INVALID_HANDLE_VALUE;
TimeoutQueue timeout_queue_; // Time for next timeout.
bool shutdown_;
HANDLE completion_port_;
bool shutdown_ = false;
HANDLE completion_port_ = INVALID_HANDLE_VALUE;
std::atomic<bool> socket_extensions_initialized_{false};
LPFN_ACCEPTEX accept_ex_ = nullptr;
+5 -5
View File
@@ -146,7 +146,7 @@ class FSEventsWatcher {
static void Run(uword arg) {
FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(arg);
// Only checked in debug mode.
watcher->threadId_ = Thread::GetCurrentThreadId();
watcher->owner_.Acquire();
watcher->run_loop_ = CFRunLoopGetCurrent();
CFRetain(watcher->run_loop_);
@@ -165,6 +165,7 @@ class FSEventsWatcher {
CFRelease(watcher->run_loop_);
watcher->monitor_.Enter();
watcher->owner_.Release();
watcher->run_loop_ = nullptr;
watcher->monitor_.Notify();
watcher->monitor_.Exit();
@@ -188,7 +189,7 @@ class FSEventsWatcher {
static void StopCallback(CFRunLoopTimerRef timer, void* info) {
FSEventsWatcher* watcher = reinterpret_cast<FSEventsWatcher*>(info);
ASSERT(Thread::Compare(watcher->threadId_, Thread::GetCurrentThreadId()));
DEBUG_ASSERT(watcher->owner_.IsOwnedByCurrentThread());
CFRunLoopStop(watcher->run_loop_);
}
@@ -228,8 +229,7 @@ class FSEventsWatcher {
}
Node* node = static_cast<Node*>(client);
RELEASE_ASSERT(node->watcher() != nullptr);
ASSERT(Thread::Compare(node->watcher()->threadId_,
Thread::GetCurrentThreadId()));
DEBUG_ASSERT(node->watcher()->owner_.IsOwnedByCurrentThread());
for (size_t i = 0; i < num_events; i++) {
char* path = reinterpret_cast<char**>(event_paths)[i];
FSEvent event;
@@ -251,7 +251,7 @@ class FSEventsWatcher {
Monitor monitor_;
CFRunLoopRef run_loop_;
ThreadId threadId_;
platform::ThreadBoundResource owner_;
DISALLOW_COPY_AND_ASSIGN(FSEventsWatcher);
};
+1 -68
View File
@@ -6,37 +6,13 @@
#define RUNTIME_BIN_THREAD_H_
#include "platform/globals.h"
namespace dart {
namespace bin {
class Thread;
class Mutex;
class Monitor;
} // namespace bin
} // namespace dart
// Declare the OS-specific types ahead of defining the generic classes.
#if defined(DART_USE_ABSL)
#include "bin/thread_absl.h"
#elif defined(DART_HOST_OS_FUCHSIA)
#include "bin/thread_fuchsia.h"
#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_ANDROID)
#include "bin/thread_linux.h"
#elif defined(DART_HOST_OS_MACOS)
#include "bin/thread_macos.h"
#elif defined(DART_HOST_OS_WINDOWS)
#include "bin/thread_win.h"
#else
#error Unknown target os.
#endif
#include "platform/synchronization.h"
namespace dart {
namespace bin {
class Thread {
public:
static const ThreadId kInvalidThreadId;
typedef void (*ThreadStartFunction)(uword parameter);
// Start a thread running the specified function. Returns 0 if the
@@ -47,8 +23,6 @@ class Thread {
uword parameters);
static intptr_t GetMaxStackSize();
static ThreadId GetCurrentThreadId();
static bool Compare(ThreadId a, ThreadId b);
static void InitOnce();
@@ -57,47 +31,6 @@ class Thread {
DISALLOW_IMPLICIT_CONSTRUCTORS(Thread);
};
class Mutex {
public:
Mutex();
~Mutex();
void Lock();
bool TryLock();
void Unlock();
private:
MutexData data_;
DISALLOW_COPY_AND_ASSIGN(Mutex);
};
class Monitor {
public:
enum WaitResult { kNotified, kTimedOut };
static constexpr int64_t kNoTimeout = 0;
Monitor();
~Monitor();
void Enter();
void Exit();
// Wait for notification or timeout.
WaitResult Wait(int64_t millis);
WaitResult WaitMicros(int64_t micros);
// Notify waiting threads.
void Notify();
void NotifyAll();
private:
MonitorData data_; // OS-specific data.
DISALLOW_COPY_AND_ASSIGN(Monitor);
};
} // namespace bin
} // namespace dart
-100
View File
@@ -10,37 +10,12 @@
#include <sys/time.h> // NOLINT
#include "bin/thread.h"
#include "bin/thread_absl.h"
#include "platform/assert.h"
#include "platform/utils.h"
namespace dart {
namespace bin {
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, Utils::StrError(result, error_buf, kBufferSize)); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
return result; \
}
#endif
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -113,86 +88,11 @@ int Thread::Start(const char* name,
return 0;
}
const ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
intptr_t Thread::GetMaxStackSize() {
const int kStackSize = (128 * kWordSize * KB);
return kStackSize;
}
ThreadId Thread::GetCurrentThreadId() {
return pthread_self();
}
bool Thread::Compare(ThreadId a, ThreadId b) {
return (pthread_equal(a, b) != 0);
}
Mutex::Mutex() : data_() {}
Mutex::~Mutex() {}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Mutex::Lock() {
data_.mutex()->Lock();
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
bool Mutex::TryLock() {
if (!data_.mutex()->TryLock()) {
return false;
}
return true;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Mutex::Unlock() {
data_.mutex()->Unlock();
}
Monitor::Monitor() : data_() {}
Monitor::~Monitor() {}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::Enter() {
data_.mutex()->Lock();
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::Exit() {
data_.mutex()->Unlock();
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
return WaitMicros(millis * kMicrosecondsPerMillisecond);
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
data_.cond()->Wait(data_.mutex());
} else {
if (data_.cond()->WaitWithTimeout(data_.mutex(),
absl::Microseconds(micros))) {
retval = kTimedOut;
}
}
return retval;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::Notify() {
data_.cond()->Signal();
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::NotifyAll() {
data_.cond()->SignalAll();
}
} // namespace bin
} // namespace dart
-58
View File
@@ -1,58 +0,0 @@
// Copyright (c) 2022, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_BIN_THREAD_ABSL_H_
#define RUNTIME_BIN_THREAD_ABSL_H_
#if !defined(RUNTIME_BIN_THREAD_H_)
#error Do not include thread_absl.h directly; use thread.h instead.
#endif
#include <pthread.h>
#include "platform/assert.h"
#include "platform/globals.h"
#include "third_party/absl/synchronization/mutex.h"
namespace dart {
namespace bin {
typedef pthread_t ThreadId;
class MutexData {
private:
MutexData() : mutex_() {}
~MutexData() {}
absl::Mutex* mutex() { return &mutex_; }
absl::Mutex mutex_;
friend class Mutex;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class MonitorData {
private:
MonitorData() : mutex_(), cond_() {}
~MonitorData() {}
absl::Mutex* mutex() { return &mutex_; }
absl::CondVar* cond() { return &cond_; }
absl::Mutex mutex_;
absl::CondVar cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_THREAD_ABSL_H_
-185
View File
@@ -6,7 +6,6 @@
#if defined(DART_HOST_OS_FUCHSIA) && !defined(DART_USE_ABSL)
#include "bin/thread.h"
#include "bin/thread_fuchsia.h"
#include <errno.h> // NOLINT
#include <sys/time.h> // NOLINT
@@ -21,44 +20,6 @@
namespace dart {
namespace bin {
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, Utils::StrError(result, error_buf, kBufferSize)); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
return result; \
}
#endif
static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
int64_t secs = micros / kMicrosecondsPerSecond;
int64_t nanos =
(micros - (secs * kMicrosecondsPerSecond)) * kNanosecondsPerMicrosecond;
int result = clock_gettime(CLOCK_MONOTONIC, ts);
ASSERT(result == 0);
ts->tv_sec += secs;
ts->tv_nsec += nanos;
if (ts->tv_nsec >= kNanosecondsPerSecond) {
ts->tv_sec += 1;
ts->tv_nsec -= kNanosecondsPerSecond;
}
}
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -127,157 +88,11 @@ int Thread::Start(const char* name,
return 0;
}
const ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
intptr_t Thread::GetMaxStackSize() {
const int kStackSize = (128 * kWordSize * KB);
return kStackSize;
}
ThreadId Thread::GetCurrentThreadId() {
return pthread_self();
}
bool Thread::Compare(ThreadId a, ThreadId b) {
return (pthread_equal(a, b) != 0);
}
Mutex::Mutex() {
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT(result);
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT(result);
}
void Mutex::Lock() {
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT(result == 0); // Verify no other errors.
// TODO(iposva): Do we need to track lock owners?
}
bool Mutex::TryLock() {
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT(result == 0); // Verify no other errors.
// TODO(iposva): Do we need to track lock owners?
return true;
}
void Mutex::Unlock() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT(result == 0); // Verify no other errors.
}
Monitor::Monitor() {
pthread_mutexattr_t mutex_attr;
int result = pthread_mutexattr_init(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
pthread_condattr_t cond_attr;
result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::~Monitor() {
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::Enter() {
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
// TODO(iposva): Do we need to track lock owners?
}
void Monitor::Exit() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
return WaitMicros(millis * kMicrosecondsPerMillisecond);
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
// TODO(iposva): Do we need to track lock owners?
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
ComputeTimeSpecMicros(&ts, micros);
int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
return retval;
}
void Monitor::Notify() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace bin
} // namespace dart
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_BIN_THREAD_FUCHSIA_H_
#define RUNTIME_BIN_THREAD_FUCHSIA_H_
#if !defined(RUNTIME_BIN_THREAD_H_)
#error Do not include thread_fuchsia.h directly; use thread.h instead.
#endif
#include <pthread.h>
#include "platform/assert.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
typedef pthread_t ThreadId;
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_THREAD_FUCHSIA_H_
-185
View File
@@ -7,7 +7,6 @@
!defined(DART_USE_ABSL)
#include "bin/thread.h"
#include "bin/thread_linux.h"
#include <errno.h> // NOLINT
#include <sys/resource.h> // NOLINT
@@ -19,44 +18,6 @@
namespace dart {
namespace bin {
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, Utils::StrError(result, error_buf, kBufferSize)); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
return result; \
}
#endif
static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
int64_t secs = micros / kMicrosecondsPerSecond;
int64_t nanos =
(micros - (secs * kMicrosecondsPerSecond)) * kNanosecondsPerMicrosecond;
int result = clock_gettime(CLOCK_MONOTONIC, ts);
ASSERT(result == 0);
ts->tv_sec += secs;
ts->tv_nsec += nanos;
if (ts->tv_nsec >= kNanosecondsPerSecond) {
ts->tv_sec += 1;
ts->tv_nsec -= kNanosecondsPerSecond;
}
}
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -124,157 +85,11 @@ int Thread::Start(const char* name,
return 0;
}
const ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(0);
intptr_t Thread::GetMaxStackSize() {
const int kStackSize = (128 * kWordSize * KB);
return kStackSize;
}
ThreadId Thread::GetCurrentThreadId() {
return pthread_self();
}
bool Thread::Compare(ThreadId a, ThreadId b) {
return (pthread_equal(a, b) != 0);
}
Mutex::Mutex() {
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT(result);
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT(result);
}
void Mutex::Lock() {
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT(result == 0); // Verify no other errors.
// TODO(iposva): Do we need to track lock owners?
}
bool Mutex::TryLock() {
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT(result == 0); // Verify no other errors.
// TODO(iposva): Do we need to track lock owners?
return true;
}
void Mutex::Unlock() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT(result == 0); // Verify no other errors.
}
Monitor::Monitor() {
pthread_mutexattr_t mutex_attr;
int result = pthread_mutexattr_init(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
pthread_condattr_t cond_attr;
result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::~Monitor() {
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::Enter() {
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
// TODO(iposva): Do we need to track lock owners?
}
void Monitor::Exit() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
return WaitMicros(millis * kMicrosecondsPerMillisecond);
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
// TODO(iposva): Do we need to track lock owners?
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
ComputeTimeSpecMicros(&ts, micros);
int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
return retval;
}
void Monitor::Notify() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace bin
} // namespace dart
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_BIN_THREAD_LINUX_H_
#define RUNTIME_BIN_THREAD_LINUX_H_
#if !defined(RUNTIME_BIN_THREAD_H_)
#error Do not include thread_linux.h directly; use thread.h instead.
#endif
#include <pthread.h>
#include "platform/assert.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
typedef pthread_t ThreadId;
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_THREAD_LINUX_H_
-171
View File
@@ -6,7 +6,6 @@
#if defined(DART_HOST_OS_MACOS) && !defined(DART_USE_ABSL)
#include "bin/thread.h"
#include "bin/thread_macos.h"
#include <mach/mach_host.h> // NOLINT
#include <mach/mach_init.h> // NOLINT
@@ -25,31 +24,6 @@
namespace dart {
namespace bin {
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
FATAL("pthread error: %d (%s)", result, error_message); \
}
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, error_message); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
return result; \
}
#endif
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -118,156 +92,11 @@ int Thread::Start(const char* name,
return 0;
}
const ThreadId Thread::kInvalidThreadId = static_cast<ThreadId>(nullptr);
intptr_t Thread::GetMaxStackSize() {
const int kStackSize = (128 * kWordSize * KB);
return kStackSize;
}
ThreadId Thread::GetCurrentThreadId() {
return pthread_self();
}
bool Thread::Compare(ThreadId a, ThreadId b) {
return (pthread_equal(a, b) != 0);
}
Mutex::Mutex() {
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT(result);
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT(result);
}
void Mutex::Lock() {
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT(result == 0); // Verify no other errors.
// TODO(iposva): Do we need to track lock owners?
}
bool Mutex::TryLock() {
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if ((result == EBUSY) || (result == EDEADLK)) {
return false;
}
ASSERT(result == 0); // Verify no other errors.
// TODO(iposva): Do we need to track lock owners?
return true;
}
void Mutex::Unlock() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT(result == 0); // Verify no other errors.
}
Monitor::Monitor() {
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), nullptr);
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::~Monitor() {
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::Enter() {
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
// TODO(iposva): Do we need to track lock owners?
}
void Monitor::Exit() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
return WaitMicros(millis * kMicrosecondsPerMillisecond);
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
// TODO(iposva): Do we need to track lock owners?
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
int64_t secs = micros / kMicrosecondsPerSecond;
if (secs > kMaxInt32) {
// Avoid truncation of overly large timeout values.
secs = kMaxInt32;
}
int64_t nanos =
(micros - (secs * kMicrosecondsPerSecond)) * kNanosecondsPerMicrosecond;
ts.tv_sec = static_cast<int32_t>(secs);
ts.tv_nsec = static_cast<long>(nanos); // NOLINT (long used in timespec).
int result =
pthread_cond_timedwait_relative_np(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
return retval;
}
void Monitor::Notify() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// TODO(iposva): Do we need to track lock owners?
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace bin
} // namespace dart
-57
View File
@@ -1,57 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_BIN_THREAD_MACOS_H_
#define RUNTIME_BIN_THREAD_MACOS_H_
#if !defined(RUNTIME_BIN_THREAD_H_)
#error Do not include thread_macos.h directly; use thread.h instead.
#endif
#include <pthread.h>
#include "platform/assert.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
typedef pthread_t ThreadId;
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_THREAD_MACOS_H_
-85
View File
@@ -6,7 +6,6 @@
#if defined(DART_HOST_OS_WINDOWS) && !defined(DART_USE_ABSL)
#include "bin/thread.h"
#include "bin/thread_win.h"
#include <process.h> // NOLINT
@@ -70,95 +69,11 @@ int Thread::Start(const char* name,
return 0;
}
const ThreadId Thread::kInvalidThreadId = 0;
intptr_t Thread::GetMaxStackSize() {
const int kStackSize = (128 * kWordSize * KB);
return kStackSize;
}
ThreadId Thread::GetCurrentThreadId() {
return ::GetCurrentThreadId();
}
bool Thread::Compare(ThreadId a, ThreadId b) {
return (a == b);
}
Mutex::Mutex() {
InitializeSRWLock(&data_.lock_);
}
Mutex::~Mutex() {}
void Mutex::Lock() {
AcquireSRWLockExclusive(&data_.lock_);
}
bool Mutex::TryLock() {
if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) {
return true;
}
return false;
}
void Mutex::Unlock() {
ReleaseSRWLockExclusive(&data_.lock_);
}
Monitor::Monitor() {
InitializeSRWLock(&data_.lock_);
InitializeConditionVariable(&data_.cond_);
}
Monitor::~Monitor() {}
void Monitor::Enter() {
AcquireSRWLockExclusive(&data_.lock_);
}
void Monitor::Exit() {
ReleaseSRWLockExclusive(&data_.lock_);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
Monitor::WaitResult retval = kNotified;
if (millis == kNoTimeout) {
SleepConditionVariableSRW(&data_.cond_, &data_.lock_, INFINITE,
/*Flags=*/0);
} else {
// Wait for the given period of time for a Notify or a NotifyAll
// event.
if (!SleepConditionVariableSRW(&data_.cond_, &data_.lock_, millis,
/*Flags=*/0)) {
ASSERT(GetLastError() == ERROR_TIMEOUT);
retval = kTimedOut;
}
}
return retval;
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
// TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows.
int64_t millis = micros / kMicrosecondsPerMillisecond;
if ((millis * kMicrosecondsPerMillisecond) < micros) {
// We've been asked to sleep for a fraction of a millisecond,
// this isn't supported on Windows. Bumps milliseconds up by one
// so that we never return too early. We likely return late though.
millis += 1;
}
return Wait(millis);
}
void Monitor::Notify() {
WakeConditionVariable(&data_.cond_);
}
void Monitor::NotifyAll() {
WakeAllConditionVariable(&data_.cond_);
}
} // namespace bin
} // namespace dart
-50
View File
@@ -1,50 +0,0 @@
// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_BIN_THREAD_WIN_H_
#define RUNTIME_BIN_THREAD_WIN_H_
#if !defined(RUNTIME_BIN_THREAD_H_)
#error Do not include thread_win.h directly; use thread.h instead.
#endif
#include "platform/assert.h"
#include "platform/globals.h"
namespace dart {
namespace bin {
typedef DWORD ThreadId;
class MutexData {
private:
MutexData() {}
~MutexData() {}
SRWLOCK lock_;
friend class Mutex;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
SRWLOCK lock_;
CONDITION_VARIABLE cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace bin
} // namespace dart
#endif // RUNTIME_BIN_THREAD_WIN_H_
+4
View File
@@ -21,6 +21,10 @@ platform_sources = [
"memory_sanitizer.h",
"safe_stack.h",
"signal_blocker.h",
"synchronization.h",
"synchronization_absl.cc",
"synchronization_posix.cc",
"synchronization_win.cc",
"syslog.h",
"syslog_android.cc",
"syslog_fuchsia.cc",
+135
View File
@@ -0,0 +1,135 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_PLATFORM_SYNCHRONIZATION_H_
#define RUNTIME_PLATFORM_SYNCHRONIZATION_H_
#include "platform/allocation.h"
#include "platform/threads.h"
#if defined(DART_USE_ABSL)
#include "third_party/absl/synchronization/mutex.h"
#endif
namespace dart {
#if defined(DART_USE_ABSL)
using MutexImpl = absl::Mutex;
using ConditionVariableImpl = absl::CondVar;
#elif defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
using MutexImpl = pthread_mutex_t;
using ConditionVariableImpl = pthread_cond_t;
#elif defined(DART_HOST_OS_WINDOWS)
using MutexImpl = SRWLOCK;
using ConditionVariableImpl = CONDITION_VARIABLE;
#else
#error Unknown target os.
#endif
// Mark when we are running in a signal handler (Linux, Android) or with a
// suspended thread (Windows, Mac, Fuchia). During this time, we cannot take
// locks.
class DisallowMutexLockingScope : public ValueObject {
#if defined(DEBUG)
public:
DisallowMutexLockingScope() {
ASSERT(!is_active_);
is_active_ = true;
}
~DisallowMutexLockingScope() { is_active_ = false; }
static bool is_active() { return is_active_; }
private:
static inline thread_local bool is_active_ = false;
#endif // DEBUG
};
class Mutex {
public:
Mutex();
~Mutex();
bool IsOwnedByCurrentThread() const {
return owner_.IsOwnedByCurrentThread();
}
void Lock();
bool TryLock(); // Returns false if lock is busy and locking failed.
void Unlock();
private:
MutexImpl mutex_;
platform::ThreadBoundResource owner_;
friend class ConditionVariable;
DISALLOW_COPY_AND_ASSIGN(Mutex);
};
class ConditionVariable {
public:
enum WaitResult { kNotified, kTimedOut };
static constexpr int64_t kNoTimeout = 0;
ConditionVariable();
~ConditionVariable();
WaitResult Wait(Mutex* mutex, int64_t timeout_millis = kNoTimeout);
WaitResult WaitMicros(Mutex* mutex, int64_t timeout_micros = kNoTimeout);
void Notify();
void NotifyAll();
private:
ConditionVariableImpl cv_;
DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
};
class Monitor {
public:
using WaitResult = ConditionVariable::WaitResult;
static constexpr WaitResult kNotified = ConditionVariable::kNotified;
static constexpr WaitResult kTimedOut = ConditionVariable::kTimedOut;
static constexpr int64_t kNoTimeout = ConditionVariable::kNoTimeout;
Monitor() {}
~Monitor() {}
bool IsOwnedByCurrentThread() const {
return mutex_.IsOwnedByCurrentThread();
}
bool TryEnter() { return mutex_.TryLock(); }
void Enter() { return mutex_.Lock(); }
void Exit() { return mutex_.Unlock(); }
// Wait for notification or timeout.
WaitResult Wait(int64_t timeout_millis) {
return cv_.Wait(&mutex_, timeout_millis);
}
WaitResult WaitMicros(int64_t timeout_micros) {
return cv_.WaitMicros(&mutex_, timeout_micros);
}
// Notify waiting threads.
void Notify() { cv_.Notify(); }
void NotifyAll() { cv_.NotifyAll(); }
private:
Mutex mutex_; // OS-specific data.
ConditionVariable cv_;
DISALLOW_COPY_AND_ASSIGN(Monitor);
};
} // namespace dart
#endif // RUNTIME_PLATFORM_SYNCHRONIZATION_H_
+83
View File
@@ -0,0 +1,83 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h" // NOLINT
#if defined(DART_USE_ABSL)
#include "platform/synchronization.h"
#include "platform/assert.h"
#include "platform/utils.h"
namespace dart {
Mutex::Mutex() {}
Mutex::~Mutex() {}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Mutex::Lock() {
mutex_.Lock();
owner_.Acquire();
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
bool Mutex::TryLock() {
if (!mutex_.TryLock()) {
return false;
}
owner_.Acquire();
return true;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Mutex::Unlock() {
owner_.Release();
mutex_.Unlock();
}
ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {}
ABSL_NO_THREAD_SAFETY_ANALYSIS
ConditionVariable::WaitResult ConditionVariable::Wait(Mutex* mutex,
int64_t timeout_millis) {
static_assert(kNoTimeout * kMicrosecondsPerMillisecond == kNoTimeout);
return WaitMicros(mutex, timeout_millis * kMicrosecondsPerMillisecond);
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
ConditionVariable::WaitResult ConditionVariable::WaitMicros(
Mutex* mutex,
int64_t timeout_micros) {
mutex->owner_.Release();
Monitor::WaitResult retval = kNotified;
if (timeout_micros == kNoTimeout) {
// Wait forever.
cv_.Wait(&mutex->mutex_);
} else {
if (cv_.WaitWithTimeout(&mutex->mutex_,
absl::Microseconds(timeout_micros))) {
retval = kTimedOut;
}
}
mutex->owner_.Acquire();
return retval;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void ConditionVariable::Notify() {
cv_.Signal();
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void ConditionVariable::NotifyAll() {
cv_.SignalAll();
}
} // namespace dart
#endif // defined(DART_USE_ABSL)
+172
View File
@@ -0,0 +1,172 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h" // NOLINT
#if !defined(DART_USE_ABSL) && \
(defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID))
#include "platform/synchronization.h"
#include <errno.h> // NOLINT
#include <stdio.h>
#include <sys/time.h> // NOLINT
#include "platform/utils.h"
namespace dart {
Mutex::Mutex() {
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(&mutex_, &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT(result);
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(&mutex_);
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT(result);
}
void Mutex::Lock() {
DEBUG_ASSERT(!DisallowMutexLockingScope::is_active());
int result = pthread_mutex_lock(&mutex_);
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
owner_.Acquire();
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!DisallowMutexLockingScope::is_active());
int result = pthread_mutex_trylock(&mutex_);
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
owner_.Acquire();
return true;
}
void Mutex::Unlock() {
owner_.Release();
int result = pthread_mutex_unlock(&mutex_);
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
}
ConditionVariable::ConditionVariable() {
pthread_condattr_t cond_attr;
int result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
#if !defined(DART_HOST_OS_MACOS)
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
#endif
result = pthread_cond_init(&cv_, &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
}
ConditionVariable::~ConditionVariable() {
int result = pthread_cond_destroy(&cv_);
VALIDATE_PTHREAD_RESULT(result);
}
ConditionVariable::WaitResult ConditionVariable::Wait(Mutex* mutex,
int64_t millis) {
static_assert(kNoTimeout * kMicrosecondsPerMillisecond == kNoTimeout);
return WaitMicros(mutex, millis * kMicrosecondsPerMillisecond);
}
static int TimedWait(pthread_cond_t* cv,
pthread_mutex_t* mutex,
int64_t timeout_micros) {
const int64_t secs = timeout_micros / kMicrosecondsPerSecond;
const int64_t nanos = (timeout_micros - (secs * kMicrosecondsPerSecond)) *
kNanosecondsPerMicrosecond;
struct timespec ts;
#if defined(DART_HOST_OS_MACOS)
// On Mac OS X we can use non-portable pthread_cond_timedwait_relative_np
// instead of computing timespec for the wakeup moment.
ts.tv_sec = static_cast<int32_t>(
Utils::Minimum(static_cast<int64_t>(kMaxInt32), secs));
ts.tv_nsec = static_cast<long>(nanos); // NOLINT (long used in timespec).
return pthread_cond_timedwait_relative_np(cv, mutex, &ts);
#else
// Otherwise we need to compute absolute timespec.
int result = clock_gettime(CLOCK_MONOTONIC, &ts);
if (result != 0) {
return result;
}
ts.tv_sec += secs;
ts.tv_nsec += nanos;
if (ts.tv_nsec >= kNanosecondsPerSecond) {
ts.tv_sec += 1;
ts.tv_nsec -= kNanosecondsPerSecond;
}
return pthread_cond_timedwait(cv, mutex, &ts);
#endif
}
ConditionVariable::WaitResult ConditionVariable::WaitMicros(
Mutex* mutex,
int64_t timeout_micros) {
mutex->owner_.Release();
Monitor::WaitResult retval = kNotified;
if (timeout_micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(&cv_, &mutex->mutex_);
VALIDATE_PTHREAD_RESULT(result);
} else {
int result = TimedWait(&cv_, &mutex->mutex_, timeout_micros);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
mutex->owner_.Acquire();
return retval;
}
void ConditionVariable::Notify() {
int result = pthread_cond_signal(&cv_);
VALIDATE_PTHREAD_RESULT(result);
}
void ConditionVariable::NotifyAll() {
int result = pthread_cond_broadcast(&cv_);
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace dart
#endif // !defined(DART_USE_ABSL) && (defined(DART_HOST_OS_LINUX) || \
// defined(DART_HOST_OS_FUCHSIA) || \
// defined(DART_HOST_OS_MACOS) || \
// defined(DART_HOST_OS_ANDROID))
+93
View File
@@ -0,0 +1,93 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#include "platform/globals.h" // NOLINT
#if defined(DART_HOST_OS_WINDOWS) && !defined(DART_USE_ABSL)
#include "platform/synchronization.h"
#include <process.h> // NOLINT
#include "platform/address_sanitizer.h"
#include "platform/assert.h"
#include "platform/safe_stack.h"
namespace dart {
Mutex::Mutex() {
InitializeSRWLock(&mutex_);
}
Mutex::~Mutex() {}
void Mutex::Lock() {
DEBUG_ASSERT(!DisallowMutexLockingScope::is_active());
AcquireSRWLockExclusive(&mutex_);
owner_.Acquire();
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!DisallowMutexLockingScope::is_active());
if (TryAcquireSRWLockExclusive(&mutex_) != 0) {
owner_.Acquire();
return true;
}
return false;
}
void Mutex::Unlock() {
owner_.Release();
ReleaseSRWLockExclusive(&mutex_);
}
ConditionVariable::ConditionVariable() {
InitializeConditionVariable(&cv_);
}
ConditionVariable::~ConditionVariable() {}
ConditionVariable::WaitResult ConditionVariable::Wait(Mutex* mutex,
int64_t timeout_millis) {
mutex->owner_.Release();
Monitor::WaitResult retval = kNotified;
if (timeout_millis == kNoTimeout) {
SleepConditionVariableSRW(&cv_, &mutex->mutex_, INFINITE, 0);
} else {
// Wait for the given period of time for a Notify or a NotifyAll
// event.
if (!SleepConditionVariableSRW(&cv_, &mutex->mutex_, timeout_millis, 0)) {
ASSERT(GetLastError() == ERROR_TIMEOUT);
retval = kTimedOut;
}
}
mutex->owner_.Acquire();
return retval;
}
ConditionVariable::WaitResult ConditionVariable::WaitMicros(Mutex* mutex,
int64_t micros) {
// TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows.
int64_t millis = micros / kMicrosecondsPerMillisecond;
if ((millis * kMicrosecondsPerMillisecond) < micros) {
// We've been asked to sleep for a fraction of a millisecond,
// this isn't supported on Windows. Bumps milliseconds up by one
// so that we never return too early. We likely return late though.
millis += 1;
}
return Wait(mutex, millis);
}
void ConditionVariable::Notify() {
WakeConditionVariable(&cv_);
}
void ConditionVariable::NotifyAll() {
WakeAllConditionVariable(&cv_);
}
} // namespace dart
#endif // defined(DART_HOST_OS_WINDOWS) && !defined(DART_USE_ABSL)
+127
View File
@@ -0,0 +1,127 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
#ifndef RUNTIME_PLATFORM_THREADS_H_
#define RUNTIME_PLATFORM_THREADS_H_
#include "platform/assert.h"
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
#include <pthread.h>
#endif
namespace dart {
namespace platform {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
typedef pthread_t ThreadId;
#elif defined(DART_HOST_OS_WINDOWS)
typedef DWORD ThreadId;
#else
#error Unknown target os.
#endif
static constexpr ThreadId kInvalidThreadId = static_cast<ThreadId>(0);
inline ThreadId GetCurrentThreadId() {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
return pthread_self();
#elif defined(DART_HOST_OS_WINDOWS)
return ::GetCurrentThreadId();
#else
#error Unknown target os.
#endif
}
inline bool AreSameThreads(ThreadId a, ThreadId b) {
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
return pthread_equal(a, b) != 0;
#elif defined(DART_HOST_OS_WINDOWS)
return a == b;
#else
#error Unknown target os.
#endif
}
#if defined(DEBUG)
class ThreadBoundResource {
public:
~ThreadBoundResource() { ASSERT(owner_ == kUnowned); }
void Acquire() {
ASSERT(owner_ == kUnowned);
owner_ = GetCurrentThreadId();
}
void Release() {
ASSERT(IsOwnedByCurrentThread());
owner_ = kUnowned;
}
bool IsOwnedByCurrentThread() const {
return AreSameThreads(owner_, GetCurrentThreadId());
}
private:
static constexpr ThreadId kUnowned = kInvalidThreadId;
ThreadId owner_ = kUnowned;
};
#else
class ThreadBoundResource {
public:
void Acquire() {}
void Release() {}
bool IsOwnedByCurrentThread() const {
UNREACHABLE();
return false;
}
};
#endif
} // namespace platform
#if defined(DART_HOST_OS_LINUX) || defined(DART_HOST_OS_FUCHSIA) || \
defined(DART_HOST_OS_MACOS) || defined(DART_HOST_OS_ANDROID)
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
#if defined(DEBUG)
#define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result)
#else
// NOTE: This (currently) expands to a no-op.
#define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0)
#endif
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, Utils::StrError(result, error_buf, kBufferSize)); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) return result;
#endif
#endif
} // namespace dart
#endif // RUNTIME_PLATFORM_THREADS_H_
+1 -1
View File
@@ -30,7 +30,7 @@ static intptr_t page_cache_size = 0;
void Page::Init() {
ASSERT(page_cache_mutex == nullptr);
page_cache_mutex = new Mutex(NOT_IN_PRODUCT("page_cache_mutex"));
page_cache_mutex = new Mutex();
}
void Page::ClearCache() {
+13 -23
View File
@@ -357,28 +357,18 @@ IsolateGroup::IsolateGroup(std::shared_ptr<IsolateGroupSource> source,
#if !defined(DART_PRECOMPILED_RUNTIME)
background_compiler_(new BackgroundCompiler(this)),
#endif
symbols_mutex_(NOT_IN_PRODUCT("IsolateGroup::symbols_mutex_")),
type_canonicalization_mutex_(
NOT_IN_PRODUCT("IsolateGroup::type_canonicalization_mutex_")),
type_arguments_canonicalization_mutex_(NOT_IN_PRODUCT(
"IsolateGroup::type_arguments_canonicalization_mutex_")),
subtype_test_cache_mutex_(
NOT_IN_PRODUCT("IsolateGroup::subtype_test_cache_mutex_")),
megamorphic_table_mutex_(
NOT_IN_PRODUCT("IsolateGroup::megamorphic_table_mutex_")),
type_feedback_mutex_(
NOT_IN_PRODUCT("IsolateGroup::type_feedback_mutex_")),
patchable_call_mutex_(
NOT_IN_PRODUCT("IsolateGroup::patchable_call_mutex_")),
constant_canonicalization_mutex_(
NOT_IN_PRODUCT("IsolateGroup::constant_canonicalization_mutex_")),
kernel_data_lib_cache_mutex_(
NOT_IN_PRODUCT("IsolateGroup::kernel_data_lib_cache_mutex_")),
kernel_data_class_cache_mutex_(
NOT_IN_PRODUCT("IsolateGroup::kernel_data_class_cache_mutex_")),
kernel_constants_mutex_(
NOT_IN_PRODUCT("IsolateGroup::kernel_constants_mutex_")),
field_list_mutex_(NOT_IN_PRODUCT("Isolate::field_list_mutex_")),
symbols_mutex_(),
type_canonicalization_mutex_(),
type_arguments_canonicalization_mutex_(),
subtype_test_cache_mutex_(),
megamorphic_table_mutex_(),
type_feedback_mutex_(),
patchable_call_mutex_(),
constant_canonicalization_mutex_(),
kernel_data_lib_cache_mutex_(),
kernel_data_class_cache_mutex_(),
kernel_constants_mutex_(),
field_list_mutex_(),
boxed_field_list_(GrowableObjectArray::null()),
program_lock_(new SafepointRwLock()),
active_mutators_monitor_(new Monitor()),
@@ -1758,7 +1748,7 @@ Isolate::Isolate(IsolateGroup* isolate_group,
on_shutdown_callback_(Isolate::ShutdownCallback()),
on_cleanup_callback_(Isolate::CleanupCallback()),
random_(),
mutex_(NOT_IN_PRODUCT("Isolate::mutex_")),
mutex_(),
tag_table_(GrowableObjectArray::null()),
sticky_error_(Error::null()),
spawn_count_monitor_(),
+14 -130
View File
@@ -8,6 +8,8 @@
#include "platform/atomic.h"
#include "platform/globals.h"
#include "platform/safe_stack.h"
#include "platform/synchronization.h"
#include "platform/threads.h"
#include "platform/utils.h"
#include "vm/allocation.h"
#include "vm/globals.h"
@@ -37,53 +39,6 @@ class Mutex;
class ThreadState;
class TimelineEventBlock;
class Mutex {
public:
explicit Mutex(NOT_IN_PRODUCT(const char* name = "anonymous mutex"));
~Mutex();
ThreadId InvalidateOwner();
void SetCurrentThreadAsOwner();
bool IsOwnedByCurrentThread() const;
void Lock();
void Unlock();
private:
bool TryLock(); // Returns false if lock is busy and locking failed.
MutexData data_;
NOT_IN_PRODUCT(const char* name_);
#if defined(DEBUG)
ThreadId owner_;
#endif // defined(DEBUG)
friend class ConditionVariable;
friend class MallocLocker;
friend class MutexLocker;
friend class SafepointMutexLocker;
friend class OSThreadIterator;
friend class TimelineEventRecorder;
friend class TimelineEventRingRecorder;
friend class PageSpace;
friend void Dart_TestMutex();
DISALLOW_COPY_AND_ASSIGN(Mutex);
};
class ConditionVariable {
public:
ConditionVariable();
~ConditionVariable();
void Wait(Mutex* mutex);
void Notify();
private:
Mutex* mutex_;
ConditionVariableData data_;
DISALLOW_COPY_AND_ASSIGN(ConditionVariable);
};
class BaseThread {
public:
bool is_os_thread() const { return is_os_thread_; }
@@ -100,6 +55,8 @@ class BaseThread {
DISALLOW_IMPLICIT_CONSTRUCTORS(BaseThread);
};
using ThreadId = platform::ThreadId;
// Low-level operations on OS platform threads.
class OSThread : public BaseThread {
public:
@@ -240,13 +197,11 @@ class OSThread : public BaseThread {
static uword GetThreadLocal(ThreadLocalKey key) {
return ThreadInlineImpl::GetThreadLocal(key);
}
static ThreadId GetCurrentThreadId();
static void SetThreadLocal(ThreadLocalKey key, uword value);
static intptr_t GetMaxStackSize();
static void Join(ThreadJoinId id);
static intptr_t ThreadIdToIntPtr(ThreadId id);
static ThreadId ThreadIdFromIntPtr(intptr_t id);
static bool Compare(ThreadId a, ThreadId b);
// This function can be called only once per OSThread, and should only be
// called when the returned id will eventually be passed to OSThread::Join().
@@ -262,10 +217,17 @@ class OSThread : public BaseThread {
static constexpr intptr_t kStackSizeBufferMax = (16 * KB * kWordSize);
static constexpr float kStackSizeBufferFraction = 0.5;
static const ThreadId kInvalidThreadId;
static const ThreadJoinId kInvalidThreadJoinId;
static constexpr ThreadId kInvalidThreadId = platform::kInvalidThreadId;
static ThreadId GetCurrentThreadId() {
return platform::GetCurrentThreadId();
}
static bool Compare(ThreadId a, ThreadId b) {
return platform::AreSameThreads(a, b);
}
private:
// The constructor is private as CreateOSThread should be used
// to create a new OSThread structure.
@@ -372,78 +334,6 @@ class OSThreadIterator : public ValueObject {
OSThread* next_;
};
class Monitor {
public:
enum WaitResult { kNotified, kTimedOut };
static constexpr int64_t kNoTimeout = 0;
Monitor();
~Monitor();
#if defined(DEBUG)
bool IsOwnedByCurrentThread() const {
return owner_ == OSThread::GetCurrentThreadId();
}
#else
bool IsOwnedByCurrentThread() const {
UNREACHABLE();
return false;
}
#endif
private:
bool TryEnter(); // Returns false if lock is busy and locking failed.
void Enter();
void Exit();
// Wait for notification or timeout.
WaitResult Wait(int64_t millis);
WaitResult WaitMicros(int64_t micros);
// Notify waiting threads.
void Notify();
void NotifyAll();
MonitorData data_; // OS-specific data.
#if defined(DEBUG)
ThreadId owner_;
#endif // defined(DEBUG)
friend class MonitorLocker;
friend class SafepointMonitorLocker;
friend class SafepointRwLock;
friend void Dart_TestMonitor();
DISALLOW_COPY_AND_ASSIGN(Monitor);
};
inline bool Mutex::IsOwnedByCurrentThread() const {
#if defined(DEBUG)
return owner_ == OSThread::GetCurrentThreadId();
#else
UNREACHABLE();
return false;
#endif
}
inline ThreadId Mutex::InvalidateOwner() {
#if defined(DEBUG)
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
return saved_owner;
#else
UNREACHABLE();
#endif
}
inline void Mutex::SetCurrentThreadAsOwner() {
#if defined(DEBUG)
owner_ = OSThread::GetCurrentThreadId();
#else
UNREACHABLE();
#endif
}
// Mark when we are running in a signal handler (Linux, Android) or with a
// suspended thread (Windows, Mac, Fuchia). During this time, we cannot take
// locks, access Thread/Isolate::Current(), or use malloc.
@@ -451,9 +341,6 @@ class ThreadInterruptScope : public ValueObject {
#if defined(DEBUG)
public:
ThreadInterruptScope() {
ASSERT(!in_thread_interrupt_scope_); // We don't use nested signals.
in_thread_interrupt_scope_ = true;
// Poison attempts to use Thread::Current. This is much cheaper than adding
// an assert in Thread::Current itself.
saved_current_vm_thread_ = OSThread::CurrentVMThread();
@@ -462,14 +349,11 @@ class ThreadInterruptScope : public ValueObject {
~ThreadInterruptScope() {
OSThread::SetCurrentVMThread(saved_current_vm_thread_);
in_thread_interrupt_scope_ = false;
}
static bool in_thread_interrupt_scope() { return in_thread_interrupt_scope_; }
private:
DisallowMutexLockingScope disallow_locks_;
ThreadState* saved_current_vm_thread_;
static inline thread_local bool in_thread_interrupt_scope_ = false;
#endif // DEBUG
};
-216
View File
@@ -30,48 +30,6 @@ DEFINE_FLAG(int,
kMinInt,
"The thread priority the VM should use for new worker threads.");
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
// Variation of VALIDATE_PTHREAD_RESULT for named objects.
#if defined(PRODUCT)
#define VALIDATE_PTHREAD_RESULT_NAMED(result) VALIDATE_PTHREAD_RESULT(result)
#else
#define VALIDATE_PTHREAD_RESULT_NAMED(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("[%s] pthread error: %d (%s)", name_, result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
#endif
#if defined(DEBUG)
#define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result)
#else
// NOTE: This (currently) expands to a no-op.
#define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0)
#endif
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, Utils::StrError(result, error_buf, kBufferSize)); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) return result;
#endif
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -187,7 +145,6 @@ int OSThread::Start(const char* name,
return 0;
}
const ThreadId OSThread::kInvalidThreadId = static_cast<ThreadId>(0);
const ThreadJoinId OSThread::kInvalidThreadJoinId =
static_cast<ThreadJoinId>(0);
@@ -216,10 +173,6 @@ intptr_t OSThread::GetMaxStackSize() {
return kStackSize;
}
ThreadId OSThread::GetCurrentThreadId() {
return pthread_self();
}
#ifdef SUPPORT_TIMELINE
ThreadId OSThread::GetCurrentThreadTraceId() {
#if defined(DART_HOST_OS_ANDROID)
@@ -280,10 +233,6 @@ ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
#endif
}
bool OSThread::Compare(ThreadId a, ThreadId b) {
return pthread_equal(a, b) != 0;
}
bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
#if defined(DART_HOST_OS_ANDROID) || defined(DART_HOST_OS_LINUX)
pthread_attr_t attr;
@@ -325,171 +274,6 @@ void OSThread::SetCurrentSafestackPointer(uword ssp) {
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)
#endif
{
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Mutex::~Mutex() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Mutex::Lock() {
data_.mutex()->Lock();
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
bool Mutex::TryLock() {
if (!data_.mutex()->TryLock()) {
return false;
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Mutex::Unlock() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
data_.mutex()->Unlock();
}
ConditionVariable::ConditionVariable() {}
ConditionVariable::~ConditionVariable() {}
void ConditionVariable::Wait(Mutex* mutex) {
#if defined(DEBUG)
ThreadId saved_owner = mutex->InvalidateOwner();
#endif
data_.cond()->Wait(mutex->data_.mutex());
#if defined(DEBUG)
mutex->SetCurrentThreadAsOwner();
ASSERT(OSThread::GetCurrentThreadId() == saved_owner);
#endif
}
void ConditionVariable::Notify() {
data_.cond()->Signal();
}
Monitor::Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Monitor::~Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
bool Monitor::TryEnter() {
if (!data_.mutex()->TryLock()) {
return false;
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::Enter() {
data_.mutex()->Lock();
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::Exit() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
data_.mutex()->Unlock();
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
Monitor::WaitResult retval = WaitMicros(millis * kMicrosecondsPerMillisecond);
return retval;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
data_.cond()->Wait(data_.mutex());
} else {
if (data_.cond()->WaitWithTimeout(data_.mutex(),
absl::Microseconds(micros))) {
retval = kTimedOut;
}
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
ASSERT(owner_ == saved_owner);
#endif // defined(DEBUG)
return retval;
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::Notify() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
data_.cond()->Signal();
}
ABSL_NO_THREAD_SAFETY_ANALYSIS
void Monitor::NotifyAll() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
data_.cond()->SignalAll();
}
} // namespace dart
#endif // defined(DART_USE_ABSL)
-50
View File
@@ -13,12 +13,10 @@
#include "platform/assert.h"
#include "platform/globals.h"
#include "third_party/absl/synchronization/mutex.h"
namespace dart {
typedef pthread_key_t ThreadLocalKey;
typedef pthread_t ThreadId;
typedef pthread_t ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey =
@@ -40,54 +38,6 @@ class ThreadInlineImpl {
DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
};
class MutexData {
private:
MutexData() : mutex_() {}
~MutexData() {}
absl::Mutex* mutex() { return &mutex_; }
absl::Mutex mutex_;
friend class Mutex;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class ConditionVariableData {
private:
ConditionVariableData() : cond_() {}
~ConditionVariableData() {}
absl::CondVar* cond() { return &cond_; }
absl::CondVar cond_;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ConditionVariableData);
};
class MonitorData {
private:
MonitorData() : mutex_(), cond_() {}
~MonitorData() {}
absl::Mutex* mutex() { return &mutex_; }
absl::CondVar* cond() { return &cond_; }
absl::Mutex mutex_;
absl::CondVar cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace dart
#endif // RUNTIME_VM_OS_THREAD_ABSL_H_
-319
View File
@@ -29,62 +29,6 @@ DEFINE_FLAG(int,
kMinInt,
"The thread priority the VM should use for new worker threads.");
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
FATAL("pthread error: %d (%s)", result, error_message); \
}
#if defined(PRODUCT)
#define VALIDATE_PTHREAD_RESULT_NAMED(result) VALIDATE_PTHREAD_RESULT(result)
#else
#define VALIDATE_PTHREAD_RESULT_NAMED(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
FATAL("[%s] pthread error: %d (%s)", name_, result, error_message); \
}
#endif
#if defined(DEBUG)
#define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result)
#else
// NOTE: This (currently) expands to a no-op.
#define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0)
#endif
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, error_message); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) return result;
#endif
static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
struct timeval tv;
int64_t secs = micros / kMicrosecondsPerSecond;
int64_t remaining_micros = (micros - (secs * kMicrosecondsPerSecond));
int result = gettimeofday(&tv, nullptr);
ASSERT(result == 0);
ts->tv_sec = tv.tv_sec + secs;
ts->tv_nsec = (tv.tv_usec + remaining_micros) * kNanosecondsPerMicrosecond;
if (ts->tv_nsec >= kNanosecondsPerSecond) {
ts->tv_sec += 1;
ts->tv_nsec -= kNanosecondsPerSecond;
}
}
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -179,7 +123,6 @@ int OSThread::Start(const char* name,
return 0;
}
const ThreadId OSThread::kInvalidThreadId = static_cast<ThreadId>(0);
const ThreadJoinId OSThread::kInvalidThreadJoinId =
static_cast<ThreadJoinId>(0);
@@ -208,10 +151,6 @@ intptr_t OSThread::GetMaxStackSize() {
return kStackSize;
}
ThreadId OSThread::GetCurrentThreadId() {
return gettid();
}
#ifdef SUPPORT_TIMELINE
ThreadId OSThread::GetCurrentThreadTraceId() {
return GetCurrentThreadId();
@@ -252,10 +191,6 @@ ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
return static_cast<ThreadId>(id);
}
bool OSThread::Compare(ThreadId a, ThreadId b) {
return a == b;
}
bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
pthread_attr_t attr;
if (pthread_getattr_np(pthread_self(), &attr) != 0) {
@@ -290,260 +225,6 @@ void OSThread::SetCurrentSafestackPointer(uword ssp) {
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)
#endif
{
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT_NAMED(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
void Mutex::Lock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Mutex::Unlock() {
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
}
ConditionVariable::ConditionVariable() {
pthread_condattr_t cond_attr;
int result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
}
ConditionVariable::~ConditionVariable() {
int result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void ConditionVariable::Wait(Mutex* mutex) {
#if defined(DEBUG)
ThreadId saved_owner = mutex->InvalidateOwner();
#endif
int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
mutex->SetCurrentThreadAsOwner();
ASSERT(OSThread::GetCurrentThreadId() == saved_owner);
#endif
}
void ConditionVariable::Notify() {
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::Monitor() {
pthread_mutexattr_t mutex_attr;
int result = pthread_mutexattr_init(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
pthread_condattr_t cond_attr;
result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Monitor::~Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
bool Monitor::TryEnter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Monitor::Enter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
void Monitor::Exit() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
return WaitMicros(millis * kMicrosecondsPerMillisecond);
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
ComputeTimeSpecMicros(&ts, micros);
int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
ASSERT(owner_ == saved_owner);
#endif // defined(DEBUG)
return retval;
}
void Monitor::Notify() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace dart
#endif // defined(DART_HOST_OS_ANDROID) && !defined(DART_USE_ABSL)
-49
View File
@@ -17,7 +17,6 @@
namespace dart {
typedef pthread_key_t ThreadLocalKey;
typedef pid_t ThreadId;
typedef pthread_t ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey =
@@ -39,54 +38,6 @@ class ThreadInlineImpl {
DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
};
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class ConditionVariableData {
private:
ConditionVariableData() {}
~ConditionVariableData() {}
pthread_cond_t* cond() { return &cond_; }
pthread_cond_t cond_;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ConditionVariableData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace dart
#endif // RUNTIME_VM_OS_THREAD_ANDROID_H_
-310
View File
@@ -22,49 +22,6 @@
namespace dart {
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
FATAL("pthread error: %d", result); \
}
#if defined(PRODUCT)
#define VALIDATE_PTHREAD_RESULT_NAMED(result) VALIDATE_PTHREAD_RESULT(result)
#else
#define VALIDATE_PTHREAD_RESULT_NAMED(result) \
if (result != 0) { \
FATAL("[%s] pthread error: %d", name_, result); \
}
#endif
#if defined(DEBUG)
#define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result)
#else
// NOTE: This (currently) expands to a no-op.
#define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0)
#endif
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
fprintf(stderr, "%s:%d: pthread error: %d\n", __FILE__, __LINE__, result); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) return result;
#endif
static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
// time in nanoseconds.
zx_time_t now = zx_clock_get_monotonic();
zx_time_t target = now + (micros * kNanosecondsPerMicrosecond);
int64_t secs = target / kNanosecondsPerSecond;
int64_t nanos = target - (secs * kNanosecondsPerSecond);
ts->tv_sec = secs;
ts->tv_nsec = nanos;
}
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -136,7 +93,6 @@ int OSThread::Start(const char* name,
return 0;
}
const ThreadId OSThread::kInvalidThreadId = ZX_HANDLE_INVALID;
const ThreadJoinId OSThread::kInvalidThreadJoinId =
static_cast<ThreadJoinId>(0);
@@ -165,10 +121,6 @@ intptr_t OSThread::GetMaxStackSize() {
return kStackSize;
}
ThreadId OSThread::GetCurrentThreadId() {
return thrd_get_zx_handle(thrd_current());
}
#ifdef SUPPORT_TIMELINE
ThreadId OSThread::GetCurrentThreadTraceId() {
return pthread_self();
@@ -209,10 +161,6 @@ ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
return static_cast<ThreadId>(id);
}
bool OSThread::Compare(ThreadId a, ThreadId b) {
return pthread_equal(a, b) != 0;
}
bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
pthread_attr_t attr;
if (pthread_getattr_np(pthread_self(), &attr) != 0) {
@@ -283,264 +231,6 @@ void OSThread::SetCurrentSafestackPointer(uword ssp) {
#undef STRINGIFY
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)
#endif
{
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT_NAMED(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
void Mutex::Lock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Mutex::Unlock() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
}
ConditionVariable::ConditionVariable() {
pthread_condattr_t cond_attr;
int result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
}
ConditionVariable::~ConditionVariable() {
int result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void ConditionVariable::Wait(Mutex* mutex) {
#if defined(DEBUG)
ThreadId saved_owner = mutex->InvalidateOwner();
#endif
int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
mutex->SetCurrentThreadAsOwner();
ASSERT(OSThread::GetCurrentThreadId() == saved_owner);
#endif
}
void ConditionVariable::Notify() {
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::Monitor() {
pthread_mutexattr_t mutex_attr;
int result = pthread_mutexattr_init(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
pthread_condattr_t cond_attr;
result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Monitor::~Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
bool Monitor::TryEnter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Monitor::Enter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
void Monitor::Exit() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
Monitor::WaitResult retval = WaitMicros(millis * kMicrosecondsPerMillisecond);
return retval;
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
ComputeTimeSpecMicros(&ts, micros);
int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
ASSERT(owner_ == saved_owner);
#endif // defined(DEBUG)
return retval;
}
void Monitor::Notify() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace dart
#endif // defined(DART_HOST_OS_FUCHSIA) && !defined(DART_USE_ABSL)
-49
View File
@@ -18,7 +18,6 @@
namespace dart {
typedef pthread_key_t ThreadLocalKey;
typedef zx_handle_t ThreadId;
typedef pthread_t ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey =
@@ -40,54 +39,6 @@ class ThreadInlineImpl {
DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
};
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class ConditionVariableData {
private:
ConditionVariableData() {}
~ConditionVariableData() {}
pthread_cond_t* cond() { return &cond_; }
pthread_cond_t cond_;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ConditionVariableData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace dart
#endif // RUNTIME_VM_OS_THREAD_FUCHSIA_H_
-324
View File
@@ -28,63 +28,6 @@ DEFINE_FLAG(int,
worker_thread_priority,
kMinInt,
"The thread priority the VM should use for new worker threads.");
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("pthread error: %d (%s)", result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
// Variation of VALIDATE_PTHREAD_RESULT for named objects.
#if defined(PRODUCT)
#define VALIDATE_PTHREAD_RESULT_NAMED(result) VALIDATE_PTHREAD_RESULT(result)
#else
#define VALIDATE_PTHREAD_RESULT_NAMED(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
FATAL("[%s] pthread error: %d (%s)", name_, result, \
Utils::StrError(result, error_buf, kBufferSize)); \
}
#endif
#if defined(DEBUG)
#define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result)
#else
// NOTE: This (currently) expands to a no-op.
#define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0)
#endif
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_buf[kBufferSize]; \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, Utils::StrError(result, error_buf, kBufferSize)); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) return result;
#endif
static void ComputeTimeSpecMicros(struct timespec* ts, int64_t micros) {
int64_t secs = micros / kMicrosecondsPerSecond;
int64_t nanos =
(micros - (secs * kMicrosecondsPerSecond)) * kNanosecondsPerMicrosecond;
int result = clock_gettime(CLOCK_MONOTONIC, ts);
ASSERT(result == 0);
ts->tv_sec += secs;
ts->tv_nsec += nanos;
if (ts->tv_nsec >= kNanosecondsPerSecond) {
ts->tv_sec += 1;
ts->tv_nsec -= kNanosecondsPerSecond;
}
}
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -179,7 +122,6 @@ int OSThread::Start(const char* name,
return 0;
}
const ThreadId OSThread::kInvalidThreadId = static_cast<ThreadId>(0);
const ThreadJoinId OSThread::kInvalidThreadJoinId =
static_cast<ThreadJoinId>(0);
@@ -208,10 +150,6 @@ intptr_t OSThread::GetMaxStackSize() {
return kStackSize;
}
ThreadId OSThread::GetCurrentThreadId() {
return pthread_self();
}
#ifdef SUPPORT_TIMELINE
ThreadId OSThread::GetCurrentThreadTraceId() {
return syscall(__NR_gettid);
@@ -252,10 +190,6 @@ ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
return static_cast<ThreadId>(id);
}
bool OSThread::Compare(ThreadId a, ThreadId b) {
return pthread_equal(a, b) != 0;
}
bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
pthread_attr_t attr;
// May fail on the main thread.
@@ -291,264 +225,6 @@ void OSThread::SetCurrentSafestackPointer(uword ssp) {
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)
#endif
{
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT_NAMED(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
void Mutex::Lock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Mutex::Unlock() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
}
ConditionVariable::ConditionVariable() {
pthread_condattr_t cond_attr;
int result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
}
ConditionVariable::~ConditionVariable() {
int result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void ConditionVariable::Wait(Mutex* mutex) {
#if defined(DEBUG)
ThreadId saved_owner = mutex->InvalidateOwner();
#endif
int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
mutex->SetCurrentThreadAsOwner();
ASSERT(OSThread::GetCurrentThreadId() == saved_owner);
#endif
}
void ConditionVariable::Notify() {
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::Monitor() {
pthread_mutexattr_t mutex_attr;
int result = pthread_mutexattr_init(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&mutex_attr);
VALIDATE_PTHREAD_RESULT(result);
pthread_condattr_t cond_attr;
result = pthread_condattr_init(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), &cond_attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_condattr_destroy(&cond_attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Monitor::~Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
bool Monitor::TryEnter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if (result == EBUSY) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Monitor::Enter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
void Monitor::Exit() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
Monitor::WaitResult retval = WaitMicros(millis * kMicrosecondsPerMillisecond);
return retval;
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
ComputeTimeSpecMicros(&ts, micros);
int result = pthread_cond_timedwait(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
ASSERT(owner_ == saved_owner);
#endif // defined(DEBUG)
return retval;
}
void Monitor::Notify() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace dart
#endif // defined(DART_HOST_OS_LINUX) && !defined(DART_USE_ABSL)
-49
View File
@@ -17,7 +17,6 @@
namespace dart {
typedef pthread_key_t ThreadLocalKey;
typedef pthread_t ThreadId;
typedef pthread_t ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey =
@@ -39,54 +38,6 @@ class ThreadInlineImpl {
DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
};
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class ConditionVariableData {
private:
ConditionVariableData() {}
~ConditionVariableData() {}
pthread_cond_t* cond() { return &cond_; }
pthread_cond_t cond_;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ConditionVariableData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace dart
#endif // RUNTIME_VM_OS_THREAD_LINUX_H_
-297
View File
@@ -34,48 +34,6 @@ DEFINE_FLAG(int,
kMinInt,
"The thread priority the VM should use for new worker threads.");
#define VALIDATE_PTHREAD_RESULT(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
FATAL("pthread error: %d (%s)", result, error_message); \
}
#if defined(PRODUCT)
#define VALIDATE_PTHREAD_RESULT_NAMED(result) VALIDATE_PTHREAD_RESULT(result)
#else
#define VALIDATE_PTHREAD_RESULT_NAMED(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
FATAL("[%s] pthread error: %d (%s)", name_, result, error_message); \
}
#endif
#if defined(DEBUG)
#define ASSERT_PTHREAD_SUCCESS(result) VALIDATE_PTHREAD_RESULT(result)
#else
// NOTE: This (currently) expands to a no-op.
#define ASSERT_PTHREAD_SUCCESS(result) ASSERT(result == 0)
#endif
#ifdef DEBUG
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) { \
const int kBufferSize = 1024; \
char error_message[kBufferSize]; \
Utils::StrError(result, error_message, kBufferSize); \
fprintf(stderr, "%s:%d: pthread error: %d (%s)\n", __FILE__, __LINE__, \
result, error_message); \
return result; \
}
#else
#define RETURN_ON_PTHREAD_FAILURE(result) \
if (result != 0) return result;
#endif
class ThreadStartData {
public:
ThreadStartData(const char* name,
@@ -161,7 +119,6 @@ int OSThread::Start(const char* name,
return 0;
}
const ThreadId OSThread::kInvalidThreadId = static_cast<ThreadId>(nullptr);
const ThreadJoinId OSThread::kInvalidThreadJoinId =
static_cast<ThreadJoinId>(nullptr);
@@ -190,10 +147,6 @@ intptr_t OSThread::GetMaxStackSize() {
return kStackSize;
}
ThreadId OSThread::GetCurrentThreadId() {
return pthread_self();
}
#ifdef SUPPORT_TIMELINE
ThreadId OSThread::GetCurrentThreadTraceId() {
return ThreadIdFromIntPtr(pthread_mach_thread_np(pthread_self()));
@@ -234,10 +187,6 @@ ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
return reinterpret_cast<ThreadId>(id);
}
bool OSThread::Compare(ThreadId a, ThreadId b) {
return pthread_equal(a, b) != 0;
}
bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
*upper = reinterpret_cast<uword>(pthread_get_stackaddr_np(pthread_self()));
*lower = *upper - pthread_get_stacksize_np(pthread_self());
@@ -259,252 +208,6 @@ void OSThread::SetCurrentSafestackPointer(uword ssp) {
}
#endif
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)
#endif
{
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
// Verify that creating a pthread_mutex succeeded.
VALIDATE_PTHREAD_RESULT_NAMED(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Mutex::~Mutex() {
int result = pthread_mutex_destroy(data_.mutex());
// Verify that the pthread_mutex was destroyed.
VALIDATE_PTHREAD_RESULT_NAMED(result);
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
void Mutex::Lock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
// Specifically check for dead lock to help debugging.
ASSERT(result != EDEADLK);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if ((result == EBUSY) || (result == EDEADLK)) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Mutex::Unlock() {
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
// Specifically check for wrong thread unlocking to aid debugging.
ASSERT(result != EPERM);
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
}
ConditionVariable::ConditionVariable() {
int result = pthread_cond_init(data_.cond(), nullptr);
VALIDATE_PTHREAD_RESULT(result);
}
ConditionVariable::~ConditionVariable() {
int result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void ConditionVariable::Wait(Mutex* mutex) {
#if defined(DEBUG)
ThreadId saved_owner = mutex->InvalidateOwner();
#endif
int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
mutex->SetCurrentThreadAsOwner();
ASSERT(OSThread::GetCurrentThreadId() == saved_owner);
#endif
}
void ConditionVariable::Notify() {
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::Monitor() {
pthread_mutexattr_t attr;
int result = pthread_mutexattr_init(&attr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
result = pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
VALIDATE_PTHREAD_RESULT(result);
#endif // defined(DEBUG)
result = pthread_mutex_init(data_.mutex(), &attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_mutexattr_destroy(&attr);
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_init(data_.cond(), nullptr);
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Monitor::~Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
int result = pthread_mutex_destroy(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
result = pthread_cond_destroy(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
bool Monitor::TryEnter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_trylock(data_.mutex());
// Return false if the lock is busy and locking failed.
if ((result == EBUSY) || (result == EDEADLK)) {
return false;
}
ASSERT_PTHREAD_SUCCESS(result); // Verify no other errors.
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
void Monitor::Enter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
int result = pthread_mutex_lock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
void Monitor::Exit() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
int result = pthread_mutex_unlock(data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
return WaitMicros(millis * kMicrosecondsPerMillisecond);
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
Monitor::WaitResult retval = kNotified;
if (micros == kNoTimeout) {
// Wait forever.
int result = pthread_cond_wait(data_.cond(), data_.mutex());
VALIDATE_PTHREAD_RESULT(result);
} else {
struct timespec ts;
int64_t secs = micros / kMicrosecondsPerSecond;
if (secs > kMaxInt32) {
// Avoid truncation of overly large timeout values.
secs = kMaxInt32;
}
int64_t nanos =
(micros - (secs * kMicrosecondsPerSecond)) * kNanosecondsPerMicrosecond;
ts.tv_sec = static_cast<int32_t>(secs);
ts.tv_nsec = static_cast<long>(nanos); // NOLINT (long used in timespec).
int result =
pthread_cond_timedwait_relative_np(data_.cond(), data_.mutex(), &ts);
ASSERT((result == 0) || (result == ETIMEDOUT));
if (result == ETIMEDOUT) {
retval = kTimedOut;
}
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
ASSERT(owner_ == saved_owner);
#endif // defined(DEBUG)
return retval;
}
void Monitor::Notify() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_signal(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
void Monitor::NotifyAll() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
int result = pthread_cond_broadcast(data_.cond());
VALIDATE_PTHREAD_RESULT(result);
}
} // namespace dart
#endif // defined(DART_HOST_OS_MACOS)
-49
View File
@@ -17,7 +17,6 @@
namespace dart {
typedef pthread_key_t ThreadLocalKey;
typedef pthread_t ThreadId;
typedef pthread_t ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey =
@@ -40,54 +39,6 @@ class ThreadInlineImpl {
DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
};
class MutexData {
private:
MutexData() {}
~MutexData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_mutex_t mutex_;
friend class Mutex;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class ConditionVariableData {
private:
ConditionVariableData() {}
~ConditionVariableData() {}
pthread_cond_t* cond() { return &cond_; }
pthread_cond_t cond_;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ConditionVariableData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
pthread_mutex_t* mutex() { return &mutex_; }
pthread_cond_t* cond() { return &cond_; }
pthread_mutex_t mutex_;
pthread_cond_t cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
} // namespace dart
#endif // RUNTIME_VM_OS_THREAD_MACOS_H_
-189
View File
@@ -99,7 +99,6 @@ int OSThread::Start(const char* name,
return 0;
}
const ThreadId OSThread::kInvalidThreadId = 0;
const ThreadJoinId OSThread::kInvalidThreadJoinId = nullptr;
ThreadLocalKey OSThread::CreateThreadLocal(ThreadDestructor destructor) {
@@ -125,10 +124,6 @@ intptr_t OSThread::GetMaxStackSize() {
return kStackSize;
}
ThreadId OSThread::GetCurrentThreadId() {
return ::GetCurrentThreadId();
}
#ifdef SUPPORT_TIMELINE
ThreadId OSThread::GetCurrentThreadTraceId() {
return ::GetCurrentThreadId();
@@ -173,10 +168,6 @@ ThreadId OSThread::ThreadIdFromIntPtr(intptr_t id) {
return static_cast<ThreadId>(id);
}
bool OSThread::Compare(ThreadId a, ThreadId b) {
return a == b;
}
bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) {
// On Windows stack limits for the current thread are available in
// the thread information block (TIB).
@@ -227,186 +218,6 @@ void OSThread::SetThreadLocal(ThreadLocalKey key, uword value) {
}
}
Mutex::Mutex(NOT_IN_PRODUCT(const char* name))
#if !defined(PRODUCT)
: name_(name)
#endif
{
InitializeSRWLock(&data_.lock_);
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Mutex::~Mutex() {
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
void Mutex::Lock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
AcquireSRWLockExclusive(&data_.lock_);
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
bool Mutex::TryLock() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) {
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
return false;
}
void Mutex::Unlock() {
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
ReleaseSRWLockExclusive(&data_.lock_);
}
ConditionVariable::ConditionVariable() {
InitializeConditionVariable(&data_.cond_);
}
ConditionVariable::~ConditionVariable() {}
void ConditionVariable::Wait(Mutex* mutex) {
#if defined(DEBUG)
ThreadId saved_owner = mutex->InvalidateOwner();
#endif
SleepConditionVariableSRW(&data_.cond_, &mutex->data_.lock_, INFINITE, 0);
#if defined(DEBUG)
mutex->SetCurrentThreadAsOwner();
ASSERT(OSThread::GetCurrentThreadId() == saved_owner);
#endif
}
void ConditionVariable::Notify() {
WakeConditionVariable(&data_.cond_);
}
Monitor::Monitor() {
InitializeSRWLock(&data_.lock_);
InitializeConditionVariable(&data_.cond_);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
}
Monitor::~Monitor() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
#endif // defined(DEBUG)
}
bool Monitor::TryEnter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
// Attempt to pass the semaphore but return immediately.
if (TryAcquireSRWLockExclusive(&data_.lock_) != 0) {
#if defined(DEBUG)
// When running with assertions enabled we do track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
return true;
}
return false;
}
void Monitor::Enter() {
DEBUG_ASSERT(!ThreadInterruptScope::in_thread_interrupt_scope());
AcquireSRWLockExclusive(&data_.lock_);
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
#endif // defined(DEBUG)
}
void Monitor::Exit() {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
ReleaseSRWLockExclusive(&data_.lock_);
}
Monitor::WaitResult Monitor::Wait(int64_t millis) {
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
ThreadId saved_owner = owner_;
owner_ = OSThread::kInvalidThreadId;
#endif // defined(DEBUG)
Monitor::WaitResult retval = kNotified;
if (millis == kNoTimeout) {
SleepConditionVariableSRW(&data_.cond_, &data_.lock_, INFINITE, 0);
} else {
// Wait for the given period of time for a Notify or a NotifyAll
// event.
if (!SleepConditionVariableSRW(&data_.cond_, &data_.lock_, millis, 0)) {
ASSERT(GetLastError() == ERROR_TIMEOUT);
retval = kTimedOut;
}
}
#if defined(DEBUG)
// When running with assertions enabled we track the owner.
ASSERT(owner_ == OSThread::kInvalidThreadId);
owner_ = OSThread::GetCurrentThreadId();
ASSERT(owner_ == saved_owner);
#endif // defined(DEBUG)
return retval;
}
Monitor::WaitResult Monitor::WaitMicros(int64_t micros) {
// TODO(johnmccutchan): Investigate sub-millisecond sleep times on Windows.
int64_t millis = micros / kMicrosecondsPerMillisecond;
if ((millis * kMicrosecondsPerMillisecond) < micros) {
// We've been asked to sleep for a fraction of a millisecond,
// this isn't supported on Windows. Bumps milliseconds up by one
// so that we never return too early. We likely return late though.
millis += 1;
}
return Wait(millis);
}
void Monitor::Notify() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
WakeConditionVariable(&data_.cond_);
}
void Monitor::NotifyAll() {
// When running with assertions enabled we track the owner.
ASSERT(IsOwnedByCurrentThread());
WakeAllConditionVariable(&data_.cond_);
}
void ThreadLocalData::AddThreadLocal(ThreadLocalKey key,
ThreadDestructor destructor) {
ASSERT(thread_locals_ != nullptr);
-42
View File
@@ -17,7 +17,6 @@
namespace dart {
typedef DWORD ThreadLocalKey;
typedef DWORD ThreadId;
typedef HANDLE ThreadJoinId;
static const ThreadLocalKey kUnsetThreadLocalKey = TLS_OUT_OF_INDEXES;
@@ -39,47 +38,6 @@ class ThreadInlineImpl {
DISALLOW_COPY_AND_ASSIGN(ThreadInlineImpl);
};
class MutexData {
private:
MutexData() {}
~MutexData() {}
SRWLOCK lock_;
friend class Mutex;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MutexData);
};
class ConditionVariableData {
private:
ConditionVariableData() {}
~ConditionVariableData() {}
CONDITION_VARIABLE cond_;
friend class ConditionVariable;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(ConditionVariableData);
};
class MonitorData {
private:
MonitorData() {}
~MonitorData() {}
SRWLOCK lock_;
CONDITION_VARIABLE cond_;
friend class Monitor;
DISALLOW_ALLOCATION();
DISALLOW_COPY_AND_ASSIGN(MonitorData);
};
typedef void (*ThreadDestructor)(void* parameter);
class ThreadLocalEntry {
+1 -1
View File
@@ -80,7 +80,7 @@ static Mutex* global_random_mutex = nullptr;
void Random::Init() {
ASSERT(global_random_mutex == nullptr);
global_random_mutex = new Mutex(NOT_IN_PRODUCT("global_random_mutex"));
global_random_mutex = new Mutex();
ASSERT(global_random == nullptr);
global_random = new Random();
}
+1 -1
View File
@@ -59,7 +59,7 @@ void VirtualMemoryCompressedHeap::Init(void* compressed_heap_region,
// same upper 32 bits, which is what we really need for compressed pointers.
intptr_t mask = ~(kCompressedHeapAlignment - 1);
ASSERT((base_ & mask) == ((base_ + size_ - 1) & mask));
mutex_ = new Mutex(NOT_IN_PRODUCT("compressed_heap_mutex"));
mutex_ = new Mutex();
}
void VirtualMemoryCompressedHeap::Cleanup() {
+1 -1
View File
@@ -57,7 +57,7 @@ static intptr_t segment_cache_size = 0;
void Zone::Init() {
ASSERT(segment_cache_mutex == nullptr);
segment_cache_mutex = new Mutex(NOT_IN_PRODUCT("segment_cache_mutex"));
segment_cache_mutex = new Mutex();
}
void Zone::Cleanup() {
@@ -10,12 +10,12 @@ import "dart:nativewrappers" show NativeFieldWrapperClass1;
@pragma("vm:entry-point")
abstract interface class Mutex {
@patch
factory Mutex._(String debug_name) => _MutexImpl(debug_name);
factory Mutex._() => _MutexImpl();
}
@pragma("vm:entry-point")
base class _MutexImpl extends NativeFieldWrapperClass1 implements Mutex {
_MutexImpl(this.debug_name) {
_MutexImpl() {
_initialize();
}
@@ -38,8 +38,6 @@ base class _MutexImpl extends NativeFieldWrapperClass1 implements Mutex {
_unlock();
}
}
String debug_name;
}
@patch
+2 -2
View File
@@ -15,9 +15,9 @@ library dart.concurrent;
///
/// Mutex objects are owned by an isolate which created them.
abstract interface class Mutex {
factory Mutex({String debug_name = "mutex"}) => Mutex._(debug_name);
factory Mutex() => Mutex._();
external factory Mutex._(String debug_name);
external factory Mutex._();
/// Acquire exclusive ownership of this mutex.
///