diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn index 4475779d8d7..addf9a3945c 100644 --- a/runtime/bin/BUILD.gn +++ b/runtime/bin/BUILD.gn @@ -14,7 +14,6 @@ import("../vm/vm_sources.gni") import("builtin_impl_sources.gni") import("builtin_sources.gni") import("cli_sources.gni") -import("concurrent_impl_sources.gni") import("io_impl_sources.gni") import("io_sources.gni") import("native_assets_impl_sources.gni") @@ -136,37 +135,11 @@ build_native_assets_api("native_assets_api_product") { ] } -template("build_concurrent_api") { - extra_configs = [] - if (defined(invoker.extra_configs)) { - extra_configs += invoker.extra_configs - } - source_set(target_name) { - configs += [ "..:dart_config" ] + extra_configs - deps = [] - include_dirs = [ ".." ] - sources = concurrent_api_sources - sources += [ - "concurrent_natives.cc", - "concurrent_natives.h", - ] - } +# TODO(aam): Remove once https://dart-review.googlesource.com/c/sdk/+/377541 +# rolls into flutter engine. +source_set("concurrent_api") { } - -build_concurrent_api("concurrent_api") { - extra_configs = [ - "..:dart_maybe_product_config", - "..:dart_os_config", - "..:dart_arch_config", - ] -} - -build_concurrent_api("concurrent_api_product") { - extra_configs = [ - "..:dart_product_config", - "..:dart_os_config", - "..:dart_arch_config", - ] +source_set("concurrent_api_product") { } static_library("crashpad") { @@ -881,12 +854,6 @@ template("dart_executable") { deps += [ ":standalone_dart_io" ] } - if (use_product_mode) { - deps += [ ":concurrent_api_product" ] - } else { - deps += [ ":concurrent_api" ] - } - configs += [ ":export_api_symbols" ] ldflags = extra_ldflags @@ -1133,7 +1100,6 @@ executable("run_vm_tests") { } deps = [ - ":concurrent_api", ":crashpad", ":dart_kernel_platform_cc", ":dart_snapshot_cc", diff --git a/runtime/bin/builtin_natives.cc b/runtime/bin/builtin_natives.cc index 548548187ed..bd28a128a22 100644 --- a/runtime/bin/builtin_natives.cc +++ b/runtime/bin/builtin_natives.cc @@ -13,7 +13,6 @@ #include "platform/assert.h" #include "bin/builtin.h" -#include "bin/concurrent_natives.h" #include "bin/dartutils.h" #include "bin/file.h" #include "bin/io_natives.h" @@ -25,8 +24,7 @@ namespace bin { // Lists the native functions implementing basic functionality in // standalone dart, such as printing, file I/O, and platform information. // Advanced I/O classes like sockets and process management are implemented -// using functions listed in io_natives.cc and synchronization primitives - -// in concurrent_natives.cc. +// using functions listed in io_natives.cc. #define BUILTIN_NATIVE_LIST(V) V(Builtin_PrintString, 1) BUILTIN_NATIVE_LIST(DECLARE_FUNCTION); @@ -65,10 +63,6 @@ Dart_NativeFunction Builtin::NativeLookup(Dart_Handle name, } Dart_NativeFunction result = IONativeLookup(name, argument_count, auto_setup_scope); - if (result != nullptr) { - return result; - } - result = ConcurrentNativeLookup(name, argument_count, auto_setup_scope); if (result == nullptr) { result = Builtin_DummyNative; } diff --git a/runtime/bin/concurrent.cc b/runtime/bin/concurrent.cc deleted file mode 100644 index 61a839133b0..00000000000 --- a/runtime/bin/concurrent.cc +++ /dev/null @@ -1,104 +0,0 @@ -// 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 "bin/builtin.h" -#include "bin/thread.h" -#include "include/dart_api.h" - -namespace dart { -namespace bin { - -static constexpr int kMutexNativeField = 0; -static constexpr int kCondVarNativeField = 0; - -static void DeleteMutex(void* isolate_data, void* mutex_pointer) { - delete reinterpret_cast(mutex_pointer); -} - -void FUNCTION_NAME(Mutex_Initialize)(Dart_NativeArguments args) { - Dart_Handle mutex_obj = Dart_GetNativeArgument(args, 0); - Mutex* mutex = new Mutex(); - Dart_Handle err = Dart_SetNativeInstanceField( - mutex_obj, kMutexNativeField, reinterpret_cast(mutex)); - if (Dart_IsError(err)) { - delete mutex; - Dart_PropagateError(err); - } - Dart_NewFinalizableHandle(mutex_obj, mutex, sizeof(Mutex), DeleteMutex); -} - -void FUNCTION_NAME(Mutex_Lock)(Dart_NativeArguments args) { - Dart_Handle mutex_obj = Dart_GetNativeArgument(args, 0); - Mutex* mutex; - Dart_Handle result = Dart_GetNativeInstanceField( - mutex_obj, kMutexNativeField, reinterpret_cast(&mutex)); - if (Dart_IsError(result)) { - Dart_PropagateError(result); - } - mutex->Lock(); - Dart_SetReturnValue(args, Dart_Null()); -} - -void FUNCTION_NAME(Mutex_Unlock)(Dart_NativeArguments args) { - Dart_Handle mutex_obj = Dart_GetNativeArgument(args, 0); - Mutex* mutex; - Dart_Handle result = Dart_GetNativeInstanceField( - mutex_obj, kMutexNativeField, reinterpret_cast(&mutex)); - if (Dart_IsError(result)) { - Dart_PropagateError(result); - } - mutex->Unlock(); - Dart_SetReturnValue(args, Dart_Null()); -} - -static void DeleteConditionVariable(void* isolate_data, void* condvar_pointer) { - delete reinterpret_cast(condvar_pointer); -} - -void FUNCTION_NAME(ConditionVariable_Initialize)(Dart_NativeArguments args) { - Dart_Handle condvar_obj = Dart_GetNativeArgument(args, 0); - ConditionVariable* condvar = new ConditionVariable(); - Dart_Handle err = Dart_SetNativeInstanceField( - condvar_obj, kCondVarNativeField, reinterpret_cast(condvar)); - if (Dart_IsError(err)) { - delete condvar; - Dart_PropagateError(err); - } - Dart_NewFinalizableHandle(condvar_obj, condvar, sizeof(ConditionVariable), - DeleteConditionVariable); -} - -void FUNCTION_NAME(ConditionVariable_Wait)(Dart_NativeArguments args) { - Dart_Handle condvar_obj = Dart_GetNativeArgument(args, 0); - Dart_Handle mutex_obj = Dart_GetNativeArgument(args, 1); - Mutex* mutex; - Dart_Handle result_mutex = Dart_GetNativeInstanceField( - mutex_obj, kCondVarNativeField, reinterpret_cast(&mutex)); - if (Dart_IsError(result_mutex)) { - Dart_PropagateError(result_mutex); - } - ConditionVariable* condvar; - Dart_Handle result_condvar = Dart_GetNativeInstanceField( - condvar_obj, kCondVarNativeField, reinterpret_cast(&condvar)); - if (Dart_IsError(result_condvar)) { - Dart_PropagateError(result_condvar); - } - condvar->Wait(mutex); - Dart_SetReturnValue(args, Dart_Null()); -} - -void FUNCTION_NAME(ConditionVariable_Notify)(Dart_NativeArguments args) { - Dart_Handle condvar_obj = Dart_GetNativeArgument(args, 0); - ConditionVariable* condvar; - Dart_Handle result_condvar = Dart_GetNativeInstanceField( - condvar_obj, kCondVarNativeField, reinterpret_cast(&condvar)); - if (Dart_IsError(result_condvar)) { - Dart_PropagateError(result_condvar); - } - condvar->Notify(); - Dart_SetReturnValue(args, Dart_Null()); -} - -} // namespace bin -} // namespace dart diff --git a/runtime/bin/concurrent_natives.cc b/runtime/bin/concurrent_natives.cc deleted file mode 100644 index c6609212bbd..00000000000 --- a/runtime/bin/concurrent_natives.cc +++ /dev/null @@ -1,63 +0,0 @@ -// 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 "bin/concurrent_natives.h" - -#include "bin/builtin.h" - -namespace dart { -namespace bin { - -// Lists the native functions implementing advanced dart:io classes. -// Some classes, like File and Directory, list their implementations in -// builtin_natives.cc instead. -#define CONCURRENT_NATIVE_LIST(V) \ - V(Mutex_Initialize, 1) \ - V(Mutex_Lock, 1) \ - V(Mutex_Unlock, 1) \ - V(ConditionVariable_Initialize, 1) \ - V(ConditionVariable_Wait, 2) \ - V(ConditionVariable_Notify, 1) - -CONCURRENT_NATIVE_LIST(DECLARE_FUNCTION); - -static const struct NativeEntries { - const char* name_; - Dart_NativeFunction function_; - int argument_count_; -} ConcurrentEntries[] = {CONCURRENT_NATIVE_LIST(REGISTER_FUNCTION)}; - -Dart_NativeFunction ConcurrentNativeLookup(Dart_Handle name, - int argument_count, - bool* auto_setup_scope) { - const char* function_name = nullptr; - Dart_Handle result = Dart_StringToCString(name, &function_name); - ASSERT(!Dart_IsError(result)); - ASSERT(function_name != nullptr); - ASSERT(auto_setup_scope != nullptr); - *auto_setup_scope = true; - int num_entries = sizeof(ConcurrentEntries) / sizeof(struct NativeEntries); - for (int i = 0; i < num_entries; i++) { - const struct NativeEntries* entry = &(ConcurrentEntries[i]); - if ((strcmp(function_name, entry->name_) == 0) && - (entry->argument_count_ == argument_count)) { - return reinterpret_cast(entry->function_); - } - } - return nullptr; -} - -const uint8_t* ConcurrentNativeSymbol(Dart_NativeFunction nf) { - int num_entries = sizeof(ConcurrentEntries) / sizeof(struct NativeEntries); - for (int i = 0; i < num_entries; i++) { - const struct NativeEntries* entry = &(ConcurrentEntries[i]); - if (reinterpret_cast(entry->function_) == nf) { - return reinterpret_cast(entry->name_); - } - } - return nullptr; -} - -} // namespace bin -} // namespace dart diff --git a/runtime/bin/concurrent_natives.h b/runtime/bin/concurrent_natives.h deleted file mode 100644 index 4de04b4c8fa..00000000000 --- a/runtime/bin/concurrent_natives.h +++ /dev/null @@ -1,22 +0,0 @@ -// 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_BIN_CONCURRENT_NATIVES_H_ -#define RUNTIME_BIN_CONCURRENT_NATIVES_H_ - -#include "include/dart_api.h" - -namespace dart { -namespace bin { - -Dart_NativeFunction ConcurrentNativeLookup(Dart_Handle name, - int argument_count, - bool* auto_setup_scope); - -const uint8_t* ConcurrentNativeSymbol(Dart_NativeFunction nf); - -} // namespace bin -} // namespace dart - -#endif // RUNTIME_BIN_CONCURRENT_NATIVES_H_ diff --git a/runtime/bin/thread.h b/runtime/bin/thread.h index 313de35caac..e41e8b620a5 100644 --- a/runtime/bin/thread.h +++ b/runtime/bin/thread.h @@ -69,25 +69,9 @@ class Mutex { private: MutexData data_; - friend class ConditionVariable; - DISALLOW_COPY_AND_ASSIGN(Mutex); }; -class ConditionVariable { - public: - ConditionVariable(); - ~ConditionVariable(); - - void Wait(Mutex* mutex); - void Notify(); - - private: - ConditionVariableData data_; - - DISALLOW_COPY_AND_ASSIGN(ConditionVariable); -}; - class Monitor { public: enum WaitResult { kNotified, kTimedOut }; diff --git a/runtime/bin/thread_absl.cc b/runtime/bin/thread_absl.cc index 245d37a7219..23bc5e55a5c 100644 --- a/runtime/bin/thread_absl.cc +++ b/runtime/bin/thread_absl.cc @@ -150,19 +150,6 @@ void Mutex::Unlock() { data_.mutex()->Unlock(); } -ConditionVariable::ConditionVariable() {} - -ConditionVariable::~ConditionVariable() {} - -ABSL_NO_THREAD_SAFETY_ANALYSIS -void ConditionVariable::Wait(Mutex* mutex) { - data_.cond()->Wait(mutex->data_.mutex()); -} - -void ConditionVariable::Notify() { - data_.cond()->Signal(); -} - Monitor::Monitor() : data_() {} Monitor::~Monitor() {} diff --git a/runtime/bin/thread_absl.h b/runtime/bin/thread_absl.h index 3e8add491ab..190af2ebd7e 100644 --- a/runtime/bin/thread_absl.h +++ b/runtime/bin/thread_absl.h @@ -30,27 +30,11 @@ class MutexData { 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_() {} diff --git a/runtime/bin/thread_fuchsia.cc b/runtime/bin/thread_fuchsia.cc index 5a5d769cb48..20d918b4000 100644 --- a/runtime/bin/thread_fuchsia.cc +++ b/runtime/bin/thread_fuchsia.cc @@ -193,37 +193,6 @@ void Mutex::Unlock() { ASSERT(result == 0); // 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) { - int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex()); - VALIDATE_PTHREAD_RESULT(result); -} - -void ConditionVariable::Notify() { - // TODO(iposva): Do we need to track lock owners? - 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); diff --git a/runtime/bin/thread_fuchsia.h b/runtime/bin/thread_fuchsia.h index c313065e9fb..95f26940978 100644 --- a/runtime/bin/thread_fuchsia.h +++ b/runtime/bin/thread_fuchsia.h @@ -29,26 +29,11 @@ class MutexData { 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() {} diff --git a/runtime/bin/thread_linux.cc b/runtime/bin/thread_linux.cc index c045aef9ac3..409131bda4a 100644 --- a/runtime/bin/thread_linux.cc +++ b/runtime/bin/thread_linux.cc @@ -190,37 +190,6 @@ void Mutex::Unlock() { ASSERT(result == 0); // 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) { - int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex()); - VALIDATE_PTHREAD_RESULT(result); -} - -void ConditionVariable::Notify() { - // TODO(iposva): Do we need to track lock owners? - 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); diff --git a/runtime/bin/thread_linux.h b/runtime/bin/thread_linux.h index c55f9b228c5..b3f99c7f7fa 100644 --- a/runtime/bin/thread_linux.h +++ b/runtime/bin/thread_linux.h @@ -29,26 +29,11 @@ class MutexData { 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() {} diff --git a/runtime/bin/thread_macos.cc b/runtime/bin/thread_macos.cc index 13c1413254f..6071333f1af 100644 --- a/runtime/bin/thread_macos.cc +++ b/runtime/bin/thread_macos.cc @@ -184,27 +184,6 @@ void Mutex::Unlock() { ASSERT(result == 0); // 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) { - int result = pthread_cond_wait(data_.cond(), mutex->data_.mutex()); - VALIDATE_PTHREAD_RESULT(result); -} - -void ConditionVariable::Notify() { - // TODO(iposva): Do we need to track lock owners? - int result = pthread_cond_signal(data_.cond()); - VALIDATE_PTHREAD_RESULT(result); -} - Monitor::Monitor() { pthread_mutexattr_t attr; int result = pthread_mutexattr_init(&attr); diff --git a/runtime/bin/thread_macos.h b/runtime/bin/thread_macos.h index 494aa65e80a..c45091e0bd4 100644 --- a/runtime/bin/thread_macos.h +++ b/runtime/bin/thread_macos.h @@ -29,26 +29,11 @@ class MutexData { 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() {} diff --git a/runtime/bin/thread_win.cc b/runtime/bin/thread_win.cc index 2a65586484d..fea1a63aaf6 100644 --- a/runtime/bin/thread_win.cc +++ b/runtime/bin/thread_win.cc @@ -106,20 +106,6 @@ void Mutex::Unlock() { ReleaseSRWLockExclusive(&data_.lock_); } -ConditionVariable::ConditionVariable() { - InitializeConditionVariable(&data_.cond_); -} - -ConditionVariable::~ConditionVariable() {} - -void ConditionVariable::Wait(Mutex* mutex) { - SleepConditionVariableSRW(&data_.cond_, &mutex->data_.lock_, INFINITE, 0); -} - -void ConditionVariable::Notify() { - WakeConditionVariable(&data_.cond_); -} - Monitor::Monitor() { InitializeCriticalSection(&data_.cs_); InitializeConditionVariable(&data_.cond_); diff --git a/runtime/bin/thread_win.h b/runtime/bin/thread_win.h index 141e0d054f4..99691d24ab8 100644 --- a/runtime/bin/thread_win.h +++ b/runtime/bin/thread_win.h @@ -25,25 +25,11 @@ class 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() {} diff --git a/runtime/lib/concurrent.cc b/runtime/lib/concurrent.cc new file mode 100644 index 00000000000..1a76eea863a --- /dev/null +++ b/runtime/lib/concurrent.cc @@ -0,0 +1,101 @@ +// 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 "include/dart_api.h" +#include "vm/bootstrap_natives.h" +#include "vm/os_thread.h" + +namespace dart { + +static void DeleteMutex(void* isolate_data, void* mutex_pointer) { + delete reinterpret_cast(mutex_pointer); +} + +static constexpr int kMutexNativeField = 0; + +DEFINE_FFI_NATIVE_ENTRY(Mutex_Initialize, void, (Dart_Handle mutex_handle)) { + Mutex* mutex = new Mutex(); + Dart_Handle err = Dart_SetNativeInstanceField( + mutex_handle, kMutexNativeField, reinterpret_cast(mutex)); + if (Dart_IsError(err)) { + delete mutex; + Dart_PropagateError(err); + } + Dart_NewFinalizableHandle(mutex_handle, mutex, sizeof(Mutex), DeleteMutex); +}; + +DEFINE_FFI_NATIVE_ENTRY(Mutex_Lock, void, (Dart_Handle mutex_handle)) { + Mutex* mutex; + Dart_Handle result = Dart_GetNativeInstanceField( + mutex_handle, kMutexNativeField, reinterpret_cast(&mutex)); + if (Dart_IsError(result)) { + Dart_PropagateError(result); + } + mutex->Lock(); +} + +DEFINE_FFI_NATIVE_ENTRY(Mutex_Unlock, void, (Dart_Handle mutex_handle)) { + Mutex* mutex; + Dart_Handle result = Dart_GetNativeInstanceField( + mutex_handle, kMutexNativeField, reinterpret_cast(&mutex)); + if (Dart_IsError(result)) { + Dart_PropagateError(result); + } + mutex->Unlock(); +} + +static void DeleteConditionVariable(void* isolate_data, void* condvar_pointer) { + delete reinterpret_cast(condvar_pointer); +} + +static constexpr int kCondVarNativeField = 0; + +DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Initialize, + void, + (Dart_Handle condvar_handle)) { + ConditionVariable* condvar = new ConditionVariable(); + Dart_Handle err = Dart_SetNativeInstanceField( + condvar_handle, kCondVarNativeField, reinterpret_cast(condvar)); + if (Dart_IsError(err)) { + delete condvar; + Dart_PropagateError(err); + } + Dart_NewFinalizableHandle(condvar_handle, condvar, sizeof(ConditionVariable), + DeleteConditionVariable); +} + +DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Wait, + void, + (Dart_Handle condvar_handle, + Dart_Handle mutex_handle)) { + Mutex* mutex; + Dart_Handle result_mutex = Dart_GetNativeInstanceField( + mutex_handle, kCondVarNativeField, reinterpret_cast(&mutex)); + if (Dart_IsError(result_mutex)) { + Dart_PropagateError(result_mutex); + } + ConditionVariable* condvar; + Dart_Handle result_condvar = + Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField, + reinterpret_cast(&condvar)); + if (Dart_IsError(result_condvar)) { + Dart_PropagateError(result_condvar); + } + condvar->Wait(mutex); +} + +DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Notify, + void, + (Dart_Handle condvar_handle)) { + ConditionVariable* condvar; + Dart_Handle result_condvar = + Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField, + reinterpret_cast(&condvar)); + if (Dart_IsError(result_condvar)) { + Dart_PropagateError(result_condvar); + } + condvar->Notify(); +} + +} // namespace dart diff --git a/runtime/bin/concurrent_impl_sources.gni b/runtime/lib/concurrent_sources.gni similarity index 81% rename from runtime/bin/concurrent_impl_sources.gni rename to runtime/lib/concurrent_sources.gni index a6f84b20528..2f2bad25145 100644 --- a/runtime/bin/concurrent_impl_sources.gni +++ b/runtime/lib/concurrent_sources.gni @@ -2,4 +2,4 @@ # 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. -concurrent_api_sources = [ "concurrent.cc" ] +concurrent_runtime_cc_files = [ "concurrent.cc" ] diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn index b5c6ef5fa75..b0b270fc097 100644 --- a/runtime/vm/BUILD.gn +++ b/runtime/vm/BUILD.gn @@ -24,6 +24,7 @@ import("../bin/cli_sources.gni") import("../bin/io_sources.gni") import("../configs.gni") import("../lib/async_sources.gni") +import("../lib/concurrent_sources.gni") import("../lib/convert_sources.gni") import("../lib/core_sources.gni") import("../lib/developer_sources.gni") @@ -222,11 +223,12 @@ library_for_all_configs("libdart_lib") { extra_deps += [ "$fuchsia_sdk/pkg/trace-engine" ] } include_dirs = [ ".." ] - allsources = async_runtime_cc_files + core_runtime_cc_files + - developer_runtime_cc_files + isolate_runtime_cc_files + + allsources = async_runtime_cc_files + concurrent_runtime_cc_files + + core_runtime_cc_files + developer_runtime_cc_files + + ffi_runtime_cc_files + isolate_runtime_cc_files + math_runtime_cc_files + mirrors_runtime_cc_files + - typed_data_runtime_cc_files + vmservice_runtime_cc_files + - ffi_runtime_cc_files + typed_data_runtime_cc_files + vmservice_runtime_cc_files + sources = [ "bootstrap.cc" ] + rebase_path(allsources, ".", "../lib") snapshot_sources = [] } diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc index 4547b9154b7..cf2184d341f 100644 --- a/runtime/vm/bootstrap_natives.cc +++ b/runtime/vm/bootstrap_natives.cc @@ -117,6 +117,7 @@ void Bootstrap::SetupNativeResolver() { ASSERT(!library.IsNull()); library.set_native_entry_resolver(resolver); library.set_native_entry_symbol_resolver(symbol_resolver); + library.set_ffi_native_resolver(ffi_native_resolver); library = Library::CoreLibrary(); ASSERT(!library.IsNull()); diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h index e7853f8af98..a9fd1583823 100644 --- a/runtime/vm/bootstrap_natives.h +++ b/runtime/vm/bootstrap_natives.h @@ -366,7 +366,13 @@ namespace dart { V(VariableMirror_type, 2) #define BOOTSTRAP_FFI_NATIVE_LIST(V) \ + V(ConditionVariable_Initialize, void, (Dart_Handle)) \ + V(ConditionVariable_Notify, void, (Dart_Handle)) \ + V(ConditionVariable_Wait, void, (Dart_Handle, Dart_Handle)) \ V(FinalizerEntry_SetExternalSize, void, (Dart_Handle, intptr_t)) \ + V(Mutex_Initialize, void, (Dart_Handle)) \ + V(Mutex_Lock, void, (Dart_Handle)) \ + V(Mutex_Unlock, void, (Dart_Handle)) \ V(Pointer_asTypedListFinalizerAllocateData, void*, ()) \ V(Pointer_asTypedListFinalizerCallbackPointer, void*, ()) diff --git a/runtime/vm/os_thread.h b/runtime/vm/os_thread.h index 2e3fc7507ee..e49977eec1e 100644 --- a/runtime/vm/os_thread.h +++ b/runtime/vm/os_thread.h @@ -42,19 +42,23 @@ class Mutex { explicit Mutex(NOT_IN_PRODUCT(const char* name = "anonymous mutex")); ~Mutex(); + ThreadId InvalidateOwner(); + void SetCurrentThreadAsOwner(); bool IsOwnedByCurrentThread() const; - private: void Lock(); - bool TryLock(); // Returns false if lock is busy and locking failed. 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; @@ -66,6 +70,20 @@ class Mutex { 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_; } @@ -408,6 +426,24 @@ inline bool Mutex::IsOwnedByCurrentThread() const { #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. diff --git a/runtime/vm/os_thread_absl.cc b/runtime/vm/os_thread_absl.cc index 8c4e7e2aecd..37d89967c3b 100644 --- a/runtime/vm/os_thread_absl.cc +++ b/runtime/vm/os_thread_absl.cc @@ -374,6 +374,27 @@ void Mutex::Unlock() { 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. diff --git a/runtime/vm/os_thread_absl.h b/runtime/vm/os_thread_absl.h index e10793b22fc..9912342188f 100644 --- a/runtime/vm/os_thread_absl.h +++ b/runtime/vm/os_thread_absl.h @@ -50,11 +50,27 @@ class MutexData { 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_() {} diff --git a/runtime/vm/os_thread_android.cc b/runtime/vm/os_thread_android.cc index d4ad65acb45..8937d9c0240 100644 --- a/runtime/vm/os_thread_android.cc +++ b/runtime/vm/os_thread_android.cc @@ -369,6 +369,45 @@ void Mutex::Unlock() { 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); diff --git a/runtime/vm/os_thread_android.h b/runtime/vm/os_thread_android.h index 9e2e0d04a8a..44744218857 100644 --- a/runtime/vm/os_thread_android.h +++ b/runtime/vm/os_thread_android.h @@ -49,11 +49,27 @@ class MutexData { 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() {} diff --git a/runtime/vm/os_thread_fuchsia.cc b/runtime/vm/os_thread_fuchsia.cc index c5294233172..97d78198667 100644 --- a/runtime/vm/os_thread_fuchsia.cc +++ b/runtime/vm/os_thread_fuchsia.cc @@ -362,6 +362,45 @@ void Mutex::Unlock() { 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); diff --git a/runtime/vm/os_thread_fuchsia.h b/runtime/vm/os_thread_fuchsia.h index e17b4a6fb26..8df5cb53fd4 100644 --- a/runtime/vm/os_thread_fuchsia.h +++ b/runtime/vm/os_thread_fuchsia.h @@ -50,11 +50,27 @@ class MutexData { 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() {} diff --git a/runtime/vm/os_thread_linux.cc b/runtime/vm/os_thread_linux.cc index 3543aaa1421..ccaa14a4456 100644 --- a/runtime/vm/os_thread_linux.cc +++ b/runtime/vm/os_thread_linux.cc @@ -370,6 +370,45 @@ void Mutex::Unlock() { 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); diff --git a/runtime/vm/os_thread_linux.h b/runtime/vm/os_thread_linux.h index 9acc2e394fd..e835af4046f 100644 --- a/runtime/vm/os_thread_linux.h +++ b/runtime/vm/os_thread_linux.h @@ -49,11 +49,27 @@ class MutexData { 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() {} diff --git a/runtime/vm/os_thread_macos.cc b/runtime/vm/os_thread_macos.cc index 0d9c8de7b1a..40937c7ec51 100644 --- a/runtime/vm/os_thread_macos.cc +++ b/runtime/vm/os_thread_macos.cc @@ -338,6 +338,35 @@ void Mutex::Unlock() { 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); diff --git a/runtime/vm/os_thread_macos.h b/runtime/vm/os_thread_macos.h index 9b053d0a32b..721aa2e5275 100644 --- a/runtime/vm/os_thread_macos.h +++ b/runtime/vm/os_thread_macos.h @@ -50,11 +50,27 @@ class MutexData { 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() {} diff --git a/runtime/vm/os_thread_win.cc b/runtime/vm/os_thread_win.cc index b884c60d79f..e7d9014d024 100644 --- a/runtime/vm/os_thread_win.cc +++ b/runtime/vm/os_thread_win.cc @@ -278,6 +278,29 @@ void Mutex::Unlock() { 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_); diff --git a/runtime/vm/os_thread_win.h b/runtime/vm/os_thread_win.h index 8e1e917bb7a..25a50d085e7 100644 --- a/runtime/vm/os_thread_win.h +++ b/runtime/vm/os_thread_win.h @@ -47,11 +47,25 @@ class 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() {} diff --git a/sdk/lib/_internal/vm/lib/concurrent_patch.dart b/sdk/lib/_internal/vm/lib/concurrent_patch.dart index ce3e86fe7bd..4c8430909f7 100644 --- a/sdk/lib/_internal/vm/lib/concurrent_patch.dart +++ b/sdk/lib/_internal/vm/lib/concurrent_patch.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import "dart:_internal" show patch; +import "dart:ffi" show Handle, Void, Native; import "dart:nativewrappers" show NativeFieldWrapperClass1; @patch @@ -18,15 +19,15 @@ base class _MutexImpl extends NativeFieldWrapperClass1 implements Mutex { _initialize(); } - @pragma("vm:external-name", "Mutex_Initialize") + @Native(symbol: "Mutex_Initialize") external void _initialize(); @patch - @pragma("vm:external-name", "Mutex_Lock") + @Native(symbol: "Mutex_Lock") external void _lock(); @patch - @pragma("vm:external-name", "Mutex_Unlock") + @Native(symbol: "Mutex_Unlock") external void _unlock(); R runLocked(R Function() action) { @@ -55,14 +56,14 @@ base class _ConditionVariableImpl extends NativeFieldWrapperClass1 _initialize(); } - @pragma("vm:external-name", "ConditionVariable_Initialize") + @Native(symbol: "ConditionVariable_Initialize") external void _initialize(); @patch - @pragma("vm:external-name", "ConditionVariable_Wait") + @Native(symbol: "ConditionVariable_Wait") external void wait(Mutex mutex); @patch - @pragma("vm:external-name", "ConditionVariable_Notify") + @Native(symbol: "ConditionVariable_Notify") external void notify(); }