diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 54e8db81929eb3..016936b3fd8a01 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -129,7 +129,7 @@ static void emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb) { // FIXME Put a boolean in MonoMethodBuilder instead. - if (strstr (mb->name, "mono_thread_interruption_checkpoint")) + if (mono_opt_wasm_disable_threads || strstr (mb->name, "mono_thread_interruption_checkpoint")) return; mono_marshal_shared_emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_interruption_checkpoint); @@ -138,6 +138,9 @@ emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb) static void emit_thread_force_interrupt_checkpoint (MonoMethodBuilder *mb) { + if (mono_opt_wasm_disable_threads) + return; + mono_marshal_shared_emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_force_interruption_checkpoint_noraise); } @@ -596,8 +599,8 @@ gc_safe_transition_builder_init (GCSafeTransitionBuilder *builder, MonoMethodBui #ifndef DISABLE_THREADS return TRUE; #else - /* if we're in the AOT compiler, obey the --wasm-gc-safepoints option even if the AOT compiler doesn't have threads enabled */ - return mono_opt_wasm_gc_safepoints; + /* if we're in the AOT compiler, obey the --wasm-disable-threads option even if the AOT compiler doesn't have threads enabled */ + return !mono_opt_wasm_disable_threads; #endif #else return TRUE; @@ -2564,11 +2567,11 @@ emit_thunk_invoke_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono MonoExceptionClause *clause; MonoType *object_type = mono_get_object_type (); #if defined (TARGET_WASM) - /* in the AOT compiler emit blocking transitions if --wasm-gc-safepoints was used */ + /* in the AOT compiler emit blocking transitions if --wasm-disable-threads was used */ #ifndef DISABLE_THREADS const gboolean do_blocking_transition = TRUE; #else - const gboolean do_blocking_transition = mono_opt_wasm_gc_safepoints; + const gboolean do_blocking_transition = !mono_opt_wasm_disable_threads; #endif #else const gboolean do_blocking_transition = TRUE; diff --git a/src/mono/mono/metadata/marshal-shared.c b/src/mono/mono/metadata/marshal-shared.c index 7a6beef71a7406..efbae695f173cf 100644 --- a/src/mono/mono/metadata/marshal-shared.c +++ b/src/mono/mono/metadata/marshal-shared.c @@ -12,6 +12,7 @@ #include "mono/metadata/class-internals.h" #include "metadata/reflection-internals.h" #include "mono/metadata/handle.h" +#include #define OPDEF(a,b,c,d,e,f,g,h,i,j) \ @@ -962,6 +963,10 @@ mono_marshal_shared_emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, g void mono_marshal_shared_emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, MonoJitICallId checkpoint_icall_id) { + if(mono_opt_wasm_disable_threads) { + return; + } + int pos_noabort, pos_noex; mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX); diff --git a/src/mono/mono/metadata/monitor.c b/src/mono/mono/metadata/monitor.c index 2e08f94d3361e7..892a67fc4423b5 100644 --- a/src/mono/mono/metadata/monitor.c +++ b/src/mono/mono/metadata/monitor.c @@ -1160,8 +1160,11 @@ mono_monitor_try_enter_loop_if_interrupted (MonoObject *obj, guint32 ms, res = mono_monitor_try_enter_internal (obj, ms, allow_interruption); if (res == -1) { // The wait was interrupted and the monitor was not acquired. +#ifndef DISABLE_THREADS MonoException *exc; +#endif HANDLE_FUNCTION_ENTER (); +#ifndef DISABLE_THREADS exc = mono_thread_interruption_checkpoint (); if (exc) { MONO_HANDLE_NEW (MonoException, exc); @@ -1170,9 +1173,12 @@ mono_monitor_try_enter_loop_if_interrupted (MonoObject *obj, guint32 ms, else mono_set_pending_exception (exc); } +#endif HANDLE_FUNCTION_RETURN (); +#ifndef DISABLE_THREADS if (exc) return FALSE; +#endif // The interrupt was a false positive. Ignore it from now on. // This feels like a hack. // threads.c should give us less confusing directions. diff --git a/src/mono/mono/metadata/object.c b/src/mono/mono/metadata/object.c index 7b453e88d237a5..5a4c547f96b1d3 100644 --- a/src/mono/mono/metadata/object.c +++ b/src/mono/mono/metadata/object.c @@ -605,8 +605,12 @@ mono_runtime_class_init_full (MonoVTable *vtable, MonoError *error) * throw tie for the type. */ if (exc && mono_object_class (exc) == mono_defaults.threadabortexception_class) { +#ifndef DISABLE_THREADS pending_tae = TRUE; mono_thread_resume_interruption (FALSE); +#else // DISABLE_THREADS + g_assert_not_reached (); +#endif // DISABLE_THREADS } } else { /* this just blocks until the initializing thread is done */ diff --git a/src/mono/mono/metadata/threads.c b/src/mono/mono/metadata/threads.c index 11fb393d770676..e8269325d77dec 100644 --- a/src/mono/mono/metadata/threads.c +++ b/src/mono/mono/metadata/threads.c @@ -282,24 +282,31 @@ enum { ABORT_PROT_BLOCK_MASK = (((1 << ABORT_PROT_BLOCK_BITS) - 1) << ABORT_PROT_BLOCK_SHIFT) }; +#ifndef DISABLE_THREADS static int mono_thread_get_abort_prot_block_count (MonoInternalThread *thread) { gsize state = thread->thread_state; return (state & ABORT_PROT_BLOCK_MASK) >> ABORT_PROT_BLOCK_SHIFT; } +#endif gboolean mono_threads_is_current_thread_in_protected_block (void) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); return mono_thread_get_abort_prot_block_count (thread) > 0; +#else + return false; +#endif } void mono_threads_begin_abort_protected_block (void) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); gsize old_state, new_state; int new_val; @@ -323,8 +330,10 @@ mono_threads_begin_abort_protected_block (void) } else { THREADS_INTERRUPT_DEBUG ("[%d] begin abort protected block old_state %ld new_state %ld, tir %d\n", thread->small_id, old_state, new_state, mono_thread_interruption_request_flag); } +#endif } +#ifndef DISABLE_THREADS static gboolean mono_thread_state_has_interruption (gsize state) { @@ -338,10 +347,12 @@ mono_thread_state_has_interruption (gsize state) return FALSE; } +#endif gboolean mono_threads_end_abort_protected_block (void) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); gsize old_state, new_state; int new_val; @@ -364,8 +375,12 @@ mono_threads_end_abort_protected_block (void) } return mono_thread_state_has_interruption (new_state); +#else + return FALSE; +#endif } +#ifndef DISABLE_THREADS static gboolean mono_thread_get_interruption_requested (MonoInternalThread *thread) { @@ -373,6 +388,7 @@ mono_thread_get_interruption_requested (MonoInternalThread *thread) return mono_thread_state_has_interruption (state); } +#endif /* * Returns TRUE is there was a state change @@ -381,6 +397,7 @@ mono_thread_get_interruption_requested (MonoInternalThread *thread) static gboolean mono_thread_clear_interruption_requested (MonoInternalThread *thread) { +#ifndef DISABLE_THREADS gsize old_state, new_state; do { old_state = thread->thread_state; @@ -401,23 +418,34 @@ mono_thread_clear_interruption_requested (MonoInternalThread *thread) if (mono_thread_interruption_request_flag < 0) g_warning ("bad mono_thread_interruption_request_flag state"); return TRUE; +#else + return FALSE; +#endif } static gboolean mono_thread_clear_interruption_requested_handle (MonoInternalThreadHandle thread) { +#ifndef DISABLE_THREADS // Internal threads are pinned so shallow coop/handle. return mono_thread_clear_interruption_requested (mono_internal_thread_handle_ptr (thread)); +#else + return FALSE; +#endif } /* Returns TRUE is there was a state change and the interruption can be processed */ static gboolean mono_thread_set_interruption_requested (MonoInternalThread *thread) { +#ifndef DISABLE_THREADS //always force when the current thread is doing it to itself. gboolean sync = thread == mono_thread_internal_current (); /* Normally synchronous interruptions can bypass abort protection. */ return mono_thread_set_interruption_requested_flags (thread, sync); +#else + g_assert_not_reached (); +#endif } /* Returns TRUE if there was a state change and the interruption can be @@ -430,16 +458,21 @@ mono_thread_set_interruption_requested (MonoInternalThread *thread) static gboolean mono_thread_set_self_interruption_respect_abort_prot (void) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); /* N.B. Sets the ASYNC_REQUESTED_BIT for current this thread, * which is unusual. */ return mono_thread_set_interruption_requested_flags (thread, FALSE); +#else + g_assert_not_reached (); +#endif } /* Returns TRUE if there was a state change and the interruption can be processed. */ static gboolean mono_thread_set_interruption_requested_flags (MonoInternalThread *thread, gboolean sync) { +#ifndef DISABLE_THREADS gsize old_state, new_state; do { old_state = thread->thread_state; @@ -463,6 +496,9 @@ mono_thread_set_interruption_requested_flags (MonoInternalThread *thread, gboole } return sync || !(new_state & ABORT_PROT_BLOCK_MASK); +#else + g_assert_not_reached (); +#endif } static MonoNativeThreadId @@ -3686,6 +3722,7 @@ mono_thread_execute_interruption_ptr (void) static gboolean mono_thread_request_interruption_internal (gboolean running_managed, MonoExceptionHandle *pexc) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); /* The thread may already be stopping */ @@ -3710,6 +3747,9 @@ mono_thread_request_interruption_internal (gboolean running_managed, MonoExcepti return FALSE; } return mono_thread_execute_interruption (pexc); +#else // DISABLE_THREADS + g_assert_not_reached (); +#endif } static void @@ -3729,6 +3769,7 @@ mono_thread_request_interruption_managed (MonoExceptionHandle *exc) void mono_thread_resume_interruption (gboolean exec) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); gboolean still_aborting; @@ -3751,23 +3792,29 @@ mono_thread_resume_interruption (gboolean exec) if (exec) // Ignore the exception here, it will be raised later. mono_thread_execute_interruption_void (); +#else + g_assert_not_reached (); +#endif } gboolean mono_thread_interruption_requested (void) { +#ifndef DISABLE_THREADS if (mono_thread_interruption_request_flag) { MonoInternalThread *thread = mono_thread_internal_current (); /* The thread may already be stopping */ if (thread != NULL) return mono_thread_get_interruption_requested (thread); } +#endif return FALSE; } static MonoException* mono_thread_interruption_checkpoint_request (gboolean bypass_abort_protection) { +#ifndef DISABLE_THREADS MonoInternalThread *thread = mono_thread_internal_current (); /* The thread may already be stopping */ @@ -3779,6 +3826,9 @@ mono_thread_interruption_checkpoint_request (gboolean bypass_abort_protection) return NULL; return mono_thread_execute_interruption_ptr (); +#else + return NULL; +#endif } /* diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index 2bc048ca8d5fe7..c7d67d284f8f0f 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -1132,6 +1132,7 @@ interp_throw_ex_general ( THROW_EX (interp_get_exception_null_reference (frame, ip), ip); \ } while (0) +#ifndef DISABLE_THREADS #define EXCEPTION_CHECKPOINT \ do { \ if (mono_thread_interruption_request_flag && !mono_threads_is_critical_method (frame->imethod->method)) { \ @@ -1140,6 +1141,9 @@ interp_throw_ex_general ( THROW_EX_GENERAL (exc, ip, TRUE); \ } \ } while (0) +#else +#define EXCEPTION_CHECKPOINT do { } while (0); +#endif // Reduce duplicate code in mono_interp_exec_method static MONO_NEVER_INLINE void diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index 85f566553fa55e..a3e620a4a63cdf 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -2422,8 +2422,12 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu } } if (is_outside) { +#ifndef DISABLE_THREADS jit_tls->handler_block = NULL; mono_thread_resume_interruption (TRUE); /*We ignore the exception here, it will be raised later*/ +#else // DISABLE_THREADS + g_assert_not_reached (); +#endif // DISABLE_THREADS } } diff --git a/src/mono/mono/mini/mini.h b/src/mono/mono/mini/mini.h index 97196e7e125cb4..e985fb6b1136f5 100644 --- a/src/mono/mono/mini/mini.h +++ b/src/mono/mono/mini/mini.h @@ -2995,7 +2995,7 @@ mini_safepoints_enabled (void) #ifndef DISABLE_THREADS return TRUE; #else - return mono_opt_wasm_gc_safepoints; + return !mono_opt_wasm_disable_threads; #endif #else return TRUE; diff --git a/src/mono/mono/utils/options-def.h b/src/mono/mono/utils/options-def.h index 2397b3dd4ede3a..eb8cee1b8cd82d 100644 --- a/src/mono/mono/utils/options-def.h +++ b/src/mono/mono/utils/options-def.h @@ -64,7 +64,7 @@ DEFINE_BOOL(aot_lazy_assembly_load, "aot-lazy-assembly-load", FALSE, "Load assem DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", FALSE, "Record interpreter tiering information for automatic PGO") #else DEFINE_BOOL(interp_pgo_recording, "interp-pgo-recording", FALSE, "Record interpreter tiering information for automatic PGO") -DEFINE_BOOL(wasm_gc_safepoints, "wasm-gc-safepoints", FALSE, "Use GC safepoints on WASM") +DEFINE_BOOL(wasm_disable_threads, "wasm-disable-threads", FALSE, "Disable threads on WASM") #endif DEFINE_BOOL(interp_pgo_logging, "interp-pgo-logging", FALSE, "Log messages when interpreter PGO optimizes a method or updates its table") DEFINE_BOOL(interp_codegen_timing, "interp-codegen-timing", FALSE, "Measure time spent generating interpreter code and log it periodically") @@ -80,7 +80,7 @@ DEFINE_BOOL(jiterpreter_interp_entry_enabled, "jiterpreter-interp-entry-enabled" // jit_call_enabled controls whether do_jit_call will use specialized trampolines for hot call sites DEFINE_BOOL(jiterpreter_jit_call_enabled, "jiterpreter-jit-call-enabled", TRUE, "JIT specialized WASM do_jit_call trampolines") -DEFINE_BOOL(wasm_gc_safepoints, "wasm-gc-safepoints", FALSE, "Use GC safepoints on WASM") +DEFINE_BOOL(wasm_disable_threads, "wasm-disable-threads", TRUE, "Disable threads on WASM") #else // traces_enabled controls whether the jiterpreter will JIT individual interpreter opcode traces DEFINE_BOOL(jiterpreter_traces_enabled, "jiterpreter-traces-enabled", TRUE, "JIT interpreter opcode traces into WASM") @@ -89,7 +89,7 @@ DEFINE_BOOL_READONLY(jiterpreter_interp_entry_enabled, "jiterpreter-interp-entry // jit_call_enabled controls whether do_jit_call will use specialized trampolines for hot call sites DEFINE_BOOL_READONLY(jiterpreter_jit_call_enabled, "jiterpreter-jit-call-enabled", FALSE, "JIT specialized WASM do_jit_call trampolines") -DEFINE_BOOL_READONLY(wasm_gc_safepoints, "wasm-gc-safepoints", TRUE, "Use GC safepoints on WASM") +DEFINE_BOOL(wasm_disable_threads, "wasm-disable-threads", FALSE, "Disable threads on WASM") #endif // DISABLE_THREADS // enables using WASM try/catch_all instructions where appropriate (currently only do_jit_call), diff --git a/src/mono/wasm/build/WasmApp.Common.targets b/src/mono/wasm/build/WasmApp.Common.targets index d37350ecf80ad8..b73bb8de6528a0 100644 --- a/src/mono/wasm/build/WasmApp.Common.targets +++ b/src/mono/wasm/build/WasmApp.Common.targets @@ -639,7 +639,7 @@ - +