From e105029f62a6000da69b8d7cde1b323839e503c7 Mon Sep 17 00:00:00 2001 From: Vyacheslav Egorov Date: Wed, 7 Aug 2024 12:59:35 +0000 Subject: [PATCH] [vm] Move synchronization primitives to platform This CL also removes ability to assign names to mutexes which was added in c25ebfff962928b4ab599d6f7e0ffc2087639b4a 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 --- runtime/bin/builtin_impl_sources.gni | 5 - runtime/bin/eventhandler_win.cc | 51 ++- runtime/bin/eventhandler_win.h | 40 +-- runtime/bin/file_system_watcher_macos.cc | 10 +- runtime/bin/thread.h | 69 +--- runtime/bin/thread_absl.cc | 100 ------ runtime/bin/thread_absl.h | 58 ---- runtime/bin/thread_fuchsia.cc | 185 ---------- runtime/bin/thread_fuchsia.h | 57 --- runtime/bin/thread_linux.cc | 185 ---------- runtime/bin/thread_linux.h | 57 --- runtime/bin/thread_macos.cc | 171 --------- runtime/bin/thread_macos.h | 57 --- runtime/bin/thread_win.cc | 85 ----- runtime/bin/thread_win.h | 50 --- runtime/platform/platform_sources.gni | 4 + runtime/platform/synchronization.h | 135 ++++++++ runtime/platform/synchronization_absl.cc | 83 +++++ runtime/platform/synchronization_posix.cc | 172 ++++++++++ runtime/platform/synchronization_win.cc | 93 +++++ runtime/platform/threads.h | 127 +++++++ runtime/vm/heap/page.cc | 2 +- runtime/vm/isolate.cc | 36 +- runtime/vm/os_thread.h | 144 +------- runtime/vm/os_thread_absl.cc | 216 ------------ runtime/vm/os_thread_absl.h | 50 --- runtime/vm/os_thread_android.cc | 319 ----------------- runtime/vm/os_thread_android.h | 49 --- runtime/vm/os_thread_fuchsia.cc | 310 ----------------- runtime/vm/os_thread_fuchsia.h | 49 --- runtime/vm/os_thread_linux.cc | 324 ------------------ runtime/vm/os_thread_linux.h | 49 --- runtime/vm/os_thread_macos.cc | 297 ---------------- runtime/vm/os_thread_macos.h | 49 --- runtime/vm/os_thread_win.cc | 189 ---------- runtime/vm/os_thread_win.h | 42 --- runtime/vm/random.cc | 2 +- runtime/vm/virtual_memory_compressed.cc | 2 +- runtime/vm/zone.cc | 2 +- .../_internal/vm/lib/concurrent_patch.dart | 6 +- sdk/lib/concurrent/concurrent.dart | 4 +- 41 files changed, 694 insertions(+), 3241 deletions(-) delete mode 100644 runtime/bin/thread_absl.h delete mode 100644 runtime/bin/thread_fuchsia.h delete mode 100644 runtime/bin/thread_linux.h delete mode 100644 runtime/bin/thread_macos.h delete mode 100644 runtime/bin/thread_win.h create mode 100644 runtime/platform/synchronization.h create mode 100644 runtime/platform/synchronization_absl.cc create mode 100644 runtime/platform/synchronization_posix.cc create mode 100644 runtime/platform/synchronization_win.cc create mode 100644 runtime/platform/threads.h diff --git a/runtime/bin/builtin_impl_sources.gni b/runtime/bin/builtin_impl_sources.gni index 6e4b6519b54..9f3890baa4a 100644 --- a/runtime/bin/builtin_impl_sources.gni +++ b/runtime/bin/builtin_impl_sources.gni @@ -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", diff --git a/runtime/bin/eventhandler_win.cc b/runtime/bin/eventhandler_win.cc index a42373a242e..37b59551c22 100644 --- a/runtime/bin/eventhandler_win.cc +++ b/runtime/bin/eventhandler_win.cc @@ -190,15 +190,7 @@ Handle::Handle(intptr_t handle, monitor_(), type_(type), handle_(reinterpret_cast(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 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(); } } diff --git a/runtime/bin/eventhandler_win.h b/runtime/bin/eventhandler_win.h index e5eeff2d14d..0e91158dea5 100644 --- a/runtime/bin/eventhandler_win.h +++ b/runtime/bin/eventhandler_win.h @@ -254,16 +254,15 @@ class Handle : public ReferenceCounted, public DescriptorInfoBase { HANDLE handle_; std::unique_ptr - 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, public DescriptorInfoBase { struct sockaddr* sa, socklen_t sa_len); - int flags_; + int flags_ = 0; friend class ReferenceCounted; 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 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 socket_extensions_initialized_{false}; LPFN_ACCEPTEX accept_ex_ = nullptr; diff --git a/runtime/bin/file_system_watcher_macos.cc b/runtime/bin/file_system_watcher_macos.cc index 8c767ef99f9..bbe708d1a96 100644 --- a/runtime/bin/file_system_watcher_macos.cc +++ b/runtime/bin/file_system_watcher_macos.cc @@ -146,7 +146,7 @@ class FSEventsWatcher { static void Run(uword arg) { FSEventsWatcher* watcher = reinterpret_cast(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(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(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(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); }; diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h index e41e8b620a5..286f41b4ee3 100644 --- a/runtime/bin/thread.h +++ b/runtime/bin/thread.h @@ -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 diff --git a/runtime/bin/thread_absl.cc b/runtime/bin/thread_absl.cc index 23bc5e55a5c..0cc3d576fbe 100644 --- a/runtime/bin/thread_absl.cc +++ b/runtime/bin/thread_absl.cc @@ -10,37 +10,12 @@ #include // 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(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 diff --git a/runtime/bin/thread_absl.h b/runtime/bin/thread_absl.h deleted file mode 100644 index 190af2ebd7e..00000000000 --- a/runtime/bin/thread_absl.h +++ /dev/null @@ -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 - -#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_ diff --git a/runtime/bin/thread_fuchsia.cc b/runtime/bin/thread_fuchsia.cc index 20d918b4000..5647eecb60c 100644 --- a/runtime/bin/thread_fuchsia.cc +++ b/runtime/bin/thread_fuchsia.cc @@ -6,7 +6,6 @@ #if defined(DART_HOST_OS_FUCHSIA) && !defined(DART_USE_ABSL) #include "bin/thread.h" -#include "bin/thread_fuchsia.h" #include // NOLINT #include // 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(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 diff --git a/runtime/bin/thread_fuchsia.h b/runtime/bin/thread_fuchsia.h deleted file mode 100644 index 95f26940978..00000000000 --- a/runtime/bin/thread_fuchsia.h +++ /dev/null @@ -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 - -#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_ diff --git a/runtime/bin/thread_linux.cc b/runtime/bin/thread_linux.cc index 409131bda4a..2ae5993498d 100644 --- a/runtime/bin/thread_linux.cc +++ b/runtime/bin/thread_linux.cc @@ -7,7 +7,6 @@ !defined(DART_USE_ABSL) #include "bin/thread.h" -#include "bin/thread_linux.h" #include // NOLINT #include // 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(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 diff --git a/runtime/bin/thread_linux.h b/runtime/bin/thread_linux.h deleted file mode 100644 index b3f99c7f7fa..00000000000 --- a/runtime/bin/thread_linux.h +++ /dev/null @@ -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 - -#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_ diff --git a/runtime/bin/thread_macos.cc b/runtime/bin/thread_macos.cc index 6071333f1af..fa2abffc1f6 100644 --- a/runtime/bin/thread_macos.cc +++ b/runtime/bin/thread_macos.cc @@ -6,7 +6,6 @@ #if defined(DART_HOST_OS_MACOS) && !defined(DART_USE_ABSL) #include "bin/thread.h" -#include "bin/thread_macos.h" #include // NOLINT #include // 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(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(secs); - ts.tv_nsec = static_cast(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 diff --git a/runtime/bin/thread_macos.h b/runtime/bin/thread_macos.h deleted file mode 100644 index c45091e0bd4..00000000000 --- a/runtime/bin/thread_macos.h +++ /dev/null @@ -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 - -#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_ diff --git a/runtime/bin/thread_win.cc b/runtime/bin/thread_win.cc index 6f7b9c01644..2e2fe0684b8 100644 --- a/runtime/bin/thread_win.cc +++ b/runtime/bin/thread_win.cc @@ -6,7 +6,6 @@ #if defined(DART_HOST_OS_WINDOWS) && !defined(DART_USE_ABSL) #include "bin/thread.h" -#include "bin/thread_win.h" #include // 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 diff --git a/runtime/bin/thread_win.h b/runtime/bin/thread_win.h deleted file mode 100644 index 42de4b2d0c8..00000000000 --- a/runtime/bin/thread_win.h +++ /dev/null @@ -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_ diff --git a/runtime/platform/platform_sources.gni b/runtime/platform/platform_sources.gni index e300478c7ea..19fa38e1359 100644 --- a/runtime/platform/platform_sources.gni +++ b/runtime/platform/platform_sources.gni @@ -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", diff --git a/runtime/platform/synchronization.h b/runtime/platform/synchronization.h new file mode 100644 index 00000000000..c0997198238 --- /dev/null +++ b/runtime/platform/synchronization.h @@ -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_ diff --git a/runtime/platform/synchronization_absl.cc b/runtime/platform/synchronization_absl.cc new file mode 100644 index 00000000000..2393bd968db --- /dev/null +++ b/runtime/platform/synchronization_absl.cc @@ -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) diff --git a/runtime/platform/synchronization_posix.cc b/runtime/platform/synchronization_posix.cc new file mode 100644 index 00000000000..b5d86595b7b --- /dev/null +++ b/runtime/platform/synchronization_posix.cc @@ -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 // NOLINT +#include +#include // 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( + Utils::Minimum(static_cast(kMaxInt32), secs)); + ts.tv_nsec = static_cast(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)) diff --git a/runtime/platform/synchronization_win.cc b/runtime/platform/synchronization_win.cc new file mode 100644 index 00000000000..41655290f18 --- /dev/null +++ b/runtime/platform/synchronization_win.cc @@ -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 // 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) diff --git a/runtime/platform/threads.h b/runtime/platform/threads.h new file mode 100644 index 00000000000..3710e2e4d53 --- /dev/null +++ b/runtime/platform/threads.h @@ -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 +#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(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_ diff --git a/runtime/vm/heap/page.cc b/runtime/vm/heap/page.cc index 331fc239c04..fda047ed724 100644 --- a/runtime/vm/heap/page.cc +++ b/runtime/vm/heap/page.cc @@ -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() { diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc index 0d428ab77e3..2080431409c 100644 --- a/runtime/vm/isolate.cc +++ b/runtime/vm/isolate.cc @@ -357,28 +357,18 @@ IsolateGroup::IsolateGroup(std::shared_ptr 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_(), diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h index e49977eec1e..0fc717021b6 100644 --- a/runtime/vm/os_thread.h +++ b/runtime/vm/os_thread.h @@ -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 }; diff --git a/runtime/vm/os_thread_absl.cc b/runtime/vm/os_thread_absl.cc index 37d89967c3b..e951b1d4516 100644 --- a/runtime/vm/os_thread_absl.cc +++ b/runtime/vm/os_thread_absl.cc @@ -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(0); const ThreadJoinId OSThread::kInvalidThreadJoinId = static_cast(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) diff --git a/runtime/vm/os_thread_absl.h b/runtime/vm/os_thread_absl.h index 9912342188f..5f2ecd6c5f7 100644 --- a/runtime/vm/os_thread_absl.h +++ b/runtime/vm/os_thread_absl.h @@ -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_ diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc index 8937d9c0240..a46f38aea04 100644 --- a/runtime/vm/os_thread_android.cc +++ b/runtime/vm/os_thread_android.cc @@ -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(0); const ThreadJoinId OSThread::kInvalidThreadJoinId = static_cast(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(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) diff --git a/runtime/vm/os_thread_android.h b/runtime/vm/os_thread_android.h index 44744218857..ccc24d577b8 100644 --- a/runtime/vm/os_thread_android.h +++ b/runtime/vm/os_thread_android.h @@ -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_ diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc index 97d78198667..b8a119cdf87 100644 --- a/runtime/vm/os_thread_fuchsia.cc +++ b/runtime/vm/os_thread_fuchsia.cc @@ -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(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(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) diff --git a/runtime/vm/os_thread_fuchsia.h b/runtime/vm/os_thread_fuchsia.h index 8df5cb53fd4..363636860b0 100644 --- a/runtime/vm/os_thread_fuchsia.h +++ b/runtime/vm/os_thread_fuchsia.h @@ -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_ diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc index ccaa14a4456..9c4e6beacc7 100644 --- a/runtime/vm/os_thread_linux.cc +++ b/runtime/vm/os_thread_linux.cc @@ -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(0); const ThreadJoinId OSThread::kInvalidThreadJoinId = static_cast(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(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) diff --git a/runtime/vm/os_thread_linux.h b/runtime/vm/os_thread_linux.h index e835af4046f..128c4a28914 100644 --- a/runtime/vm/os_thread_linux.h +++ b/runtime/vm/os_thread_linux.h @@ -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_ diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc index 40937c7ec51..f1ac51ab38a 100644 --- a/runtime/vm/os_thread_macos.cc +++ b/runtime/vm/os_thread_macos.cc @@ -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(nullptr); const ThreadJoinId OSThread::kInvalidThreadJoinId = static_cast(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(id); } -bool OSThread::Compare(ThreadId a, ThreadId b) { - return pthread_equal(a, b) != 0; -} - bool OSThread::GetCurrentStackBounds(uword* lower, uword* upper) { *upper = reinterpret_cast(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(secs); - ts.tv_nsec = static_cast(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) diff --git a/runtime/vm/os_thread_macos.h b/runtime/vm/os_thread_macos.h index 721aa2e5275..05e29f04032 100644 --- a/runtime/vm/os_thread_macos.h +++ b/runtime/vm/os_thread_macos.h @@ -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_ diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc index e7d9014d024..11766f763f5 100644 --- a/runtime/vm/os_thread_win.cc +++ b/runtime/vm/os_thread_win.cc @@ -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(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); diff --git a/runtime/vm/os_thread_win.h b/runtime/vm/os_thread_win.h index 25a50d085e7..30ae179b519 100644 --- a/runtime/vm/os_thread_win.h +++ b/runtime/vm/os_thread_win.h @@ -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 { diff --git a/runtime/vm/random.cc b/runtime/vm/random.cc index 69f55c1917d..dd5a70d336c 100644 --- a/runtime/vm/random.cc +++ b/runtime/vm/random.cc @@ -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(); } diff --git a/runtime/vm/virtual_memory_compressed.cc b/runtime/vm/virtual_memory_compressed.cc index 3832449b66a..bb50cee67f5 100644 --- a/runtime/vm/virtual_memory_compressed.cc +++ b/runtime/vm/virtual_memory_compressed.cc @@ -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() { diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc index fc44ab510ac..e56c0683a71 100644 --- a/runtime/vm/zone.cc +++ b/runtime/vm/zone.cc @@ -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() { diff --git a/sdk/lib/_internal/vm/lib/concurrent_patch.dart b/sdk/lib/_internal/vm/lib/concurrent_patch.dart index 4c8430909f7..63dfb0c0548 100644 --- a/sdk/lib/_internal/vm/lib/concurrent_patch.dart +++ b/sdk/lib/_internal/vm/lib/concurrent_patch.dart @@ -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 diff --git a/sdk/lib/concurrent/concurrent.dart b/sdk/lib/concurrent/concurrent.dart index ffdc550081d..3654a661ecb 100644 --- a/sdk/lib/concurrent/concurrent.dart +++ b/sdk/lib/concurrent/concurrent.dart @@ -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. ///