Skip to content

Commit

Permalink
Merge pull request #1169 from Unity-Technologies/os-synchronization-c…
Browse files Browse the repository at this point in the history
…ontext

OS synchronization context
  • Loading branch information
TautvydasZilys committed May 1, 2019
2 parents acf432a + 4b9c1a2 commit 59ce130
Show file tree
Hide file tree
Showing 7 changed files with 132 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 @@ -1114,6 +1114,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 @@ -293,6 +293,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 @@ -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<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 @@ -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);
}
3 changes: 3 additions & 0 deletions mono/metadata/exception.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */
7 changes: 7 additions & 0 deletions mono/metadata/icall-def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
12 changes: 12 additions & 0 deletions mono/metadata/icall.c
Original file line number Diff line number Diff line change
Expand Up @@ -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."));
}
6 changes: 6 additions & 0 deletions mono/metadata/threads-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -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_ */

0 comments on commit 59ce130

Please sign in to comment.