From 3f030a1c989dfbe463b4b9c7513606cc511fe9ed Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Mon, 25 Mar 2024 20:49:47 +0100 Subject: [PATCH 1/6] use simpler `mono_wasm_schedule_synchronization_context` instead of `schedule_background_exec` makes scheduling.ts ST only --- .../src/Interop/Browser/Interop.Runtime.cs | 2 +- .../JavaScript/JSSynchronizationContext.cs | 11 +-- src/mono/browser/runtime/corebindings.c | 6 +- src/mono/browser/runtime/cwraps.ts | 2 + src/mono/browser/runtime/driver.c | 7 ++ src/mono/browser/runtime/exports-binding.ts | 2 + src/mono/browser/runtime/pthreads/shared.ts | 13 ++++ src/mono/browser/runtime/scheduling.ts | 33 +++------ src/mono/mono/mini/mini-wasm.c | 5 +- src/mono/mono/utils/mono-threads-wasm.c | 69 ++++--------------- src/mono/mono/utils/mono-threads-wasm.h | 1 - src/mono/mono/utils/mono-threads.c | 12 ---- src/mono/mono/utils/mono-threads.h | 3 +- 13 files changed, 61 insertions(+), 105 deletions(-) diff --git a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs index 53e3fc148a46e..f298e9694f506 100644 --- a/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs +++ b/src/libraries/Common/src/Interop/Browser/Interop.Runtime.cs @@ -42,7 +42,7 @@ internal static unsafe partial class Runtime #if FEATURE_WASM_MANAGED_THREADS [MethodImpl(MethodImplOptions.InternalCall)] - public static extern void InstallWebWorkerInterop(nint proxyContextGCHandle, void* beforeSyncJSImport, void* afterSyncJSImport); + public static extern void InstallWebWorkerInterop(nint proxyContextGCHandle, void* beforeSyncJSImport, void* afterSyncJSImport, void* pumpHandler); [MethodImpl(MethodImplOptions.InternalCall)] public static extern void UninstallWebWorkerInterop(); diff --git a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs index f967540d45079..2a2ff0f6f0222 100644 --- a/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs +++ b/src/libraries/System.Runtime.InteropServices.JavaScript/src/System/Runtime/InteropServices/JavaScript/JSSynchronizationContext.cs @@ -68,7 +68,8 @@ public static unsafe JSSynchronizationContext InstallWebWorkerInterop(bool isMai Interop.Runtime.InstallWebWorkerInterop(proxyContext.ContextHandle, (delegate* unmanaged[Cdecl])&JavaScriptExports.BeforeSyncJSExport, - (delegate* unmanaged[Cdecl])&JavaScriptExports.AfterSyncJSExport); + (delegate* unmanaged[Cdecl])&JavaScriptExports.AfterSyncJSExport, + (delegate* unmanaged[Cdecl])&PumpHandler); return ctx; } @@ -170,7 +171,7 @@ private unsafe void ScheduleJSPump() { // While we COULD pump here, we don't want to. We want the pump to happen on the next event loop turn. // Otherwise we could get a chain where a pump generates a new work item and that makes us pump again, forever. - TargetThreadScheduleBackgroundJob(ProxyContext.NativeTID, (delegate* unmanaged[Cdecl])&BackgroundJobHandler); + ScheduleSynchronizationContext(ProxyContext.NativeTID); } public override void Post(SendOrPostCallback d, object? state) @@ -236,13 +237,13 @@ public override void Send(SendOrPostCallback d, object? state) } [MethodImplAttribute(MethodImplOptions.InternalCall)] - internal static extern unsafe void TargetThreadScheduleBackgroundJob(IntPtr targetTID, void* callback); + internal static extern unsafe void ScheduleSynchronizationContext(IntPtr targetTID); #pragma warning disable CS3016 // Arrays as attribute arguments is not CLS-compliant [UnmanagedCallersOnly(CallConvs = new[] { typeof(CallConvCdecl) })] #pragma warning restore CS3016 // this callback will arrive on the target thread, called from mono_background_exec - private static void BackgroundJobHandler() + private static void PumpHandler() { var ctx = JSProxyContext.AssertIsInteropThread(); ctx.SynchronizationContext.Pump(); @@ -286,7 +287,7 @@ private void Pump() } catch (Exception e) { - Environment.FailFast($"JSSynchronizationContext.BackgroundJobHandler failed, ManagedThreadId: {Environment.CurrentManagedThreadId}. {Environment.NewLine} {e.StackTrace}"); + Environment.FailFast($"JSSynchronizationContext.Pump failed, ManagedThreadId: {Environment.CurrentManagedThreadId}. {Environment.NewLine} {e.StackTrace}"); } } diff --git a/src/mono/browser/runtime/corebindings.c b/src/mono/browser/runtime/corebindings.c index b2a271b4e91eb..416b0d257d01a 100644 --- a/src/mono/browser/runtime/corebindings.c +++ b/src/mono/browser/runtime/corebindings.c @@ -42,7 +42,7 @@ void mono_wasm_resolve_or_reject_promise_post (pthread_t target_tid, void *args) void mono_wasm_cancel_promise_post (pthread_t target_tid, int task_holder_gc_handle); extern void mono_wasm_install_js_worker_interop (int context_gc_handle); -void mono_wasm_install_js_worker_interop_wrapper (int context_gc_handle, void* beforeSyncJSImport, void* afterSyncJSImport); +void mono_wasm_install_js_worker_interop_wrapper (int context_gc_handle, void* beforeSyncJSImport, void* afterSyncJSImport, void* pumpHandler); extern void mono_wasm_uninstall_js_worker_interop (); extern void mono_wasm_invoke_jsimport_MT (void* signature, void* args); void mono_wasm_invoke_jsimport_async_post (pthread_t target_tid, void* signature, void* args); @@ -256,11 +256,13 @@ void mono_wasm_get_assembly_export (char *assembly_name, char *namespace, char * void* before_sync_js_import; void* after_sync_js_import; +void* synchronization_context_pump_handler; -void mono_wasm_install_js_worker_interop_wrapper (int context_gc_handle, void* beforeSyncJSImport, void* afterSyncJSImport) +void mono_wasm_install_js_worker_interop_wrapper (int context_gc_handle, void* beforeSyncJSImport, void* afterSyncJSImport, void* pumpHandler) { before_sync_js_import = beforeSyncJSImport; after_sync_js_import = afterSyncJSImport; + synchronization_context_pump_handler = pumpHandler; mono_wasm_install_js_worker_interop (context_gc_handle); } diff --git a/src/mono/browser/runtime/cwraps.ts b/src/mono/browser/runtime/cwraps.ts index ca10e3d35ff6c..7be56846ac97e 100644 --- a/src/mono/browser/runtime/cwraps.ts +++ b/src/mono/browser/runtime/cwraps.ts @@ -33,6 +33,7 @@ const threading_cwraps: SigLine[] = WasmEnableThreads ? [ [true, "mono_wasm_register_ui_thread", "void", []], [true, "mono_wasm_register_io_thread", "void", []], [true, "mono_wasm_print_thread_dump", "void", []], + [true, "mono_wasm_synchronization_context_pump", "void", []], [true, "mono_threads_wasm_sync_run_in_target_thread_done", "void", ["number"]], ] : []; @@ -157,6 +158,7 @@ export interface t_ThreadingCwraps { mono_wasm_register_ui_thread(): void; mono_wasm_register_io_thread(): void; mono_wasm_print_thread_dump(): void; + mono_wasm_synchronization_context_pump(): void; mono_threads_wasm_sync_run_in_target_thread_done(sem: VoidPtr): void; } diff --git a/src/mono/browser/runtime/driver.c b/src/mono/browser/runtime/driver.c index 6816642a48b2a..f231a86119e7e 100644 --- a/src/mono/browser/runtime/driver.c +++ b/src/mono/browser/runtime/driver.c @@ -287,8 +287,10 @@ mono_wasm_invoke_jsexport_async_post (void* target_thread, MonoMethod *method, v typedef void (*js_interop_event)(void* args); +typedef void (*sync_context_pump)(void); extern js_interop_event before_sync_js_import; extern js_interop_event after_sync_js_import; +extern sync_context_pump synchronization_context_pump_handler; // this is running on the target thread EMSCRIPTEN_KEEPALIVE void @@ -306,6 +308,11 @@ mono_wasm_invoke_jsexport_sync_send (void* target_thread, MonoMethod *method, vo mono_threads_wasm_sync_run_in_target_thread_vii (target_thread, (void (*)(gpointer, gpointer))mono_wasm_invoke_jsexport_sync, method, args); } +EMSCRIPTEN_KEEPALIVE void mono_wasm_synchronization_context_pump (void) +{ + synchronization_context_pump_handler (); +} + #endif /* DISABLE_THREADS */ EMSCRIPTEN_KEEPALIVE void diff --git a/src/mono/browser/runtime/exports-binding.ts b/src/mono/browser/runtime/exports-binding.ts index bb88ac3b65fbb..66bc441a25cc5 100644 --- a/src/mono/browser/runtime/exports-binding.ts +++ b/src/mono/browser/runtime/exports-binding.ts @@ -32,6 +32,7 @@ import { mono_wasm_pthread_on_pthread_registered, mono_wasm_pthread_set_name, mono_wasm_install_js_worker_interop, mono_wasm_uninstall_js_worker_interop, mono_wasm_start_io_thread_async } from "./pthreads"; import { mono_wasm_dump_threads } from "./pthreads/ui-thread"; +import { mono_wasm_schedule_synchronization_context } from "./pthreads/shared"; // the JS methods would be visible to EMCC linker and become imports of the WASM module @@ -44,6 +45,7 @@ export const mono_wasm_threads_imports = !WasmEnableThreads ? [] : [ mono_wasm_pthread_set_name, mono_wasm_start_deputy_thread_async, mono_wasm_start_io_thread_async, + mono_wasm_schedule_synchronization_context, // mono-threads.c mono_wasm_dump_threads, diff --git a/src/mono/browser/runtime/pthreads/shared.ts b/src/mono/browser/runtime/pthreads/shared.ts index c83eb3b967e03..07fd3ab0a79a7 100644 --- a/src/mono/browser/runtime/pthreads/shared.ts +++ b/src/mono/browser/runtime/pthreads/shared.ts @@ -11,6 +11,7 @@ import { set_thread_prefix } from "../logging"; import { bindings_init } from "../startup"; import { forceDisposeProxies } from "../gc-handles"; import { monoMessageSymbol, GCHandleNull, PThreadPtrNull, WorkerToMainMessageType } from "../types/internal"; +import { threads_c_functions as tcwraps } from "../cwraps"; // A duplicate in loader/assets.ts export const worker_empty_prefix = " - "; @@ -106,6 +107,18 @@ export function update_thread_info(): void { } } +export function exec_synchronization_context_pump(): void { + if (!loaderHelpers.is_runtime_running()) { + return; + } + tcwraps.mono_wasm_synchronization_context_pump(); +} + +export function mono_wasm_schedule_synchronization_context(): void { + if (!WasmEnableThreads) return; + Module.safeSetTimeout(exec_synchronization_context_pump, 0); +} + export function mono_wasm_pthread_ptr(): PThreadPtr { if (!WasmEnableThreads) return PThreadPtrNull; return (Module)["_pthread_self"](); diff --git a/src/mono/browser/runtime/scheduling.ts b/src/mono/browser/runtime/scheduling.ts index c9cbf205d42d4..f7c0580eff4a1 100644 --- a/src/mono/browser/runtime/scheduling.ts +++ b/src/mono/browser/runtime/scheduling.ts @@ -4,14 +4,14 @@ import WasmEnableThreads from "consts:wasmEnableThreads"; import cwraps from "./cwraps"; -import { ENVIRONMENT_IS_WORKER, Module, loaderHelpers } from "./globals"; +import { Module, loaderHelpers } from "./globals"; import { forceThreadMemoryViewRefresh } from "./memory"; -import { is_thread_available } from "./pthreads"; let spread_timers_maximum = 0; let pump_count = 0; export function prevent_timer_throttling(): void { + if (WasmEnableThreads) return; if (!loaderHelpers.isChromium) { return; } @@ -30,26 +30,22 @@ export function prevent_timer_throttling(): void { } function prevent_timer_throttling_tick() { + if (WasmEnableThreads) return; Module.maybeExit(); if (!loaderHelpers.is_runtime_running()) { return; } - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } cwraps.mono_wasm_execute_timer(); pump_count++; mono_background_exec_until_done(); } function mono_background_exec_until_done() { + if (WasmEnableThreads) return; Module.maybeExit(); if (!loaderHelpers.is_runtime_running()) { return; } - if (WasmEnableThreads) { - forceThreadMemoryViewRefresh(); - } while (pump_count > 0) { --pump_count; cwraps.mono_background_exec(); @@ -57,28 +53,14 @@ function mono_background_exec_until_done() { } export function schedule_background_exec(): void { + if (WasmEnableThreads) return; ++pump_count; - let max_postpone_count = 10; - function postpone_schedule_background() { - if (max_postpone_count < 0 || is_thread_available()) { - Module.safeSetTimeout(mono_background_exec_until_done, 0); - } else { - max_postpone_count--; - Module.safeSetTimeout(postpone_schedule_background, 10); - } - } - - if (WasmEnableThreads && !ENVIRONMENT_IS_WORKER) { - // give threads chance to load before we run more synchronous code on UI thread - postpone_schedule_background(); - } - else { - Module.safeSetTimeout(mono_background_exec_until_done, 0); - } + Module.safeSetTimeout(mono_background_exec_until_done, 0); } let lastScheduledTimeoutId: any = undefined; export function mono_wasm_schedule_timer(shortestDueTimeMs: number): void { + if (WasmEnableThreads) return; if (lastScheduledTimeoutId) { globalThis.clearTimeout(lastScheduledTimeoutId); lastScheduledTimeoutId = undefined; @@ -91,6 +73,7 @@ export function mono_wasm_schedule_timer(shortestDueTimeMs: number): void { } function mono_wasm_schedule_timer_tick() { + if (WasmEnableThreads) return; Module.maybeExit(); if (WasmEnableThreads) { forceThreadMemoryViewRefresh(); diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index 991135288f63d..d2a2ef9d88c7e 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -447,7 +447,10 @@ G_BEGIN_DECLS EMSCRIPTEN_KEEPALIVE void mono_wasm_execute_timer (void); //JS functions imported that we use +#ifdef DISABLE_THREADS extern void mono_wasm_schedule_timer (int shortestDueTimeMs); +extern void mono_target_thread_schedule_synchronization_context(MonoNativeThreadId target_thread); +#endif // DISABLE_THREADS G_END_DECLS void mono_background_exec (void); @@ -626,7 +629,7 @@ mono_arch_register_icall (void) mono_add_internal_call_internal ("System.Threading.TimerQueue::MainThreadScheduleTimer", mono_wasm_main_thread_schedule_timer); mono_add_internal_call_internal ("System.Threading.ThreadPool::MainThreadScheduleBackgroundJob", mono_main_thread_schedule_background_job); #else - mono_add_internal_call_internal ("System.Runtime.InteropServices.JavaScript.JSSynchronizationContext::TargetThreadScheduleBackgroundJob", mono_target_thread_schedule_background_job); + mono_add_internal_call_internal ("System.Runtime.InteropServices.JavaScript.JSSynchronizationContext::ScheduleSynchronizationContext", mono_target_thread_schedule_synchronization_context); #endif /* DISABLE_THREADS */ #endif /* HOST_BROWSER */ } diff --git a/src/mono/mono/utils/mono-threads-wasm.c b/src/mono/mono/utils/mono-threads-wasm.c index 8ba904a5f6a0f..597592a7966c6 100644 --- a/src/mono/mono/utils/mono-threads-wasm.c +++ b/src/mono/mono/utils/mono-threads-wasm.c @@ -346,7 +346,6 @@ G_EXTERN_C extern void schedule_background_exec (void); // when this is called from ThreadPool, the cb would be System.Threading.ThreadPool.BackgroundJobHandler -// when this is called from JSSynchronizationContext, the cb would be System.Runtime.InteropServices.JavaScript.JSSynchronizationContext.BackgroundJobHandler // when this is called from sgen it would be wrapper of sgen_perform_collection_inner // when this is called from gc, it would be mono_runtime_do_background_work #ifdef DISABLE_THREADS @@ -354,77 +353,24 @@ void mono_main_thread_schedule_background_job (background_job_cb cb) { g_assert (cb); - THREADS_DEBUG ("mono_main_thread_schedule_background_job2: thread %p queued job %p to current thread\n", (gpointer)pthread_self(), (gpointer) cb); - mono_current_thread_schedule_background_job (cb); -} -#endif /*DISABLE_THREADS*/ - -#ifndef DISABLE_THREADS -MonoNativeTlsKey jobs_key; -#else /* DISABLE_THREADS */ -GSList *jobs; -#endif /* DISABLE_THREADS */ - -void -mono_current_thread_schedule_background_job (background_job_cb cb) -{ - g_assert (cb); -#ifdef DISABLE_THREADS + THREADS_DEBUG ("mono_main_thread_schedule_background_job: thread %p queued job %p to current thread\n", (gpointer)pthread_self(), (gpointer) cb); if (!jobs) schedule_background_exec (); if (!g_slist_find (jobs, (gconstpointer)cb)) jobs = g_slist_prepend (jobs, (gpointer)cb); - -#else /*DISABLE_THREADS*/ - - GSList *jobs = mono_native_tls_get_value (jobs_key); - THREADS_DEBUG ("mono_current_thread_schedule_background_job1: thread %p queuing job %p into %p\n", (gpointer)pthread_self(), (gpointer) cb, (gpointer) jobs); - if (!jobs) - { - THREADS_DEBUG ("mono_current_thread_schedule_background_job2: thread %p calling schedule_background_exec before job %p\n", (gpointer)pthread_self(), (gpointer) cb); - schedule_background_exec (); - } - - if (!g_slist_find (jobs, (gconstpointer)cb)) - { - jobs = g_slist_prepend (jobs, (gpointer)cb); - mono_native_tls_set_value (jobs_key, jobs); - THREADS_DEBUG ("mono_current_thread_schedule_background_job3: thread %p queued job %p\n", (gpointer)pthread_self(), (gpointer) cb); - } - -#endif /*DISABLE_THREADS*/ } -#ifndef DISABLE_THREADS -void -mono_target_thread_schedule_background_job (MonoNativeThreadId target_thread, background_job_cb cb) -{ - THREADS_DEBUG ("worker %p queued job %p to worker %p \n", (gpointer)pthread_self(), (gpointer) cb, (gpointer) target_thread); - // NOTE: here the cb is [UnmanagedCallersOnly] which wraps it with MONO_ENTER_GC_UNSAFE/MONO_EXIT_GC_UNSAFE - mono_threads_wasm_async_run_in_target_thread_vi ((pthread_t) target_thread, (void*)mono_current_thread_schedule_background_job, (gpointer)cb); -} -#endif /*DISABLE_THREADS*/ - -G_EXTERN_C -EMSCRIPTEN_KEEPALIVE void -mono_background_exec (void); +GSList *jobs; G_EXTERN_C EMSCRIPTEN_KEEPALIVE void mono_background_exec (void) { MONO_ENTER_GC_UNSAFE; -#ifdef DISABLE_THREADS GSList *j = jobs, *cur; jobs = NULL; -#else /* DISABLE_THREADS */ - THREADS_DEBUG ("mono_background_exec on thread %p started\n", (gpointer)pthread_self()); - GSList *jobs = mono_native_tls_get_value (jobs_key); - GSList *j = jobs, *cur; - mono_native_tls_set_value (jobs_key, NULL); -#endif /* DISABLE_THREADS */ for (cur = j; cur; cur = cur->next) { background_job_cb cb = (background_job_cb)cur->data; @@ -437,6 +383,17 @@ mono_background_exec (void) MONO_EXIT_GC_UNSAFE; } +#else /*DISABLE_THREADS*/ + +extern void mono_wasm_schedule_synchronization_context (); + +void mono_target_thread_schedule_synchronization_context(MonoNativeThreadId target_thread) +{ + emscripten_dispatch_to_thread_async ((pthread_t) target_thread, EM_FUNC_SIG_V, mono_wasm_schedule_synchronization_context, NULL); +} + +#endif /*DISABLE_THREADS*/ + gboolean mono_threads_platform_is_main_thread (void) { diff --git a/src/mono/mono/utils/mono-threads-wasm.h b/src/mono/mono/utils/mono-threads-wasm.h index 08cc690673df1..41d9524b479ce 100644 --- a/src/mono/mono/utils/mono-threads-wasm.h +++ b/src/mono/mono/utils/mono-threads-wasm.h @@ -87,7 +87,6 @@ mono_wasm_atomic_wait_i32 (volatile int32_t *addr, int32_t expected, int32_t tim return __builtin_wasm_memory_atomic_wait32((int32_t*)addr, expected, timeout_ns); } -extern MonoNativeTlsKey jobs_key; #else /* DISABLE_THREADS */ extern GSList *jobs; #endif /* DISABLE_THREADS */ diff --git a/src/mono/mono/utils/mono-threads.c b/src/mono/mono/utils/mono-threads.c index 14a00bc915429..144feb3887877 100644 --- a/src/mono/mono/utils/mono-threads.c +++ b/src/mono/mono/utils/mono-threads.c @@ -523,12 +523,6 @@ register_thread (MonoThreadInfo *info) g_assert (staddr); #endif /* TARGET_WASM */ -#ifdef HOST_WASM -#ifndef DISABLE_THREADS - mono_native_tls_set_value (jobs_key, NULL); -#endif /* DISABLE_THREADS */ -#endif /* HOST_WASM */ - g_assert (stsize); info->stack_start_limit = staddr; info->stack_end = staddr + stsize; @@ -979,12 +973,6 @@ mono_thread_info_init (size_t info_size) mono_threads_suspend_policy_init (); -#ifdef HOST_WASM -#ifndef DISABLE_THREADS - res = mono_native_tls_alloc (&jobs_key, NULL); -#endif /* DISABLE_THREADS */ -#endif /* HOST_BROWSER */ - #ifdef HOST_WIN32 res = mono_native_tls_alloc (&thread_info_key, NULL); res = mono_native_tls_alloc (&thread_exited_key, NULL); diff --git a/src/mono/mono/utils/mono-threads.h b/src/mono/mono/utils/mono-threads.h index 08db699e1d605..014c9bd75db62 100644 --- a/src/mono/mono/utils/mono-threads.h +++ b/src/mono/mono/utils/mono-threads.h @@ -848,8 +848,7 @@ typedef void (*background_job_cb)(void); #ifdef DISABLE_THREADS void mono_main_thread_schedule_background_job (background_job_cb cb); #endif // DISABLE_THREADS -void mono_current_thread_schedule_background_job (background_job_cb cb); -void mono_target_thread_schedule_background_job (MonoNativeThreadId target_thread, background_job_cb cb); +void mono_target_thread_schedule_synchronization_context(MonoNativeThreadId target_thread); #endif #ifdef USE_WINDOWS_BACKEND From e65037c6e8d2510ac7f1e3a45038e4558610ab00 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 26 Mar 2024 14:51:48 +0100 Subject: [PATCH 2/6] fix --- src/mono/mono/mini/mini-wasm.c | 3 +-- src/mono/mono/utils/mono-threads.h | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index d2a2ef9d88c7e..c6ef022dca0e9 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -445,6 +445,7 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe //functions exported to be used by JS G_BEGIN_DECLS EMSCRIPTEN_KEEPALIVE void mono_wasm_execute_timer (void); +EMSCRIPTEN_KEEPALIVE void mono_background_exec (void); //JS functions imported that we use #ifdef DISABLE_THREADS @@ -453,8 +454,6 @@ extern void mono_target_thread_schedule_synchronization_context(MonoNativeThread #endif // DISABLE_THREADS G_END_DECLS -void mono_background_exec (void); - #endif // HOST_BROWSER gpointer diff --git a/src/mono/mono/utils/mono-threads.h b/src/mono/mono/utils/mono-threads.h index 014c9bd75db62..8410e43ef9301 100644 --- a/src/mono/mono/utils/mono-threads.h +++ b/src/mono/mono/utils/mono-threads.h @@ -847,8 +847,9 @@ void mono_threads_join_unlock (void); typedef void (*background_job_cb)(void); #ifdef DISABLE_THREADS void mono_main_thread_schedule_background_job (background_job_cb cb); -#endif // DISABLE_THREADS +#else void mono_target_thread_schedule_synchronization_context(MonoNativeThreadId target_thread); +#endif // DISABLE_THREADS #endif #ifdef USE_WINDOWS_BACKEND From 14d13a66b6807c6f2d07763167b6650d1a82b914 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Tue, 26 Mar 2024 16:05:23 +0100 Subject: [PATCH 3/6] more --- src/mono/mono/mini/mini-wasm.c | 5 +++-- src/mono/mono/mini/mini-wasm.h | 8 ++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index c6ef022dca0e9..3d952cd59579a 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -444,12 +444,13 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe //functions exported to be used by JS G_BEGIN_DECLS -EMSCRIPTEN_KEEPALIVE void mono_wasm_execute_timer (void); -EMSCRIPTEN_KEEPALIVE void mono_background_exec (void); //JS functions imported that we use #ifdef DISABLE_THREADS +EMSCRIPTEN_KEEPALIVE void mono_wasm_execute_timer (void); +EMSCRIPTEN_KEEPALIVE void mono_background_exec (void); extern void mono_wasm_schedule_timer (int shortestDueTimeMs); +#else extern void mono_target_thread_schedule_synchronization_context(MonoNativeThreadId target_thread); #endif // DISABLE_THREADS G_END_DECLS diff --git a/src/mono/mono/mini/mini-wasm.h b/src/mono/mono/mini/mini-wasm.h index 77c7f3a78fa5c..7995a446d236c 100644 --- a/src/mono/mono/mini/mini-wasm.h +++ b/src/mono/mono/mini/mini-wasm.h @@ -100,11 +100,19 @@ typedef struct { // sdks/wasm/driver.c is C and uses this G_EXTERN_C void mono_wasm_enable_debugging (int log_level); +#ifdef HOST_BROWSER + +//JS functions imported that we use #ifdef DISABLE_THREADS +void mono_wasm_execute_timer (void); +void mono_background_exec (void); void mono_wasm_main_thread_schedule_timer (void *timerHandler, int shortestDueTimeMs); #endif // DISABLE_THREADS void mono_wasm_print_stack_trace (void); +#endif // HOST_BROWSER + + gboolean mini_wasm_is_scalar_vtype (MonoType *type, MonoType **etype); From 8f7e8ecc6c0cf75be6b11b0a449d56b9bfa36ea7 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Tue, 26 Mar 2024 19:41:25 +0000 Subject: [PATCH 4/6] fix --- src/mono/mono/mini/mini-wasm.h | 1 - src/mono/mono/utils/mono-threads-wasm.h | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-wasm.h b/src/mono/mono/mini/mini-wasm.h index 7995a446d236c..95bafda3336c0 100644 --- a/src/mono/mono/mini/mini-wasm.h +++ b/src/mono/mono/mini/mini-wasm.h @@ -105,7 +105,6 @@ G_EXTERN_C void mono_wasm_enable_debugging (int log_level); //JS functions imported that we use #ifdef DISABLE_THREADS void mono_wasm_execute_timer (void); -void mono_background_exec (void); void mono_wasm_main_thread_schedule_timer (void *timerHandler, int shortestDueTimeMs); #endif // DISABLE_THREADS diff --git a/src/mono/mono/utils/mono-threads-wasm.h b/src/mono/mono/utils/mono-threads-wasm.h index 41d9524b479ce..927c5b0eb0ea5 100644 --- a/src/mono/mono/utils/mono-threads-wasm.h +++ b/src/mono/mono/utils/mono-threads-wasm.h @@ -89,6 +89,7 @@ mono_wasm_atomic_wait_i32 (volatile int32_t *addr, int32_t expected, int32_t tim #else /* DISABLE_THREADS */ extern GSList *jobs; +void mono_background_exec (void); #endif /* DISABLE_THREADS */ void From e6df192fc229298c90df08bdcd2897a4012c27f6 Mon Sep 17 00:00:00 2001 From: Pavel Savara Date: Wed, 27 Mar 2024 08:31:26 +0100 Subject: [PATCH 5/6] fix --- src/mono/mono/mini/mini-wasm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/mini-wasm.c b/src/mono/mono/mini/mini-wasm.c index 3d952cd59579a..db7c8b2de39a6 100644 --- a/src/mono/mono/mini/mini-wasm.c +++ b/src/mono/mono/mini/mini-wasm.c @@ -591,6 +591,8 @@ mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo return FALSE; } +#ifdef DISABLE_THREADS + // this points to System.Threading.TimerQueue.TimerHandler C# method static void *timer_handler; @@ -608,7 +610,6 @@ mono_wasm_execute_timer (void) MONO_EXIT_GC_UNSAFE; } -#ifdef DISABLE_THREADS void mono_wasm_main_thread_schedule_timer (void *timerHandler, int shortestDueTimeMs) { From 326c29a14aa6ef46df2c4c44bcd6c2dfc493b756 Mon Sep 17 00:00:00 2001 From: pavelsavara Date: Wed, 27 Mar 2024 18:54:42 +0100 Subject: [PATCH 6/6] more --- src/mono/browser/runtime/pthreads/deputy-thread.ts | 2 ++ src/mono/browser/runtime/pthreads/shared.ts | 2 ++ src/mono/browser/runtime/scheduling.ts | 4 ---- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/mono/browser/runtime/pthreads/deputy-thread.ts b/src/mono/browser/runtime/pthreads/deputy-thread.ts index bb032c2479c0d..4b514b28a4aed 100644 --- a/src/mono/browser/runtime/pthreads/deputy-thread.ts +++ b/src/mono/browser/runtime/pthreads/deputy-thread.ts @@ -9,6 +9,7 @@ import { monoThreadInfo, postMessageToMain, update_thread_info } from "./shared" import { Module, loaderHelpers, runtimeHelpers } from "../globals"; import { start_runtime } from "../startup"; import { WorkerToMainMessageType } from "../types/internal"; +import { forceThreadMemoryViewRefresh } from "../memory"; export function mono_wasm_start_deputy_thread_async () { if (!WasmEnableThreads) return; @@ -28,6 +29,7 @@ export function mono_wasm_start_deputy_thread_async () { Module.runtimeKeepalivePush(); Module.safeSetTimeout(async () => { try { + forceThreadMemoryViewRefresh(); await start_runtime(); diff --git a/src/mono/browser/runtime/pthreads/shared.ts b/src/mono/browser/runtime/pthreads/shared.ts index fec3db05881a4..f72804fbcf873 100644 --- a/src/mono/browser/runtime/pthreads/shared.ts +++ b/src/mono/browser/runtime/pthreads/shared.ts @@ -12,6 +12,7 @@ import { bindings_init } from "../startup"; import { forceDisposeProxies } from "../gc-handles"; import { monoMessageSymbol, GCHandleNull, PThreadPtrNull, WorkerToMainMessageType } from "../types/internal"; import { threads_c_functions as tcwraps } from "../cwraps"; +import { forceThreadMemoryViewRefresh } from "../memory"; // A duplicate in loader/assets.ts export const worker_empty_prefix = " - "; @@ -110,6 +111,7 @@ export function exec_synchronization_context_pump (): void { if (!loaderHelpers.is_runtime_running()) { return; } + forceThreadMemoryViewRefresh(); tcwraps.mono_wasm_synchronization_context_pump(); } diff --git a/src/mono/browser/runtime/scheduling.ts b/src/mono/browser/runtime/scheduling.ts index 6132de162c36e..35552123845ad 100644 --- a/src/mono/browser/runtime/scheduling.ts +++ b/src/mono/browser/runtime/scheduling.ts @@ -64,10 +64,6 @@ export function mono_wasm_schedule_timer (shortestDueTimeMs: number): void { if (lastScheduledTimeoutId) { globalThis.clearTimeout(lastScheduledTimeoutId); lastScheduledTimeoutId = undefined; - // NOTE: Multi-threaded Module.safeSetTimeout() does the runtimeKeepalivePush() - // and non-Multi-threaded Module.safeSetTimeout does not runtimeKeepalivePush() - // but clearTimeout does not runtimeKeepalivePop() so we need to do it here in MT only. - if (WasmEnableThreads) Module.runtimeKeepalivePop(); } lastScheduledTimeoutId = Module.safeSetTimeout(mono_wasm_schedule_timer_tick, shortestDueTimeMs); }