diff --git a/mcs/class/referencesource/mscorlib/system/exception.cs b/mcs/class/referencesource/mscorlib/system/exception.cs index a539756ee162..81e472443d7d 100644 --- a/mcs/class/referencesource/mscorlib/system/exception.cs +++ b/mcs/class/referencesource/mscorlib/system/exception.cs @@ -1114,6 +1114,9 @@ internal Exception FixRemotingException () return this; } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + internal static extern void ReportUnhandledException(Exception exception); #endif } diff --git a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs index 4c5290eb74a0..9e43efdd2811 100644 --- a/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs +++ b/mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs @@ -293,6 +293,11 @@ private static SynchronizationContext GetThreadLocalContext() context = AndroidPlatform.GetDefaultSyncContext (); #endif +#if UNITY_AOT + if (context == null) + context = OSSpecificSynchronizationContext.Get(); +#endif + return context; } @@ -371,4 +376,93 @@ private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, In } #endif } + +#if UNITY_AOT + class OSSpecificSynchronizationContext : SynchronizationContext + { + object m_OSSynchronizationContext; + private static readonly ConditionalWeakTable s_ContextCache = new ConditionalWeakTable(); + + private OSSpecificSynchronizationContext(object osContext) + { + m_OSSynchronizationContext = osContext; + } + + public static OSSpecificSynchronizationContext Get() + { + var osContext = GetOSContext(); + if (osContext == null) + return null; + + return s_ContextCache.GetValue(osContext, _osContext => new OSSpecificSynchronizationContext(_osContext)); + } + + public override SynchronizationContext CreateCopy() + { + return new OSSpecificSynchronizationContext(m_OSSynchronizationContext); + } + + public override void Send(SendOrPostCallback d, object state) + { + throw new NotSupportedException(); + } + + public override void Post(SendOrPostCallback d, object state) + { + var callback = Marshal.GetFunctionPointerForDelegate((InvocationEntryDelegate)InvocationEntry); + var invocationContext = new InvocationContext(d, state); + var invocationContextHandle = GCHandle.Alloc(invocationContext); + PostInternal(m_OSSynchronizationContext, callback, GCHandle.ToIntPtr(invocationContextHandle)); + } + + private delegate void InvocationEntryDelegate(IntPtr arg); + + [MonoPInvokeCallback(typeof(InvocationEntryDelegate))] + private static void InvocationEntry(IntPtr arg) + { + try + { + var invocationContextHandle = GCHandle.FromIntPtr(arg); + var invocationContext = (InvocationContext)invocationContextHandle.Target; + invocationContextHandle.Free(); + invocationContext.Invoke(); + } + catch (Exception e) + { + Exception.ReportUnhandledException(e); + } + } + + [AttributeUsage (AttributeTargets.Method)] + sealed class MonoPInvokeCallbackAttribute : Attribute + { + public MonoPInvokeCallbackAttribute(Type t) + { + } + } + + class InvocationContext + { + private SendOrPostCallback m_Delegate; + private object m_State; + + public InvocationContext(SendOrPostCallback d, object state) + { + m_Delegate = d; + m_State = state; + } + + public void Invoke() + { + m_Delegate(m_State); + } + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static object GetOSContext(); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern static void PostInternal(object osSynchronizationContext, IntPtr callback, IntPtr arg); + } +#endif } diff --git a/mono/metadata/exception.c b/mono/metadata/exception.c index 61fde6541757..9ee13f95a145 100644 --- a/mono/metadata/exception.c +++ b/mono/metadata/exception.c @@ -1183,3 +1183,10 @@ mono_exception_from_name_four_strings_checked (MonoImage *image, const char *nam return create_exception_four_strings (klass, a1, a2, a3, a4, error); } + +void +ves_icall_System_Exception_ReportUnhandledException(MonoObject *exc) +{ + mono_unhandled_exception (exc); + mono_invoke_unhandled_exception_hook (exc); +} \ No newline at end of file diff --git a/mono/metadata/exception.h b/mono/metadata/exception.h index 6575694c7c50..f53a2c8f4597 100644 --- a/mono/metadata/exception.h +++ b/mono/metadata/exception.h @@ -161,6 +161,9 @@ typedef void (*MonoUnhandledExceptionFunc) (MonoObject *exc, void *user MONO_API void mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, void *user_data); void mono_invoke_unhandled_exception_hook (MonoObject *exc); +void +ves_icall_System_Exception_ReportUnhandledException (MonoObject *exc); + MONO_END_DECLS #endif /* _MONO_METADATA_EXCEPTION_H_ */ diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 4e6d11f6a542..8efe62c3f347 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -293,6 +293,9 @@ HANDLES(ICALL(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacP HANDLES(ICALL(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome)) ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set) +ICALL_TYPE(EXCEPTION, "System.Exception", EXCEPTION_1) +HANDLES(ICALL(EXCEPTION_1, "ReportUnhandledException", ves_icall_System_Exception_ReportUnhandledException)) + ICALL_TYPE(GC, "System.GC", GC_0) ICALL(GC_0, "GetCollectionCount", mono_gc_collection_count) ICALL(GC_0a, "GetGeneration", mono_gc_get_generation) @@ -935,6 +938,10 @@ HANDLES(ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessContro ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal) ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal) +ICALL_TYPE(OSSYNCCONTEXT, "System.Threading.OSSpecificSynchronizationContext", OSSYNCCONTEXT_1) +HANDLES(ICALL(OSSYNCCONTEXT_1, "GetOSContext", ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext)) +ICALL(OSSYNCCONTEXT_2, "PostInternal", ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal) + ICALL_TYPE(SEMA, "System.Threading.Semaphore", SEMA_1) ICALL(SEMA_1, "CreateSemaphore_internal(int,int,string,int&)", ves_icall_System_Threading_Semaphore_CreateSemaphore_internal) ICALL(SEMA_2, "OpenSemaphore_internal(string,System.Security.AccessControl.SemaphoreRights,int&)", ves_icall_System_Threading_Semaphore_OpenSemaphore_internal) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index befabf51c486..8bedfdb678e0 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -8751,3 +8751,15 @@ mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignatu return mono_register_jit_icall_full (func, name, sig, no_wrapper, NULL); } +MonoObjectHandle +ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext () +{ + return NULL_HANDLE; +} + +void +ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg) +{ + /* This isn't actually reachable since ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext always returns NULL */ + mono_set_pending_exception (mono_get_exception_not_implemented ("System.Threading.InteropServices.OSSpecificSynchronizationContext.PostInternal internal call is not implemented.")); +} diff --git a/mono/metadata/threads-types.h b/mono/metadata/threads-types.h index 4189f7a75094..2fcf55787083 100644 --- a/mono/metadata/threads-types.h +++ b/mono/metadata/threads-types.h @@ -267,4 +267,10 @@ mono_thread_internal_describe (MonoInternalThread *internal, GString *str); gboolean mono_thread_internal_is_current (MonoInternalThread *internal); +MonoObjectHandle +ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext (); + +void +ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg); + #endif /* _MONO_METADATA_THREADS_TYPES_H_ */