-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[Mono]: Add support for lazy runtime init in native-to-managed wrapper, similar to NativeAOT library build. #82253
[Mono]: Add support for lazy runtime init in native-to-managed wrapper, similar to NativeAOT library build. #82253
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main thing I'd like to see is a separate call for creating a n2m wrapper that include the callback from the ones that don't. It's kind of annoying to pass FALSE
in 20 places just to pass TRUE
in one.
I'm confused why we need two separate things that the user can modify. It seems like one should be enough? Also i'm unclear on what exactly the user is supposed to call from the callback - monovm_initialize
?
In terms of implementation, I really wish it was easier to create a wrapper around the n2m wrapper.
also I don't understand why the substitution of the callback is happening in the aot compiler's guts and not in method-to-ir
Most of the answers are inlined above. In the end I think we have the following options in this PR:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to be careful that runtime_init_callback
read/writes aren't reordered. Do we have some off the shelf spinlock in the runtime that we could use?
I mainly replicated the implementation form NativeAOT on this one runtime/src/coreclr/nativeaot/Runtime/thread.cpp Line 1217 in 50f9bcc
it does the same semantics, but I can add clear acquire/release semantics on runtime_init_callback. |
4118c93
to
598bf8e
Compare
@vargaz @lambdageek @mdh1418 Do you think this PR is ready to go or anything else that needs to be adjusted? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me!
Timeouts seems to be happening on many PR's to probably unrelated. |
NativeAOT supports library mode, building all needed runtime and managed code into a static or shared library that can be loaded and used by embedding applications. NativeAOT exports managed functiond marked with UnmanagedCallersOnly attribute that can be called by embedder to run managed code. NativeAOT runtime doesn't need any initialization, meaning that calling the managed method exported using UnmanagedCallersOnly attribute will perform lazy runtime initialization on first call. This commit add similar support to MonoVM giving it possibilities to include a call to a runtime init function as part of native-to-managed wrapper used for methods marked with UnmanagedCallersOnly attribute + entry point. AOT compiler accepts a new argument, runtime-init-callback, if used like that, the native-to-managed wrapper will get a call to a default invoke callback method implemented by runtime, that will call a set callback once (thread safe). It is also possible to pass runtime-init-callback=<custom symbol> to AOT compiler, and in that case native-to-managed wrapper will call that function and its up to implementor to do a thread safe implementation of runtime init. This capability could be used in case where the library can't set the callback before consumer of the library class the exported function. Two new runtime API's have been added in this commit, one to set the callback called by default runtime init implementation and the other is the implementation of that function used in native-to-managed wrapper if user doesn't use a custom runtime init callback function. Since this integration scenario is mainly for library build scenarios (we control the library builder), these methods are marked as MONO_COMPONENT_API and not something that should be part of the public API surface.
598bf8e
to
f6fe400
Compare
Failures in runtime (Build Libraries Test Run release mono linux arm64 Debug) is a known issue. |
NativeAOT supports library mode, building all needed runtime and managed code into a static or shared library that can be loaded and used by embedding applications. NativeAOT exports managed functions marked with UnmanagedCallersOnly attribute that can be called by embedder to run managed code. NativeAOT runtime doesn't need any initialization, meaning that calling the managed method exported using UnmanagedCallersOnly attribute will perform lazy runtime initialization on first call.
This commit add similar support to MonoVM giving it possibilities to include a call to a runtime init function as part of native-to-managed wrapper used for methods marked with UnmanagedCallersOnly attribute + entry point. AOT compiler accepts a new argument, runtime-init-callback, if used like that, the native-to-managed wrapper will get a call to a default invoke callback method implemented by runtime, that will call a set callback once (thread safe). It is also possible to pass runtime-init-callback= to AOT compiler, and in that case native-to-managed wrapper will call that function and its up to implementor to do a thread safe implementation of lazy runtime init. This capability could be used in case where the library can't set the callback before consumer of the library calls the exported function.
Two new runtime API's have been added in this commit, one to set the callback called by default runtime init implementation and the other is the implementation of that function used in native-to-managed wrapper if user doesn't use a custom runtime init callback function. Since this integration scenario is mainly for library build scenarios (we control the library builder), these methods are marked as MONO_COMPONENT_API and not something that should be part of the public API surface.
This feature is a is used together with AOT (partial or full) and the static AOT mode, a check has been added to AOT compiler to make sure prerequisites are meet.
NOTE, this only affects the native-to-managed wrappers added for managed methods decorated with UnmanagedCallersOnly + EntryPoint, all other generated native-to-managed wrappers will not be affected by this feature.