Skip to content

Commit 62b87d7

Browse files
authored
[Web.JS] call mono_wasm_gc_lock in MonoHeapLock (#46909)
Take the runtime's GC lock when creating a heap lock. **Important Notes** 1. While the runtime GC lock is locked, calling any C# function or doing anything that may trigger managed allocation will block the runtime. 2. In a threaded build, only the main browser thread is allowed to call the `mono_wasm_gc_lock` function 3. The runtime lock is not recursive 4. Background threads initially continue running, so the managed object graph may change even while the GC lock is held (although objects may not move). Background threads could mutate valuetype fields of reachable objects, even while the GC lock is held. However background threads will block as soon as they try to do any allocation. 5. The main browser thread may assume that managed heap objects will not move while the lock is held. Corresponding runtime change dotnet/runtime#82646
1 parent b40cc0b commit 62b87d7

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

src/Components/Web.JS/src/Platform/Mono/MonoPlatform.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { BINDINGType, MONOType } from 'dotnet/dotnet-legacy';
1919
export let BINDING: BINDINGType = undefined as any;
2020
export let MONO: MONOType = undefined as any;
2121
export let Module: DotnetModuleConfig & EmscriptenModule = undefined as any;
22+
let MONO_INTERNAL: any = undefined as any;
2223

2324
const uint64HighOrderShift = Math.pow(2, 32);
2425
const maxSafeNumberHighPart = Math.pow(2, 21) - 1; // The high-order int32 from Number.MAX_SAFE_INTEGER
@@ -146,7 +147,7 @@ export const monoPlatform: Platform = {
146147

147148
beginHeapLock: function beginHeapLock() {
148149
assertHeapIsNotLocked();
149-
currentHeapLock = new MonoHeapLock();
150+
currentHeapLock = MonoHeapLock.create();
150151
return currentHeapLock;
151152
},
152153

@@ -358,10 +359,11 @@ async function createRuntimeInstance(resourceLoader: WebAssemblyResourceLoader):
358359
(dotnet as any).withModuleConfig(moduleConfig);
359360

360361
const runtime = await dotnet.create();
361-
const { MONO: mono, BINDING: binding, Module: module, setModuleImports } = runtime;
362+
const { MONO: mono, BINDING: binding, Module: module, setModuleImports, INTERNAL: mono_internal } = runtime;
362363
Module = module;
363364
BINDING = binding;
364365
MONO = mono;
366+
MONO_INTERNAL = mono_internal;
365367

366368
Blazor._internal.dotNetCriticalError = printErr;
367369
Blazor._internal.loadLazyAssembly = (assemblyNameToLoad) => loadLazyAssembly(resourceLoader, assemblyNameToLoad);
@@ -568,6 +570,8 @@ class MonoHeapLock implements HeapLock {
568570
throw new Error('Trying to release a lock which isn\'t current');
569571
}
570572

573+
MONO_INTERNAL.mono_wasm_gc_unlock();
574+
571575
currentHeapLock = null;
572576

573577
while (this.postReleaseActions?.length) {
@@ -580,4 +584,9 @@ class MonoHeapLock implements HeapLock {
580584
assertHeapIsNotLocked();
581585
}
582586
}
587+
588+
static create(): MonoHeapLock {
589+
MONO_INTERNAL.mono_wasm_gc_lock();
590+
return new MonoHeapLock();
591+
}
583592
}

0 commit comments

Comments
 (0)