Merge pull request #1632 from alexanderkyte/bug24118
[mono.git] / mcs / class / corlib / System.Threading / Thread.cs
index f286d5925ca382f7afd8a7f0bf10ecf789ddfd8d..4be83d2cd58c9807089f4146144911f26f85ccce 100644 (file)
@@ -43,7 +43,7 @@ using System.Runtime.ConstrainedExecution;
 
 namespace System.Threading {
        [StructLayout (LayoutKind.Sequential)]
-       internal class InternalThread : CriticalFinalizerObject {
+       sealed class InternalThread : CriticalFinalizerObject {
 #pragma warning disable 169, 414, 649
                #region Sync with metadata/object-internals.h
                int lock_thread_id;
@@ -137,6 +137,8 @@ namespace System.Threading {
 
                IPrincipal principal;
                int principal_version;
+               bool current_culture_set;
+               bool current_ui_culture_set;
                CultureInfo current_culture;
                CultureInfo current_ui_culture;
 
@@ -156,6 +158,9 @@ namespace System.Threading {
 
                static NamedDataSlot namedDataSlot;             
 
+               static internal CultureInfo default_culture;
+               static internal CultureInfo default_ui_culture;
+
                // can be both a ThreadStart and a ParameterizedThreadStart
                private MulticastDelegate threadstart;
                //private string thread_name=null;
@@ -401,12 +406,10 @@ namespace System.Threading {
                        ResetAbort_internal ();
                }
 
-#if NET_4_0
                [HostProtectionAttribute (SecurityAction.LinkDemand, Synchronization = true, ExternalThreading = true)]
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                [ReliabilityContract (Consistency.WillNotCorruptState, Cer.Success)]
                public extern static bool Yield ();
-#endif
 
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
@@ -470,11 +473,13 @@ namespace System.Threading {
                public CultureInfo CurrentCulture {
                        get {
                                CultureInfo culture = current_culture;
-                               if (culture != null)
+                               if (current_culture_set && culture != null)
                                        return culture;
 
+                               if (default_culture != null)
+                                       return default_culture;
+
                                current_culture = culture = CultureInfo.ConstructCurrentCulture ();
-                               NumberFormatter.SetThreadCurrentCulture (culture);
                                return culture;
                        }
                        
@@ -485,16 +490,19 @@ namespace System.Threading {
 
                                value.CheckNeutral ();
                                current_culture = value;
-                               NumberFormatter.SetThreadCurrentCulture (value);
+                               current_culture_set = true;
                        }
                }
 
                public CultureInfo CurrentUICulture {
                        get {
                                CultureInfo culture = current_ui_culture;
-                               if (culture != null)
+                               if (current_ui_culture_set && culture != null)
                                        return culture;
 
+                               if (default_ui_culture != null)
+                                       return default_ui_culture;
+
                                current_ui_culture = culture = CultureInfo.ConstructCurrentUICulture ();
                                return culture;
                        }
@@ -503,6 +511,7 @@ namespace System.Threading {
                                if (value == null)
                                        throw new ArgumentNullException ("value");
                                current_ui_culture = value;
+                               current_ui_culture_set = true;
                        }
                }
 
@@ -576,11 +585,12 @@ namespace System.Threading {
 
                public ThreadPriority Priority {
                        get {
-                               return(ThreadPriority.Lowest);
+                               return (ThreadPriority)GetPriority (Internal);
                        }
                        
                        set {
-                               // FIXME: Implement setter.
+                               // FIXME: This doesn't do anything yet
+                               SetPriority (Internal, (int)value);
                        }
                }
 
@@ -593,6 +603,12 @@ namespace System.Threading {
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                private extern static void Abort_internal (InternalThread thread, object stateInfo);
 
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static int GetPriority (InternalThread thread);
+
+               [MethodImplAttribute(MethodImplOptions.InternalCall)]
+               private extern static void SetPriority (InternalThread thread, int priority);
+
                [SecurityPermission (SecurityAction.Demand, ControlThread=true)]
                public void Abort () 
                {
@@ -685,8 +701,7 @@ namespace System.Threading {
 
                public void Start() {
                        // propagate informations from the original thread to the new thread
-                       if (!ExecutionContext.IsFlowSuppressed ())
-                               ec_to_set = ExecutionContext.Capture ();
+                       ec_to_set = ExecutionContext.Capture (false, true);
                        Internal._serialized_principal = CurrentThread.Internal._serialized_principal;
 
                        // Thread_internal creates and starts the new thread, 
@@ -801,6 +816,8 @@ namespace System.Threading {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                extern public static void VolatileWrite (ref UIntPtr address, UIntPtr value);
                
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               extern static int SystemMaxStackStize ();
 
                static int CheckStackSize (int maxStackSize)
                {
@@ -815,12 +832,8 @@ namespace System.Threading {
                        if ((maxStackSize % page_size) != 0) // round up to a divisible of page size
                                maxStackSize = (maxStackSize / (page_size - 1)) * page_size;
 
-                       int default_stack_size = (IntPtr.Size / 4) * 1024 * 1024; // from wthreads.c
-
-                       if (maxStackSize > default_stack_size)
-                               return default_stack_size;
-
-                       return maxStackSize; 
+                       /* Respect the max stack size imposed by the system*/
+                       return Math.Min (maxStackSize, SystemMaxStackStize ());
                }
 
                public Thread (ThreadStart start, int maxStackSize)
@@ -849,7 +862,6 @@ namespace System.Threading {
                        Internal.stack_size = CheckStackSize (maxStackSize);
                }
 
-               [MonoTODO ("limited to CompressedStack support")]
                public ExecutionContext ExecutionContext {
                        [ReliabilityContract (Consistency.WillNotCorruptState, Cer.MayFail)]
                        get {
@@ -857,6 +869,35 @@ namespace System.Threading {
                                        _ec = new ExecutionContext ();
                                return _ec;
                        }
+                       internal set {
+                               _ec = value;
+                       }
+               }
+
+               internal bool HasExecutionContext {
+                       get {
+                               return _ec != null;
+                       }
+               }
+
+               internal void BranchExecutionContext (out ExecutionContext.Switcher switcher)
+               {
+                       if (_ec == null) {
+                               switcher =  new ExecutionContext.Switcher ();
+                       } else {
+                               switcher = new ExecutionContext.Switcher (_ec);
+                               _ec.CopyOnWrite = true;
+                       }
+               }
+
+               internal void RestoreExecutionContext (ref ExecutionContext.Switcher switcher)
+               {
+                       if (switcher.IsEmpty) {
+                               _ec = null;
+                               return;
+                       }
+
+                       switcher.Restore (_ec);
                }
 
                public int ManagedThreadId {
@@ -903,11 +944,7 @@ namespace System.Threading {
 
                public bool TrySetApartmentState (ApartmentState state) 
                {
-                       /* Only throw this exception when changing the
-                        * state of another thread.  See bug 324338
-                        */
-                       if ((this != CurrentThread) &&
-                           (ThreadState & ThreadState.Unstarted) == 0)
+                       if ((ThreadState & ThreadState.Unstarted) == 0)
                                throw new ThreadStateException ("Thread was in an invalid state for the operation being executed.");
 
                        if ((ApartmentState)Internal.apartment_state != ApartmentState.Unknown && 
@@ -987,5 +1024,10 @@ namespace System.Threading {
                        throw new NotImplementedException ();
                }
 #endif
+
+               internal CultureInfo GetCurrentUICultureNoAppX ()
+               {
+                       return CultureInfo.CurrentUICulture;
+               }
        }
 }