-
Notifications
You must be signed in to change notification settings - Fork 544
[native/mono] Use mono_jit_thread_attach() #9937
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
base: main
Are you sure you want to change the base?
Conversation
TODO: what's the explanation?
Doh!
…o_jit_thread_attach Get all those CI "ignore networking error" fixes! Make CI Green Again™ (…wait.)
Analysis switching to
|
Mono API | GC Unsafe | Cooperate | Comment |
---|---|---|---|
mono_add_internal_call | No | Yes | init-only |
mono_alc_get_default_gchandle | No | Yes | |
mono_array_new | Yes | No | Can’t be called under coop suspend model. |
mono_assembly_get_image | Yes | Yes | |
mono_assembly_load_from_full | Yes | Yes | |
mono_assembly_load_full | Yes | Yes | |
mono_assembly_load_full_alc | Yes | Yes | |
mono_assembly_loaded | Yes | Yes | |
mono_assembly_name_free | Yes | Yes | |
mono_assembly_name_get_culture | Yes | Yes | |
mono_assembly_name_get_name | Yes | Yes | |
mono_assembly_name_new | Yes | Yes | |
mono_assembly_open_full | Yes | Yes | |
mono_check_corlib_version | Yes | Yes | |
mono_class_from_mono_type | Yes | Yes | |
mono_class_from_name | Yes | Yes | |
mono_class_get | Yes | Yes | |
mono_class_get_field_from_name | Yes | Yes | |
mono_class_get_image | No | Yes | |
mono_class_get_method_from_name | Yes | Yes | |
mono_class_get_name | Yes | Yes | |
mono_class_get_namespace | Yes | Yes | |
mono_class_get_type | No | Yes | |
mono_class_get_type_token | No | Yes | |
mono_class_is_subclass_of | Yes | Yes | |
mono_class_vtable | Yes | Yes | |
mono_config_is_server_mode | No | Yes | |
mono_debug_init | No | Yes | init-only |
mono_debug_open_image_from_memory | Yes | Yes | |
mono_debugger_agent_unhandled_exception | Yes | No | Can’t be called under coop suspend model. |
mono_dl_fallback_register | No | Yes | init-only |
mono_domain_foreach | Yes | Yes | |
mono_domain_get | No | Yes | |
mono_domain_get_id | No | Yes | |
mono_domain_set | Yes | Yes | |
mono_error_get_message | No | Yes | Should transition to GC unsafe. |
mono_field_get_value | Yes | No | Can’t be called under coop suspend model. |
mono_field_set_value | Yes | No | Can’t be called under coop suspend model. |
mono_field_static_set_value | Yes | Yes | |
mono_gc_register_bridge_callbacks | No | Yes | init-only |
mono_gc_wait_for_bridge_processing | Yes | Yes | |
mono_get_byte_class | No | Yes | |
mono_get_method | No | Yes | Should transition to GC unsafe. |
mono_get_root_domain | No | Yes | |
mono_get_runtime_build_info | No | Yes | |
mono_guid_to_string | No | Yes | |
mono_image_get_name | No | Yes | |
mono_image_loaded | Yes | Yes | |
mono_image_open_from_data_alc | Yes | Yes | |
mono_image_open_from_data_with_name | Yes | Yes | |
mono_image_strerror | No | Yes | |
mono_install_assembly_preload_hook | No | Yes | init-only |
mono_install_assembly_preload_hook_v3 | No | Yes | init-only |
mono_jit_init_version | No | Yes | |
mono_jit_parse_options | No | Yes | init-only |
mono_jit_set_aot_mode | No | Yes | init-only |
mono_jit_set_trace_options | No | Yes | init-only |
mono_jit_thread_attach | No | Yes | |
mono_method_full_name | Yes | Yes | |
mono_method_get_unmanaged_callers_only_ftnptr | Yes | Yes | |
mono_object_get_class | Yes | No | Can’t be called under coop suspend model. |
mono_profiler_create | No | Yes | init-only |
mono_reflection_assembly_get_assembly | No | No | Can’t be called under coop suspend model. |
mono_reflection_type_from_name | Yes | Yes | |
mono_reflection_type_get_type | Yes | No | Can’t be called under coop suspend model. |
mono_runtime_init | No | Yes | |
mono_runtime_invoke | Yes | No | Can’t be called under coop suspend model. |
mono_runtime_set_main_args | No | Yes | init-only |
mono_set_crash_chaining | No | Yes | init-only |
mono_set_signal_chaining | No | Yes | init-only |
mono_set_use_llvm | No | Yes | init-only |
mono_string_chars | No | No | Can’t be called under coop suspend model. |
mono_string_length | No | No | Can’t be called under coop suspend model. |
mono_string_new | Yes | No | Can’t be called under coop suspend model. |
mono_string_to_utf8 | Yes | No | Can’t be called under coop suspend model. |
mono_thread_attach | No | No | Can’t be called under coop suspend model. |
mono_thread_create | Yes | Yes | |
mono_trace_set_level_string | No | Yes | init-only |
mono_trace_set_log_handler | No | Yes | init-only |
mono_trace_set_mask_string | No | Yes | init-only |
mono_trace_set_print_handler | No | Yes | init-only |
mono_trace_set_printerr_handler | No | Yes | init-only |
mono_type_get_name_full | No | Yes | Should transition to GC unsafe. |
mono_type_get_object | Yes | No | Can’t be called under coop suspend model. |
mono_unhandled_exception | Yes | No | Can’t be called under coop suspend model. |
mono_value_copy_array | No | No | Can’t be called under coop suspend model. |
@jonpryor should be proceed with this PR? |
other platform like ios/windows should also use |
dotnet OSX/iOS SDK's already use mono_jit_thread_attach for its integration as well as explicit calls to enter/exit GC safe/unsafe manually transition threads between RUNNNING and BLOCKING modes. For embedders, what API's you use depends on how you use the embedding API's from the attached thread. mono_thread_attach is the way to do it for backward compability and safety of all embedding API's. A thread attached using this API will remain in RUNNING mode (GC unsafe) and is viewed as running managed/runtime code. Such a thread will only enter BLOCKING mode (GC safe) when hitting safepoints inside managed or runtime code. In that case, if you have some native code like this: mono_thread_attach(); That violates the threading rules when attached using mono_thread_attach, since thread will be in RUNNING mode when waiting on an external event, blocking STW from completion. In cases like above, thread will need to be detached from runtime before it can wait on native thread pool. If the same thread was attached using mono_jit_thread_attach then thread will be in BLOCKING mode when returning from mono_jit_thread_attach call and the wait on event in external thread pool won't prevent STW from completing. This is however only safe in hybrid suspend mode (since it will pre-empt thread in BLOCKING mode), but in coop suspend model, it is only safe if the called embedding API's do proper GC transitions + won't pass raw managed references in/out of the embedding API. Using mono_jit_thread_attach puts more responsibility on the embedder to only use/call embedding API's that are fully cooperate aware (unless running in hybrid suspend mode). If you end up calling an embedding API that is not fully cooperate aware you will end up corrupting the managed heap in one way or the other. iOS SDK manually transitions the thread into RUNNING mode if its calling embedding API's that are not full cooperate aware and when done using them it can only keep GC handles around when switching thread black to BLOCKING mode. It is worth noting that wrappers used for reverse delegates as well as unmanaged callers only internally attach thread using mono_threads_attach_coop that works similar to mono_jit_thread_attach, leaving thread in BLOCKING mode when returning, if thread was not attached to runtime before call. It is also worth noting that thread init runtime will also return in state BLOCKING. We had a PR a long time ago to change behavior of mono_thread_attach to leave thread in BLOCKING mode on return, but it was backed out due to risk of breaking embedders since incorrectly using the embedding API's from a thread in BLOCKING mode is riskier (possible heap corruption) than incorrectly hand over thread to an external scheduler in RUNNING mode (hanging STW). The safest way of using the embedding API's under all modes is still to use mono_thread_attach and then detach thread if thread ends up handled by an external scheduler (like waiting outside of runtime/managed code). If you run in hybrid mode you can get away with mono_jit_thread_attach/mono_threads_attach_coop, but if you run in cooperate suspend mode you either use mono_thread_attach or have deep understanding around what embedding API's that can be called and do like iOS, manually switch between BLOCKING and RUNNING when needed. |
…o_jit_thread_attach
TODO: what's the explanation?