feabbd99a2
The stub can be invoked from isolategroup-bound code. Also require set experimental-shared-data flag when using IsolateGroup.runSync. TEST=vm/dart/shared_syncstar_test BUG=https://github.com/dart-lang/sdk/issues/61137 Change-Id: I2af27f3f9eeb0dd0dbdfe2e4ec5b162a8e0bd816 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/441260 Reviewed-by: Ryan Macnak <rmacnak@google.com> Commit-Queue: Alexander Aprelev <aam@google.com>
163 lines
5.5 KiB
C++
163 lines
5.5 KiB
C++
// 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/heap/safepoint.h"
|
|
#include "vm/os_thread.h"
|
|
|
|
namespace dart {
|
|
|
|
static void DeleteMutex(void* isolate_data, void* mutex_pointer) {
|
|
delete reinterpret_cast<Mutex*>(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<intptr_t>(mutex));
|
|
if (Dart_IsError(err)) {
|
|
delete mutex;
|
|
Dart_PropagateError(err);
|
|
}
|
|
Dart_NewFinalizableHandle(mutex_handle, mutex, sizeof(Mutex), DeleteMutex);
|
|
};
|
|
|
|
DEFINE_FFI_NATIVE_ENTRY(Mutex_RunLocked,
|
|
Dart_Handle,
|
|
(Dart_Handle mutex_handle,
|
|
Dart_Handle closure_handle)) {
|
|
Mutex* mutex;
|
|
Dart_Handle result = Dart_GetNativeInstanceField(
|
|
mutex_handle, kMutexNativeField, reinterpret_cast<intptr_t*>(&mutex));
|
|
if (Dart_IsError(result)) {
|
|
Dart_PropagateError(result);
|
|
}
|
|
mutex->Lock();
|
|
result = Dart_InvokeClosure(closure_handle, 0, nullptr);
|
|
mutex->Unlock();
|
|
if (Dart_IsError(result)) {
|
|
Dart_PropagateError(result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
static void DeleteConditionVariable(void* isolate_data, void* condvar_pointer) {
|
|
delete reinterpret_cast<ConditionVariable*>(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<intptr_t>(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,
|
|
intptr_t timeout)) {
|
|
Mutex* mutex;
|
|
Dart_Handle result_mutex = Dart_GetNativeInstanceField(
|
|
mutex_handle, kCondVarNativeField, reinterpret_cast<intptr_t*>(&mutex));
|
|
if (Dart_IsError(result_mutex)) {
|
|
Dart_PropagateError(result_mutex);
|
|
}
|
|
ConditionVariable* condvar;
|
|
Dart_Handle result_condvar =
|
|
Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField,
|
|
reinterpret_cast<intptr_t*>(&condvar));
|
|
if (Dart_IsError(result_condvar)) {
|
|
Dart_PropagateError(result_condvar);
|
|
}
|
|
condvar->Wait(mutex, timeout);
|
|
}
|
|
|
|
DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_Notify,
|
|
void,
|
|
(Dart_Handle condvar_handle)) {
|
|
ConditionVariable* condvar;
|
|
Dart_Handle result_condvar =
|
|
Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField,
|
|
reinterpret_cast<intptr_t*>(&condvar));
|
|
if (Dart_IsError(result_condvar)) {
|
|
Dart_PropagateError(result_condvar);
|
|
}
|
|
condvar->Notify();
|
|
}
|
|
|
|
DEFINE_FFI_NATIVE_ENTRY(ConditionVariable_NotifyAll,
|
|
void,
|
|
(Dart_Handle condvar_handle)) {
|
|
ConditionVariable* condvar;
|
|
Dart_Handle result_condvar =
|
|
Dart_GetNativeInstanceField(condvar_handle, kCondVarNativeField,
|
|
reinterpret_cast<intptr_t*>(&condvar));
|
|
if (Dart_IsError(result_condvar)) {
|
|
Dart_PropagateError(result_condvar);
|
|
}
|
|
condvar->NotifyAll();
|
|
}
|
|
|
|
DEFINE_FFI_NATIVE_ENTRY(IsolateGroup_runSync,
|
|
Dart_Handle,
|
|
(Dart_Handle closure)) {
|
|
if (!FLAG_experimental_shared_data) {
|
|
FATAL(
|
|
"Encountered shared data api when functionality is disabled. "
|
|
"Pass --experimental-shared-data");
|
|
}
|
|
|
|
Thread* current_thread = Thread::Current();
|
|
ASSERT(current_thread->execution_state() == Thread::kThreadInNative);
|
|
Isolate* saved_isolate = current_thread->isolate();
|
|
current_thread->ExitSafepointFromNative();
|
|
current_thread->set_execution_state(Thread::kThreadInVM);
|
|
Thread::ExitIsolate(/*isolate_shutdown=*/false);
|
|
|
|
Thread::EnterIsolateGroupAsMutator(current_thread->isolate_group(),
|
|
/*bypass_safepoint=*/false);
|
|
|
|
auto mutator_thread = Thread::Current();
|
|
|
|
ApiState* state = mutator_thread->isolate_group()->api_state();
|
|
ASSERT(state != nullptr);
|
|
mutator_thread->EnterApiScope();
|
|
ASSERT(mutator_thread->execution_state() == Thread::kThreadInVM);
|
|
|
|
Dart_PersistentHandle persistent_result;
|
|
{
|
|
TransitionVMToNative transition(mutator_thread);
|
|
Dart_Handle result = Dart_InvokeClosure(closure, 0, nullptr);
|
|
persistent_result = Dart_NewPersistentHandle(result);
|
|
}
|
|
|
|
mutator_thread->ExitApiScope();
|
|
|
|
Thread::ExitIsolateGroupAsMutator(/*bypass_safepoint=*/false);
|
|
Thread::EnterIsolate(saved_isolate);
|
|
|
|
Thread* T = Thread::Current();
|
|
T->set_execution_state(Thread::kThreadInNative);
|
|
T->EnterSafepoint();
|
|
|
|
Dart_Handle local_handle = Dart_HandleFromPersistent(persistent_result);
|
|
Dart_DeletePersistentHandle(persistent_result);
|
|
return local_handle;
|
|
}
|
|
|
|
} // namespace dart
|