Skip to content

[wasm] Add an internal GC lock API #82646

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Mar 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/mono/mono/metadata/sgen-stw.c
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@
#include "metadata/gc-internals.h"
#include "utils/mono-threads.h"
#include "utils/mono-threads-debug.h"
#ifdef HOST_BROWSER
#include <emscripten.h>
#include <mono/utils/mono-threads-wasm.h>
#endif

#if _MSC_VER
#pragma warning(disable:4312) // FIXME pointer cast to different size
Expand Down Expand Up @@ -485,4 +489,42 @@ mono_restart_world (MonoThreadInfoFlags flags)
release_gc_locks ();
UNLOCK_GC;
}

#ifdef HOST_BROWSER

EMSCRIPTEN_KEEPALIVE void mono_wasm_gc_lock(void);
EMSCRIPTEN_KEEPALIVE void mono_wasm_gc_unlock(void);

/* Allow the main thread to take the GC lock from JS */
EMSCRIPTEN_KEEPALIVE
void
mono_wasm_gc_lock(void)
{
MONO_ENTER_GC_UNSAFE;
#ifndef DISABLE_THREADS
/* only the browser thread is allowed to take the GC lock */
g_assert (mono_threads_wasm_is_browser_thread ());
LOCK_GC;
acquire_gc_locks();
#else
g_assert_not_reached ();
#endif
MONO_EXIT_GC_UNSAFE;
}

EMSCRIPTEN_KEEPALIVE
void
mono_wasm_gc_unlock(void)
{
MONO_ENTER_GC_UNSAFE;
#ifndef DISABLE_THREADS
release_gc_locks();
UNLOCK_GC;
#else
g_assert_not_reached ();
#endif
MONO_EXIT_GC_UNSAFE;
}
#endif /* HOST_BROWSER */

#endif
4 changes: 4 additions & 0 deletions src/mono/wasm/runtime/cwraps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ const fn_signatures: SigLine[] = [
[true, "mono_wasm_f64_to_u52", "number", ["number", "number"]],
[true, "mono_wasm_method_get_name", "number", ["number"]],
[true, "mono_wasm_method_get_full_name", "number", ["number"]],
[true, "mono_wasm_gc_lock", "void", []],
[true, "mono_wasm_gc_unlock", "void", []],

// jiterpreter
[true, "mono_jiterp_get_trace_bailout_count", "number", ["number"]],
Expand Down Expand Up @@ -239,6 +241,8 @@ export interface t_Cwraps {
mono_wasm_runtime_run_module_cctor(assembly: MonoAssembly): void;
mono_wasm_method_get_name(method: MonoMethod): CharPtr;
mono_wasm_method_get_full_name(method: MonoMethod): CharPtr;
mono_wasm_gc_lock(): void;
mono_wasm_gc_unlock(): void;

mono_jiterp_get_trace_bailout_count(reason: number): number;
mono_jiterp_value_copy(destination: VoidPtr, source: VoidPtr, klass: MonoClass): void;
Expand Down
7 changes: 6 additions & 1 deletion src/mono/wasm/runtime/exports-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { ws_wasm_create, ws_wasm_open, ws_wasm_send, ws_wasm_receive, ws_wasm_cl
import { mono_wasm_get_loaded_files } from "./assets";
import { jiterpreter_dump_stats } from "./jiterpreter";
import { getOptions, applyOptions } from "./jiterpreter-support";
import { mono_wasm_gc_lock, mono_wasm_gc_unlock } from "./gc-lock";

export function export_internal(): any {
return {
Expand Down Expand Up @@ -80,7 +81,11 @@ export function export_internal(): any {
// jiterpreter
jiterpreter_dump_stats,
jiterpreter_apply_options: applyOptions,
jiterpreter_get_options: getOptions
jiterpreter_get_options: getOptions,

// Blazor GC Lock support
mono_wasm_gc_lock,
mono_wasm_gc_unlock,
};
}

Expand Down
31 changes: 31 additions & 0 deletions src/mono/wasm/runtime/gc-lock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import MonoWasmThreads from "consts:monoWasmThreads";
import { ENVIRONMENT_IS_PTHREAD } from "./imports";
import cwraps from "./cwraps";

let locked = false;

export function mono_wasm_gc_lock(): void {
if (locked) {
throw new Error("GC is already locked");
}
if (MonoWasmThreads) {
if (ENVIRONMENT_IS_PTHREAD) {
throw new Error("GC lock only supported in main thread");
}
cwraps.mono_wasm_gc_lock();
}
locked = true;
}

export function mono_wasm_gc_unlock(): void {
if (!locked) {
throw new Error("GC is not locked");
}
if (MonoWasmThreads) {
if (ENVIRONMENT_IS_PTHREAD) {
throw new Error("GC lock only supported in main thread");
}
cwraps.mono_wasm_gc_unlock();
}
locked = false;
}