Skip to content
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

OS synchronization context #1169

Merged
merged 3 commits into from
May 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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))
TautvydasZilys marked this conversation as resolved.
Show resolved Hide resolved

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_ */