//
// ==--==
//
-// <OWNER>[....]</OWNER>
+// <OWNER>Microsoft</OWNER>
/*=============================================================================
**
** Class: Thread
using System.Runtime.InteropServices;
#if FEATURE_REMOTING
using System.Runtime.Remoting.Contexts;
-#endif
using System.Runtime.Remoting.Messaging;
+#endif
using System;
using System.Diagnostics;
using System.Security.Permissions;
#if FEATURE_REMOTING
private Context m_Context;
#endif
+#if !FEATURE_CORECLR
private ExecutionContext m_ExecutionContext; // this call context follows the logical thread
+#endif
private String m_Name;
private Delegate m_Delegate; // Delegate
#if DEBUG
private bool m_ForbidExecutionContextMutation;
#endif
-
+#endif
/*=========================================================================
** This manager is responsible for storing the global data that is
** shared amongst all the thread local stores.
// See code:#threadCultureInfo
#if !FEATURE_LEAK_CULTURE_INFO
[ThreadStatic]
- private static CultureInfo m_CurrentCulture;
+ internal static CultureInfo m_CurrentCulture;
[ThreadStatic]
- private static CultureInfo m_CurrentUICulture;
+ internal static CultureInfo m_CurrentUICulture;
#endif
+ static AsyncLocal<CultureInfo> s_asyncLocalCurrentCulture;
+ static AsyncLocal<CultureInfo> s_asyncLocalCurrentUICulture;
+
+ static void AsyncLocalSetCurrentCulture(AsyncLocalValueChangedArgs<CultureInfo> args)
+ {
+#if FEATURE_LEAK_CULTURE_INFO
+ Thread.CurrentThread.m_CurrentCulture = args.CurrentValue;
+#else
+ m_CurrentCulture = args.CurrentValue;
+#endif // FEATURE_LEAK_CULTURE_INFO
+ }
+
+ static void AsyncLocalSetCurrentUICulture(AsyncLocalValueChangedArgs<CultureInfo> args)
+ {
+#if FEATURE_LEAK_CULTURE_INFO
+ Thread.CurrentThread.m_CurrentUICulture = args.CurrentValue;
+#else
+ m_CurrentUICulture = args.CurrentValue;
+#endif // FEATURE_LEAK_CULTURE_INFO
+ }
+
#if FEATURE_CORECLR
// Adding an empty default ctor for annotation purposes
[System.Security.SecuritySafeCritical] // auto-generated
Contract.EndContractBlock();
SetStartHelper((Delegate)start,0); //0 will setup Thread with default stackSize
}
-#endif
+
[System.Security.SecuritySafeCritical] // auto-generated
public Thread(ThreadStart start, int maxStackSize) {
if (start == null) {
return new ThreadHandle(thread);
}
-
+#endif
/*=========================================================================
** Spawns off a new thread which will begin executing at the ThreadStart
ExecutionContext.CaptureOptions.IgnoreSyncCtx);
t.SetExecutionContextHelper(ec);
}
+#if FEATURE_IMPERSONATION
IPrincipal principal = (IPrincipal)CallContext.Principal;
+#else
+ IPrincipal principal = null;
+#endif
StartInternal(principal, ref stackMark);
}
+#if !FEATURE_CORECLR
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
internal ExecutionContext.Reader GetExecutionContextReader()
{
set { m_ExecutionContextBelongsToOuterScope = !value; }
}
-#if DEBUG
+#if !MONO && DEBUG
internal bool ForbidExecutionContextMutation
{
set { m_ForbidExecutionContextMutation = value; }
internal ExecutionContext GetMutableExecutionContext()
{
Contract.Assert(Thread.CurrentThread == this);
-#if DEBUG
+#if !MONO && DEBUG
Contract.Assert(!m_ForbidExecutionContextMutation);
#endif
if (m_ExecutionContext == null)
m_ExecutionContext = value.DangerousGetRawExecutionContext();
ExecutionContextBelongsToCurrentScope = belongsToCurrentScope;
}
+#endif //!FEATURE_CORECLR
+#if !MONO
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
[System.Security.SecurityCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- #if !FEATURE_CORECLR
- [System.Runtime.ForceTokenStabilization]
- #endif //!FEATURE_CORECLR
internal extern static IntPtr InternalGetCurrentThread();
/*=========================================================================
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void AbortInternal();
-
-#if !FEATURE_CORECLR
+#endif
+#if (!FEATURE_CORECLR && !MONO) || MONO_FEATURE_THREAD_ABORT
/*=========================================================================
** Resets a thread abort.
** Should be called by trusted code only
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void ResetAbortNative();
-
+#endif
+#if (!FEATURE_CORECLR && !MONO) || MONO_FEATURE_THREAD_SUSPEND_RESUME
/*=========================================================================
** Suspends the thread. If the thread is already suspended, this call has
** no effect.
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void ResumeInternal();
+#endif
+#if !FEATURE_CORECLR || MONO
/*=========================================================================
** Interrupts a thread that is inside a Wait(), Sleep() or Join(). If that
** thread is not currently blocked in that manner, it will be interrupted
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void SetPriorityNative(int priority);
-
+#if !MONO
/*=========================================================================
** Returns true if the thread has been started and is not dead.
=========================================================================*/
[MethodImpl(MethodImplOptions.InternalCall)]
get;
}
-
+#endif
/*=========================================================================
** Waits for the thread to die or for timeout milliseconds to elapse.
** Returns true if the thread died, or false if the wait timed out. If
[HostProtection(Synchronization=true, ExternalThreading=true)]
public bool Join(int millisecondsTimeout)
{
+#if MONO
+ if (millisecondsTimeout < Timeout.Infinite)
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+#endif
return JoinInternal(millisecondsTimeout);
}
[System.Security.SecuritySafeCritical] // auto-generated
public static void Sleep(int millisecondsTimeout)
{
+#if MONO
+ if (millisecondsTimeout < Timeout.Infinite)
+ throw new ArgumentOutOfRangeException("millisecondsTimeout", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegOrNegative1"));
+#endif
SleepInternal(millisecondsTimeout);
+#if !MONO
// Ensure we don't return to app code when the pause is underway
if(AppDomainPauseManager.IsPaused)
AppDomainPauseManager.ResumeEvent.WaitOneWithoutFAS();
+#endif
}
public static void Sleep(TimeSpan timeout)
Sleep((int)tm);
}
-
+#if !MONO
/* wait for a length of time proportial to 'iterations'. Each iteration is should
only take a few machine instructions. Calling this API is preferable to coding
a explict busy loop because the hardware can be informed that it is busy waiting. */
{
SpinWaitInternal(iterations);
}
-
+#endif
[System.Security.SecurityCritical] // auto-generated
- [MethodImplAttribute(MethodImplOptions.InternalCall),
- HostProtection(Synchronization = true, ExternalThreading = true),
- ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success),
- ResourceExposure(ResourceScope.None)]
+ [ResourceExposure(ResourceScope.None)]
+ [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
+ [SuppressUnmanagedCodeSecurity]
+ [HostProtection(Synchronization = true, ExternalThreading = true),
+ ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
private static extern bool YieldInternal();
[System.Security.SecuritySafeCritical] // auto-generated
{
return YieldInternal();
}
-
+
+#if !MONO
public static Thread CurrentThread {
[System.Security.SecuritySafeCritical] // auto-generated
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
-#if !FEATURE_CORECLR
- [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
-#endif
get {
Contract.Ensures(Contract.Result<Thread>() != null);
return GetCurrentThreadNative();
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private extern void StartupSetApartmentStateInternal();
#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
-
+#endif
/*=========================================================================
** Allocates an un-named data slot. The slot is allocated on ALL the
** threads.
dls.Store.SetData(slot, data);
}
-
+#if !MONO
// #threadCultureInfo
//
if (CompatibilitySwitches.IsAppEarlierThanWindowsPhone8)
{
//
- // NetCF had a bug where Thread.Current{UI}Culture would set the culture for every thread in the process.
- // This was because they stored the value in a regular static field (NetCF has no support for ThreadStatic fields).
- // Some apps depend on the broken behavior. We will emulate this behavior by redirecting setters to
- // DefaultThreadCurrentUICulture. (Note that this property did not existed in NetCF and so it is fine to piggy back
- // on it for the quirk.)
- //
+ // NetCF had a
+
+
+
+
+
CultureInfo.SetCurrentUICultureQuirk(value);
return;
}
#endif
+ if (!AppContextSwitches.NoAsyncCurrentCulture)
+ {
+ if (s_asyncLocalCurrentUICulture == null)
+ {
+ Interlocked.CompareExchange(ref s_asyncLocalCurrentUICulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentUICulture), null);
+ }
- m_CurrentUICulture = value;
+ // this one will set m_CurrentUICulture too
+ s_asyncLocalCurrentUICulture.Value = value;
+ }
+ else
+ {
+ m_CurrentUICulture = value;
+ }
}
}
return CultureInfo.GetCultureInfoForUserPreferredLanguageInAppX() ?? GetCurrentCultureNoAppX();
}
else
-#endif
+#endif
{
return GetCurrentCultureNoAppX();
}
return;
}
#endif
-
- m_CurrentCulture = value;
+ if (!AppContextSwitches.NoAsyncCurrentCulture)
+ {
+ if (s_asyncLocalCurrentCulture == null)
+ {
+ Interlocked.CompareExchange(ref s_asyncLocalCurrentCulture, new AsyncLocal<CultureInfo>(AsyncLocalSetCurrentCulture), null);
+ }
+ // this one will set m_CurrentCulture too
+ s_asyncLocalCurrentCulture.Value = value;
+ }
+ else
+ {
+ m_CurrentCulture = value;
+ }
}
}
[System.Security.SecuritySafeCritical] // auto-generated
[SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.ControlPrincipal)]
-#if !FEATURE_CORECLR
- [TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
-#endif
set
{
CallContext.Principal = value;
}
}
-#endif // FEATURE_IMPERSONATION
// Private routine called from unmanaged code to set an initial
// principal for a newly created thread.
{
GetMutableExecutionContext().LogicalCallContext.SecurityData.Principal = principal;
}
+#endif // FEATURE_IMPERSONATION
#if FEATURE_REMOTING
{
return ftnToCall(args);
}
-#endif // FEATURE_REMOTING
+#endif // FEATURE_REMOTING
/*======================================================================
** Returns the current domain in which current thread is running.
MemoryBarrier(); // Call MemoryBarrier to ensure the proper semantic in a portable way.
address = value;
}
-
+#endif
[System.Security.SecuritySafeCritical] // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
}
}
+#if !FEATURE_CORECLR && !MOBILE
void _Thread.GetTypeInfoCount(out uint pcTInfo)
{
throw new NotImplementedException();
{
throw new NotImplementedException();
}
+#endif
+#if !MONO
// Helper function to set the AbortReason for a thread abort.
// Checks that they're not alredy set, and then atomically updates
// the reason info (object + ADID).