Skip to content

Commit

Permalink
Merge pull request #1429 from Unity-Technologies/mono-upgrade-synchro…
Browse files Browse the repository at this point in the history
…nization-context

Restore Mono runtime and class library OS synchronization context changes
  • Loading branch information
Joshua Peterson committed Apr 21, 2021
2 parents e3979d9 + 2f7052b commit 7dd133f
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 0 deletions.
3 changes: 3 additions & 0 deletions mcs/class/referencesource/mscorlib/system/exception.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1138,6 +1138,9 @@ internal Exception FixRemotingException ()

return this;
}

[MethodImplAttribute(MethodImplOptions.InternalCall)]
internal static extern void ReportUnhandledException(Exception exception);
#endif
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,11 @@ private static SynchronizationContext GetThreadLocalContext()
context = AndroidPlatform.GetDefaultSyncContext ();
#endif

#if UNITY_AOT
if (context == null)
context = OSSpecificSynchronizationContext.Get();
#endif

return context;
}

Expand Down Expand Up @@ -375,4 +380,93 @@ private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, In
}
#endif
}

#if UNITY_AOT
class OSSpecificSynchronizationContext : SynchronizationContext
{
object m_OSSynchronizationContext;
private static readonly ConditionalWeakTable<object, OSSpecificSynchronizationContext> s_ContextCache = new ConditionalWeakTable<object, OSSpecificSynchronizationContext>();

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
}
7 changes: 7 additions & 0 deletions mono/metadata/exception.c
Original file line number Diff line number Diff line change
Expand Up @@ -1533,3 +1533,10 @@ mono_error_convert_to_exception_handle (MonoError *error)
return is_ok (error) ? MONO_HANDLE_CAST (MonoException, NULL_HANDLE)
: MONO_HANDLE_NEW (MonoException, mono_error_convert_to_exception (error));
}

void
ves_icall_System_Exception_ReportUnhandledException(MonoObject *exc)
{
mono_unhandled_exception_internal (exc);
mono_invoke_unhandled_exception_hook (exc);
}
3 changes: 3 additions & 0 deletions mono/metadata/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,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_ */
8 changes: 8 additions & 0 deletions mono/metadata/icall-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,10 @@ HANDLES(ENV_17, "internalGetEnvironmentVariable_native", ves_icall_System_Enviro
HANDLES(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacPath, MonoString, 0, ())
HANDLES(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome, MonoString, 0, ())
NOHANDLES(ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set))

ICALL_TYPE(EXCEPTION, "System.Exception", EXCEPTION_1)
NOHANDLES(ICALL(EXCEPTION_1, "ReportUnhandledException", ves_icall_System_Exception_ReportUnhandledException))

ICALL_TYPE(GC, "System.GC", GC_10)
NOHANDLES(ICALL(GC_10, "GetAllocatedBytesForCurrentThread", ves_icall_System_GC_GetAllocatedBytesForCurrentThread))
NOHANDLES(ICALL(GC_0, "GetCollectionCount", ves_icall_System_GC_GetCollectionCount))
Expand Down Expand Up @@ -1031,6 +1035,10 @@ HANDLES(NATIVEC_3, "OpenEvent_icall", ves_icall_System_Threading_Events_OpenEven
NOHANDLES(ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal))
NOHANDLES(ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal))

ICALL_TYPE(OSSYNCCONTEXT, "System.Threading.OSSpecificSynchronizationContext", OSSYNCCONTEXT_1)
NOHANDLES(ICALL(OSSYNCCONTEXT_1, "GetOSContext", ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext))
NOHANDLES(ICALL(OSSYNCCONTEXT_2, "PostInternal", ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal))

ICALL_TYPE(SEMA, "System.Threading.Semaphore", SEMA_1)
NOHANDLES(ICALL(SEMA_1, "CreateSemaphore_icall", ves_icall_System_Threading_Semaphore_CreateSemaphore_icall))
NOHANDLES(ICALL(SEMA_2, "OpenSemaphore_icall", ves_icall_System_Threading_Semaphore_OpenSemaphore_icall))
Expand Down
13 changes: 13 additions & 0 deletions mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -9850,3 +9850,16 @@ ves_icall_System_Net_NetworkInformation_LinuxNetworkChange_CloseNLSocket (gpoint
#undef ICALL
#undef NOHANDLES
#undef MONO_HANDLE_REGISTER_ICALL

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_exception_from_name_msg (mono_get_corlib (), "System", "NotImplementedException", "System.Threading.InteropServices.OSSpecificSynchronizationContext.PostInternal internal call is not implemented."));
}
6 changes: 6 additions & 0 deletions mono/metadata/threads-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -597,4 +597,10 @@ mono_interlocked_unlock(void) {
}
#endif

MonoObjectHandle
ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext ();

void
ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg);

#endif /* _MONO_METADATA_THREADS_TYPES_H_ */

0 comments on commit 7dd133f

Please sign in to comment.