Thread.Interrupt is not dependent on MONO_FEATURE_THREAD_SUSPEND_RESUME.
[mono.git] / mcs / class / referencesource / mscorlib / system / threading / thread.cs
index cfc99de1918932d890bf580fd63e39e15fad5b04..f45df0fcda81ad133b489c82b26a1700f4177f06 100644 (file)
@@ -4,7 +4,7 @@
 //
 // ==--==
 //
-// <OWNER>[....]</OWNER>
+// <OWNER>Microsoft</OWNER>
 /*=============================================================================
 **
 ** Class: Thread
@@ -21,8 +21,8 @@ namespace System.Threading {
     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;
@@ -139,7 +139,9 @@ namespace System.Threading {
 #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
@@ -172,7 +174,7 @@ namespace System.Threading {
 #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.
@@ -190,11 +192,32 @@ namespace System.Threading {
         // 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
@@ -215,7 +238,7 @@ namespace System.Threading {
             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) {
@@ -275,7 +298,7 @@ namespace System.Threading {
 
             return new ThreadHandle(thread);
         }
-
+#endif
 
         /*=========================================================================
         ** Spawns off a new thread which will begin executing at the ThreadStart
@@ -331,11 +354,16 @@ namespace System.Threading {
                     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()
         {
@@ -348,7 +376,7 @@ namespace System.Threading {
             set { m_ExecutionContextBelongsToOuterScope = !value; }
         }
 
-#if DEBUG
+#if !MONO && DEBUG
         internal bool ForbidExecutionContextMutation
         {
             set { m_ForbidExecutionContextMutation = value; }
@@ -377,7 +405,7 @@ namespace System.Threading {
         internal ExecutionContext GetMutableExecutionContext()
         {
             Contract.Assert(Thread.CurrentThread == this);
-#if DEBUG
+#if !MONO && DEBUG
             Contract.Assert(!m_ForbidExecutionContextMutation);
 #endif
             if (m_ExecutionContext == null)
@@ -409,7 +437,9 @@ namespace System.Threading {
             m_ExecutionContext = value.DangerousGetRawExecutionContext();
             ExecutionContextBelongsToCurrentScope = belongsToCurrentScope;
         }
+#endif //!FEATURE_CORECLR
 
+#if !MONO
         [System.Security.SecurityCritical]  // auto-generated
         [ResourceExposure(ResourceScope.None)]
         [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -452,9 +482,6 @@ namespace System.Threading {
         [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();
 
         /*=========================================================================
@@ -530,8 +557,8 @@ namespace System.Threading {
         [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
@@ -551,7 +578,8 @@ namespace System.Threading {
         [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.
@@ -588,7 +616,9 @@ namespace System.Threading {
         [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
@@ -627,7 +657,7 @@ namespace System.Threading {
         [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.
         =========================================================================*/
@@ -645,7 +675,7 @@ namespace System.Threading {
             [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
@@ -671,6 +701,10 @@ namespace System.Threading {
         [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);
         }
 
@@ -700,10 +734,16 @@ namespace System.Threading {
         [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)
@@ -714,7 +754,7 @@ namespace System.Threading {
             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. */
@@ -733,12 +773,13 @@ namespace System.Threading {
         {
             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
@@ -748,13 +789,11 @@ namespace System.Threading {
         {
             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();
@@ -959,7 +998,7 @@ namespace System.Threading {
         [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.
@@ -1038,7 +1077,7 @@ namespace System.Threading {
 
             dls.Store.SetData(slot, data);
         }
-
+#if !MONO
 
         // #threadCultureInfo
         //
@@ -1128,18 +1167,30 @@ namespace System.Threading {
                 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;
+                }
             }
         }
 
@@ -1199,7 +1250,7 @@ namespace System.Threading {
                     return CultureInfo.GetCultureInfoForUserPreferredLanguageInAppX() ?? GetCurrentCultureNoAppX();
                 } 
                 else 
-#endif 
+#endif
                 {
                     return GetCurrentCultureNoAppX();
                 }
@@ -1237,8 +1288,19 @@ namespace System.Threading {
                     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;
+                }
             }
         }
 
@@ -1328,15 +1390,11 @@ namespace System.Threading {
 
             [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.
@@ -1345,6 +1403,7 @@ namespace System.Threading {
         {
             GetMutableExecutionContext().LogicalCallContext.SecurityData.Principal = principal;
         }
+#endif // FEATURE_IMPERSONATION
 
 #if FEATURE_REMOTING   
 
@@ -1370,7 +1429,7 @@ namespace System.Threading {
         {
             return ftnToCall(args);
         }
-#endif // FEATURE_REMOTING        
+#endif // FEATURE_REMOTING
 
         /*======================================================================
         ** Returns the current domain in which current thread is running.
@@ -1704,7 +1763,7 @@ namespace System.Threading {
             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)]
@@ -1723,6 +1782,7 @@ namespace System.Threading {
             }
         }
 
+#if !FEATURE_CORECLR && !MOBILE
         void _Thread.GetTypeInfoCount(out uint pcTInfo)
         {
             throw new NotImplementedException();
@@ -1742,7 +1802,9 @@ namespace System.Threading {
         {
             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).