Skip to content

Commit 59ce130

Browse files
Merge pull request #1169 from Unity-Technologies/os-synchronization-context
OS synchronization context
2 parents acf432a + 4b9c1a2 commit 59ce130

File tree

7 files changed

+132
-0
lines changed

7 files changed

+132
-0
lines changed

mcs/class/referencesource/mscorlib/system/exception.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,9 @@ internal Exception FixRemotingException ()
11141114

11151115
return this;
11161116
}
1117+
1118+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
1119+
internal static extern void ReportUnhandledException(Exception exception);
11171120
#endif
11181121
}
11191122

mcs/class/referencesource/mscorlib/system/threading/synchronizationcontext.cs

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,11 @@ private static SynchronizationContext GetThreadLocalContext()
293293
context = AndroidPlatform.GetDefaultSyncContext ();
294294
#endif
295295

296+
#if UNITY_AOT
297+
if (context == null)
298+
context = OSSpecificSynchronizationContext.Get();
299+
#endif
300+
296301
return context;
297302
}
298303

@@ -371,4 +376,93 @@ private static int InvokeWaitMethodHelper(SynchronizationContext syncContext, In
371376
}
372377
#endif
373378
}
379+
380+
#if UNITY_AOT
381+
class OSSpecificSynchronizationContext : SynchronizationContext
382+
{
383+
object m_OSSynchronizationContext;
384+
private static readonly ConditionalWeakTable<object, OSSpecificSynchronizationContext> s_ContextCache = new ConditionalWeakTable<object, OSSpecificSynchronizationContext>();
385+
386+
private OSSpecificSynchronizationContext(object osContext)
387+
{
388+
m_OSSynchronizationContext = osContext;
389+
}
390+
391+
public static OSSpecificSynchronizationContext Get()
392+
{
393+
var osContext = GetOSContext();
394+
if (osContext == null)
395+
return null;
396+
397+
return s_ContextCache.GetValue(osContext, _osContext => new OSSpecificSynchronizationContext(_osContext));
398+
}
399+
400+
public override SynchronizationContext CreateCopy()
401+
{
402+
return new OSSpecificSynchronizationContext(m_OSSynchronizationContext);
403+
}
404+
405+
public override void Send(SendOrPostCallback d, object state)
406+
{
407+
throw new NotSupportedException();
408+
}
409+
410+
public override void Post(SendOrPostCallback d, object state)
411+
{
412+
var callback = Marshal.GetFunctionPointerForDelegate((InvocationEntryDelegate)InvocationEntry);
413+
var invocationContext = new InvocationContext(d, state);
414+
var invocationContextHandle = GCHandle.Alloc(invocationContext);
415+
PostInternal(m_OSSynchronizationContext, callback, GCHandle.ToIntPtr(invocationContextHandle));
416+
}
417+
418+
private delegate void InvocationEntryDelegate(IntPtr arg);
419+
420+
[MonoPInvokeCallback(typeof(InvocationEntryDelegate))]
421+
private static void InvocationEntry(IntPtr arg)
422+
{
423+
try
424+
{
425+
var invocationContextHandle = GCHandle.FromIntPtr(arg);
426+
var invocationContext = (InvocationContext)invocationContextHandle.Target;
427+
invocationContextHandle.Free();
428+
invocationContext.Invoke();
429+
}
430+
catch (Exception e)
431+
{
432+
Exception.ReportUnhandledException(e);
433+
}
434+
}
435+
436+
[AttributeUsage (AttributeTargets.Method)]
437+
sealed class MonoPInvokeCallbackAttribute : Attribute
438+
{
439+
public MonoPInvokeCallbackAttribute(Type t)
440+
{
441+
}
442+
}
443+
444+
class InvocationContext
445+
{
446+
private SendOrPostCallback m_Delegate;
447+
private object m_State;
448+
449+
public InvocationContext(SendOrPostCallback d, object state)
450+
{
451+
m_Delegate = d;
452+
m_State = state;
453+
}
454+
455+
public void Invoke()
456+
{
457+
m_Delegate(m_State);
458+
}
459+
}
460+
461+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
462+
private extern static object GetOSContext();
463+
464+
[MethodImplAttribute(MethodImplOptions.InternalCall)]
465+
private extern static void PostInternal(object osSynchronizationContext, IntPtr callback, IntPtr arg);
466+
}
467+
#endif
374468
}

mono/metadata/exception.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,3 +1183,10 @@ mono_exception_from_name_four_strings_checked (MonoImage *image, const char *nam
11831183

11841184
return create_exception_four_strings (klass, a1, a2, a3, a4, error);
11851185
}
1186+
1187+
void
1188+
ves_icall_System_Exception_ReportUnhandledException(MonoObject *exc)
1189+
{
1190+
mono_unhandled_exception (exc);
1191+
mono_invoke_unhandled_exception_hook (exc);
1192+
}

mono/metadata/exception.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,9 @@ typedef void (*MonoUnhandledExceptionFunc) (MonoObject *exc, void *user
161161
MONO_API void mono_install_unhandled_exception_hook (MonoUnhandledExceptionFunc func, void *user_data);
162162
void mono_invoke_unhandled_exception_hook (MonoObject *exc);
163163

164+
void
165+
ves_icall_System_Exception_ReportUnhandledException (MonoObject *exc);
166+
164167
MONO_END_DECLS
165168

166169
#endif /* _MONO_METADATA_EXCEPTION_H_ */

mono/metadata/icall-def.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,9 @@ HANDLES(ICALL(ENV_18, "internalGetGacPath", ves_icall_System_Environment_GetGacP
293293
HANDLES(ICALL(ENV_19, "internalGetHome", ves_icall_System_Environment_InternalGetHome))
294294
ICALL(ENV_20, "set_ExitCode", mono_environment_exitcode_set)
295295

296+
ICALL_TYPE(EXCEPTION, "System.Exception", EXCEPTION_1)
297+
HANDLES(ICALL(EXCEPTION_1, "ReportUnhandledException", ves_icall_System_Exception_ReportUnhandledException))
298+
296299
ICALL_TYPE(GC, "System.GC", GC_0)
297300
ICALL(GC_0, "GetCollectionCount", mono_gc_collection_count)
298301
ICALL(GC_0a, "GetGeneration", mono_gc_get_generation)
@@ -935,6 +938,10 @@ HANDLES(ICALL(NATIVEC_3, "OpenEvent_internal(string,System.Security.AccessContro
935938
ICALL(NATIVEC_4, "ResetEvent_internal", ves_icall_System_Threading_Events_ResetEvent_internal)
936939
ICALL(NATIVEC_5, "SetEvent_internal", ves_icall_System_Threading_Events_SetEvent_internal)
937940

941+
ICALL_TYPE(OSSYNCCONTEXT, "System.Threading.OSSpecificSynchronizationContext", OSSYNCCONTEXT_1)
942+
HANDLES(ICALL(OSSYNCCONTEXT_1, "GetOSContext", ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext))
943+
ICALL(OSSYNCCONTEXT_2, "PostInternal", ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal)
944+
938945
ICALL_TYPE(SEMA, "System.Threading.Semaphore", SEMA_1)
939946
ICALL(SEMA_1, "CreateSemaphore_internal(int,int,string,int&)", ves_icall_System_Threading_Semaphore_CreateSemaphore_internal)
940947
ICALL(SEMA_2, "OpenSemaphore_internal(string,System.Security.AccessControl.SemaphoreRights,int&)", ves_icall_System_Threading_Semaphore_OpenSemaphore_internal)

mono/metadata/icall.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8751,3 +8751,15 @@ mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignatu
87518751
return mono_register_jit_icall_full (func, name, sig, no_wrapper, NULL);
87528752
}
87538753

8754+
MonoObjectHandle
8755+
ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext ()
8756+
{
8757+
return NULL_HANDLE;
8758+
}
8759+
8760+
void
8761+
ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg)
8762+
{
8763+
/* This isn't actually reachable since ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext always returns NULL */
8764+
mono_set_pending_exception (mono_get_exception_not_implemented ("System.Threading.InteropServices.OSSpecificSynchronizationContext.PostInternal internal call is not implemented."));
8765+
}

mono/metadata/threads-types.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,4 +267,10 @@ mono_thread_internal_describe (MonoInternalThread *internal, GString *str);
267267
gboolean
268268
mono_thread_internal_is_current (MonoInternalThread *internal);
269269

270+
MonoObjectHandle
271+
ves_icall_System_Threading_OSSpecificSynchronizationContext_GetOSContext ();
272+
273+
void
274+
ves_icall_System_Threading_OSSpecificSynchronizationContext_PostInternal (gpointer callback, gpointer arg);
275+
270276
#endif /* _MONO_METADATA_THREADS_TYPES_H_ */

0 commit comments

Comments
 (0)