From: Filip Navara Date: Wed, 27 Feb 2019 06:48:33 +0000 (+0100) Subject: Move Thread to shared CoreLib (#22744) X-Git-Tag: accepted/tizen/unified/20190813.215958~61^2~130 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a94826d9aac0eae32c5cc59ad0e013d8dc3e0817;p=platform%2Fupstream%2Fcoreclr.git Move Thread to shared CoreLib (#22744) * Move Thread to shared CoreLib * Remove all local variables from Thread in shared code * Remove duplicate checks * Port back CoreRT changes needed for shared code * Fix missing culture initialization in ThreadStart() * Adjust for shared WaitHandle --- diff --git a/src/System.Private.CoreLib/Resources/Strings.resx b/src/System.Private.CoreLib/Resources/Strings.resx index f769f6c..155cb43 100644 --- a/src/System.Private.CoreLib/Resources/Strings.resx +++ b/src/System.Private.CoreLib/Resources/Strings.resx @@ -166,6 +166,15 @@ The ApplicationBase must be set before retrieving this property. + + Name: + + + There are no context policies. + + + Default principal object cannot be set twice. + Ambiguous implementation found. @@ -226,6 +235,9 @@ The usage of IKeyComparer and IHashCodeProvider/IComparer interfaces cannot be mixed; use one or the other. + + Attempt to unload the AppDomain failed. + Failed to resolve type from string "{0}" which was embedded in custom attribute blob. @@ -547,6 +559,9 @@ Type must be a type provided by the runtime. + + Argument must be true. + Object must be of type UInt16. @@ -826,6 +841,9 @@ Array or pointer types are not valid. + + Attribute names must be unique. + Interface method must be abstract and virtual. @@ -1138,6 +1156,18 @@ The DigitSubstitution property must be of a valid member of the DigitShapes enumeration. Valid entries include Context, NativeNational or None. + + Invalid element name '{0}'. + + + Invalid element tag '{0}'. + + + Invalid element text '{0}'. + + + Invalid element value '{0}'. + The Enum type should contain one and only one instance field. @@ -1603,6 +1633,9 @@ Buffer cannot be null. + + Cannot have a null child. + Collection cannot be null. @@ -2644,6 +2677,9 @@ Type has not been created. + + This range in the underlying list is invalid. A possible cause is that elements were removed. + Unknown enum type. @@ -2992,6 +3028,9 @@ A Primary Interop Assembly is not supported in AppX. + + The specified operation is not supported on Ranges. + Accessor does not support reading. @@ -3187,6 +3226,24 @@ Marshalling an IDispatchEx to an IReflect or IExpando is not supported on this platform. + + Secondary AppDomains are not supported on this platform. + + + Code Access Security is not supported on this platform. + + + AppDomain resource monitoring is not supported on this platform. + + + Windows Principal functionality is not supported on this platform. + + + Thread abort is not supported on this platform. + + + Thread suspend is not supported on this platform. + All assemblies loaded as part of AppDomain initialization must be fully trusted. @@ -3490,6 +3547,15 @@ An attempt was made to transition a task to a final state when it had already completed. + + Failed to set the specified COM apartment state. + + + Use CompressedStack.(Capture/Run) instead. + + + This operation must be performed on the same thread as that represented by the Thread instance. + The wait completed due to an abandoned mutex. diff --git a/src/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/System.Private.CoreLib.csproj index 595ed87..55bf8b4 100644 --- a/src/System.Private.CoreLib/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/System.Private.CoreLib.csproj @@ -115,7 +115,6 @@ - @@ -257,7 +256,7 @@ - + diff --git a/src/System.Private.CoreLib/shared/Internal/Runtime/Augments/RuntimeThread.cs b/src/System.Private.CoreLib/shared/Internal/Runtime/Augments/RuntimeThread.cs new file mode 100644 index 0000000..5e811c0 --- /dev/null +++ b/src/System.Private.CoreLib/shared/Internal/Runtime/Augments/RuntimeThread.cs @@ -0,0 +1,56 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; +using System.Security; +using System.Threading; + +namespace Internal.Runtime.Augments +{ + public class RuntimeThread : CriticalFinalizerObject + { + private Thread _thread; + [ThreadStatic] + private static RuntimeThread t_currentThread; + + private RuntimeThread(Thread thread) + { + _thread = thread; + } + + public static RuntimeThread Create(ThreadStart start) => new RuntimeThread(new Thread(start)); + public static RuntimeThread Create(ThreadStart start, int maxStackSize) => new RuntimeThread(new Thread(start, maxStackSize)); + public static RuntimeThread Create(ParameterizedThreadStart start) => new RuntimeThread(new Thread(start)); + public static RuntimeThread Create(ParameterizedThreadStart start, int maxStackSize) => new RuntimeThread(new Thread(start, maxStackSize)); + + public static RuntimeThread CurrentThread => t_currentThread ?? (t_currentThread = new RuntimeThread(Thread.CurrentThread)); + + public bool IsAlive => _thread.IsAlive; + public bool IsBackground { get => _thread.IsBackground; set => _thread.IsBackground = value; } + public bool IsThreadPoolThread => _thread.IsThreadPoolThread; + public int ManagedThreadId => _thread.ManagedThreadId; + public string Name { get => _thread.Name; set => _thread.Name = value; } + public ThreadPriority Priority { get => _thread.Priority; set => _thread.Priority = value; } + public ThreadState ThreadState => _thread.ThreadState; + + public ApartmentState GetApartmentState() => _thread.GetApartmentState(); + public bool TrySetApartmentState(ApartmentState state) => _thread.TrySetApartmentState(state); + public void DisableComObjectEagerCleanup() => _thread.DisableComObjectEagerCleanup(); + public void Interrupt() => _thread.Interrupt(); + public void Join() => _thread.Join(); + public bool Join(int millisecondsTimeout) => _thread.Join(millisecondsTimeout); + + public static void Sleep(int millisecondsTimeout) => Thread.Sleep(millisecondsTimeout); + public static int GetCurrentProcessorId() => Thread.GetCurrentProcessorId(); + public static void SpinWait(int iterations) => Thread.SpinWait(iterations); + public static bool Yield() => Thread.Yield(); + + public void Start() => _thread.Start(); + public void Start(object parameter) => _thread.Start(parameter); + } +} diff --git a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems index 0389fb6..77b9589 100644 --- a/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems +++ b/src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems @@ -21,6 +21,7 @@ + @@ -31,6 +32,8 @@ + + @@ -118,9 +121,11 @@ + + @@ -340,6 +345,7 @@ + @@ -707,10 +713,19 @@ + + + + + + + + + @@ -784,6 +799,7 @@ + @@ -807,6 +823,7 @@ + @@ -1037,6 +1054,7 @@ + @@ -1185,6 +1203,7 @@ + diff --git a/src/System.Private.CoreLib/shared/System/AppDomain.cs b/src/System.Private.CoreLib/shared/System/AppDomain.cs index 93f6a2b..fe3706b 100644 --- a/src/System.Private.CoreLib/shared/System/AppDomain.cs +++ b/src/System.Private.CoreLib/shared/System/AppDomain.cs @@ -16,6 +16,9 @@ using System.Threading; namespace System { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public sealed partial class AppDomain : MarshalByRefObject { private static readonly AppDomain s_domain = new AppDomain(); @@ -85,7 +88,7 @@ namespace System } if (assemblyName.Length == 0 || assemblyName[0] == '\0') { - throw new ArgumentException(SR.ZeroLengthString); + throw new ArgumentException(SR.Argument_StringZeroLength, nameof(assemblyName)); } return assemblyName; @@ -120,7 +123,7 @@ namespace System MethodInfo entry = assembly.EntryPoint; if (entry == null) { - throw new MissingMethodException(SR.EntryPointNotFound + assembly.FullName); + throw new MissingMethodException(SR.Arg_EntryPointNotFoundException); } object result = entry.Invoke( @@ -165,7 +168,7 @@ namespace System { throw new ArgumentNullException(nameof(domain)); } - throw new CannotUnloadAppDomainException(SR.NotSupported_Platform); + throw new CannotUnloadAppDomainException(SR.Arg_PlatformNotSupported); } public Assembly Load(byte[] rawAssembly) => Assembly.Load(rawAssembly); diff --git a/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs b/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs index 2b8e71e..c278e72 100644 --- a/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs +++ b/src/System.Private.CoreLib/shared/System/AppDomainSetup.cs @@ -4,6 +4,9 @@ namespace System { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public sealed class AppDomainSetup { internal AppDomainSetup() { } diff --git a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs index 3b65ccb..1a933a5 100644 --- a/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs +++ b/src/System.Private.CoreLib/shared/System/Buffers/TlsOverPerCoreLockedStacksArrayPool.cs @@ -6,7 +6,6 @@ using System; using System.Collections.Generic; using System.Runtime.CompilerServices; using System.Threading; -using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; namespace System.Buffers @@ -346,7 +345,7 @@ namespace System.Buffers // Try to push on to the associated stack first. If that fails, // round-robin through the other stacks. LockedStack[] stacks = _perCoreStacks; - int index = RuntimeThread.GetCurrentProcessorId() % stacks.Length; + int index = Thread.GetCurrentProcessorId() % stacks.Length; for (int i = 0; i < stacks.Length; i++) { if (stacks[index].TryPush(array)) return; @@ -362,7 +361,7 @@ namespace System.Buffers // round-robin through the other stacks. T[] arr; LockedStack[] stacks = _perCoreStacks; - int index = RuntimeThread.GetCurrentProcessorId() % stacks.Length; + int index = Thread.GetCurrentProcessorId() % stacks.Length; for (int i = 0; i < stacks.Length; i++) { if ((arr = stacks[index].TryPop()) != null) return arr; diff --git a/src/System.Private.CoreLib/shared/System/CannotUnloadAppDomainException.cs b/src/System.Private.CoreLib/shared/System/CannotUnloadAppDomainException.cs index f8dce02..9a4fb14 100644 --- a/src/System.Private.CoreLib/shared/System/CannotUnloadAppDomainException.cs +++ b/src/System.Private.CoreLib/shared/System/CannotUnloadAppDomainException.cs @@ -8,6 +8,9 @@ namespace System { [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public class CannotUnloadAppDomainException : SystemException { internal const int COR_E_CANNOTUNLOADAPPDOMAIN = unchecked((int)0x80131015); // corresponds to __HResults.COR_E_CANNOTUNLOADAPPDOMAIN in corelib diff --git a/src/System.Private.CoreLib/shared/System/Collections/ArrayList.cs b/src/System.Private.CoreLib/shared/System/Collections/ArrayList.cs index 124df2b..d2ccc23 100644 --- a/src/System.Private.CoreLib/shared/System/Collections/ArrayList.cs +++ b/src/System.Private.CoreLib/shared/System/Collections/ArrayList.cs @@ -28,6 +28,9 @@ namespace System.Collections [DebuggerDisplay("Count = {Count}")] [Serializable] [System.Runtime.CompilerServices.TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")] +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public class ArrayList : IList, ICloneable { private object[] _items; // Do not rename (binary serialization) @@ -449,7 +452,7 @@ namespace System.Collections public virtual void Insert(int index, object value) { // Note that insertions at the end are legal. - if (index < 0 || index > _size) throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_ArrayListInsert); + if (index < 0 || index > _size) throw new ArgumentOutOfRangeException(nameof(index), SR.ArgumentOutOfRange_Index); if (_size == _items.Length) EnsureCapacity(_size + 1); if (index < _size) diff --git a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs index 47cc8f7..0a1eb78 100644 --- a/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs +++ b/src/System.Private.CoreLib/shared/System/Diagnostics/Tracing/EventSource.cs @@ -182,7 +182,6 @@ using System.Security.Permissions; using System.Text; using System.Threading; using Microsoft.Win32; -using Internal.Runtime.Augments; #if ES_BUILD_STANDALONE using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor; @@ -2803,11 +2802,7 @@ namespace System.Diagnostics.Tracing // 5 chunks, so only the largest manifests will hit the pause. if ((envelope.ChunkNumber % 5) == 0) { -#if ES_BUILD_STANDALONE Thread.Sleep(15); -#else - RuntimeThread.Sleep(15); -#endif } } } @@ -4685,7 +4680,7 @@ namespace System.Diagnostics.Tracing { if (!m_osThreadId.HasValue) { - m_osThreadId = (long)RuntimeThread.CurrentOSThreadId; + m_osThreadId = (long)Thread.CurrentOSThreadId; } return m_osThreadId.Value; diff --git a/src/System.Private.CoreLib/shared/System/Environment.Unix.cs b/src/System.Private.CoreLib/shared/System/Environment.Unix.cs index 65a0260..00b5029 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.Unix.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Internal.Runtime.Augments; using System.Collections; using System.Collections.Generic; using System.Diagnostics; diff --git a/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs b/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs index a8e3dbc..3d86829 100644 --- a/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs +++ b/src/System.Private.CoreLib/shared/System/Environment.WinRT.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. using System.IO; -using Internal.Runtime.Augments; namespace System { diff --git a/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs b/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs index dae59bc..ae9a741 100644 --- a/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs +++ b/src/System.Private.CoreLib/shared/System/LocalDataStoreSlot.cs @@ -6,6 +6,9 @@ using System.Threading; namespace System { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Threading.Thread")] +#endif public sealed class LocalDataStoreSlot { internal LocalDataStoreSlot(ThreadLocal data) diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs index aef62e8..6f38bdb 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/AsyncMethodBuilder.cs @@ -19,10 +19,6 @@ using System.Threading.Tasks; using System.Text; using Internal.Runtime.CompilerServices; -#if CORERT -using Thread = Internal.Runtime.Augments.RuntimeThread; -#endif - namespace System.Runtime.CompilerServices { /// diff --git a/src/System.Private.CoreLib/shared/System/Security/IPermission.cs b/src/System.Private.CoreLib/shared/System/Security/IPermission.cs index a882c0f..cfdf1eb 100644 --- a/src/System.Private.CoreLib/shared/System/Security/IPermission.cs +++ b/src/System.Private.CoreLib/shared/System/Security/IPermission.cs @@ -4,6 +4,9 @@ namespace System.Security { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public partial interface IPermission : ISecurityEncodable { IPermission Copy(); diff --git a/src/System.Private.CoreLib/shared/System/Security/ISecurityEncodable.cs b/src/System.Private.CoreLib/shared/System/Security/ISecurityEncodable.cs index 844bb04..62cdb3f 100644 --- a/src/System.Private.CoreLib/shared/System/Security/ISecurityEncodable.cs +++ b/src/System.Private.CoreLib/shared/System/Security/ISecurityEncodable.cs @@ -4,6 +4,9 @@ namespace System.Security { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public partial interface ISecurityEncodable { void FromXml(SecurityElement e); diff --git a/src/System.Private.CoreLib/shared/System/Security/IStackWalk.cs b/src/System.Private.CoreLib/shared/System/Security/IStackWalk.cs index f8d472e..9e6986a 100644 --- a/src/System.Private.CoreLib/shared/System/Security/IStackWalk.cs +++ b/src/System.Private.CoreLib/shared/System/Security/IStackWalk.cs @@ -4,6 +4,9 @@ namespace System.Security { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public partial interface IStackWalk { void Assert(); diff --git a/src/System.Private.CoreLib/shared/System/Security/PermissionSet.cs b/src/System.Private.CoreLib/shared/System/Security/PermissionSet.cs index 5c07248..9de469d 100644 --- a/src/System.Private.CoreLib/shared/System/Security/PermissionSet.cs +++ b/src/System.Private.CoreLib/shared/System/Security/PermissionSet.cs @@ -8,6 +8,9 @@ using System.Runtime.Serialization; namespace System.Security { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public partial class PermissionSet : ICollection, IEnumerable, IDeserializationCallback, ISecurityEncodable, IStackWalk { public PermissionSet(PermissionState state) { } diff --git a/src/System.Private.CoreLib/shared/System/Security/Permissions/PermissionState.cs b/src/System.Private.CoreLib/shared/System/Security/Permissions/PermissionState.cs index aace3dc..3ce1e70 100644 --- a/src/System.Private.CoreLib/shared/System/Security/Permissions/PermissionState.cs +++ b/src/System.Private.CoreLib/shared/System/Security/Permissions/PermissionState.cs @@ -4,6 +4,9 @@ namespace System.Security.Permissions { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public enum PermissionState { None = 0, diff --git a/src/System.Private.CoreLib/shared/System/Security/Principal/IIdentity.cs b/src/System.Private.CoreLib/shared/System/Security/Principal/IIdentity.cs index a25a976..177f2b8 100644 --- a/src/System.Private.CoreLib/shared/System/Security/Principal/IIdentity.cs +++ b/src/System.Private.CoreLib/shared/System/Security/Principal/IIdentity.cs @@ -10,6 +10,9 @@ using System; namespace System.Security.Principal { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Security.Principal")] +#endif public interface IIdentity { // Access to the name string diff --git a/src/System.Private.CoreLib/shared/System/Security/Principal/PrincipalPolicy.cs b/src/System.Private.CoreLib/shared/System/Security/Principal/PrincipalPolicy.cs index 53a8ba7..3884b10 100644 --- a/src/System.Private.CoreLib/shared/System/Security/Principal/PrincipalPolicy.cs +++ b/src/System.Private.CoreLib/shared/System/Security/Principal/PrincipalPolicy.cs @@ -9,6 +9,9 @@ namespace System.Security.Principal { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Security.Principal")] +#endif public enum PrincipalPolicy { // Note: it's important that the default policy has the value 0. diff --git a/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs b/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs index 7af11e9..9b0b37f 100644 --- a/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs +++ b/src/System.Private.CoreLib/shared/System/Security/SecurityElement.cs @@ -10,6 +10,9 @@ using System.Text; namespace System.Security { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif internal interface ISecurityElementFactory { SecurityElement CreateSecurityElement(); @@ -21,6 +24,9 @@ namespace System.Security string Attribute(string attributeName); } +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")] +#endif public sealed class SecurityElement : ISecurityElementFactory { internal string _tag; diff --git a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs index 348bb2d..2529997 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/ExecutionContext.cs @@ -16,8 +16,6 @@ using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.Serialization; -using Thread = Internal.Runtime.Augments.RuntimeThread; - namespace System.Threading { public delegate void ContextCallback(object state); diff --git a/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs index 9424fbd..9776871 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/ReaderWriterLockSlim.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Internal.Runtime.Augments; using System.Diagnostics; // for TraceInformation using System.Runtime.CompilerServices; @@ -1241,11 +1240,11 @@ namespace System.Threading //Exponential back-off if ((spinCount < 5) && (ProcessorCount > 1)) { - RuntimeThread.SpinWait(LockSpinCycles * spinCount); + Thread.SpinWait(LockSpinCycles * spinCount); } else { - RuntimeThread.Sleep(0); + Thread.Sleep(0); } // Don't want to Sleep(1) in this spin wait: @@ -1592,15 +1591,15 @@ namespace System.Threading { if (spinIndex < LockSpinCount && processorCount > 1) { - RuntimeThread.SpinWait(LockSpinCycles * (spinIndex + 1)); // Wait a few dozen instructions to let another processor release lock. + Thread.SpinWait(LockSpinCycles * (spinIndex + 1)); // Wait a few dozen instructions to let another processor release lock. } else if (spinIndex < (LockSpinCount + LockSleep0Count)) { - RuntimeThread.Sleep(0); // Give up my quantum. + Thread.Sleep(0); // Give up my quantum. } else { - RuntimeThread.Sleep(1); // Give up my quantum. + Thread.Sleep(1); // Give up my quantum. } if (!IsEnterDeprioritized(reason)) diff --git a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs index d726353..c7dacef 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/SemaphoreSlim.cs @@ -5,8 +5,6 @@ using System.Diagnostics; using System.Threading.Tasks; -using Thread = Internal.Runtime.Augments.RuntimeThread; - namespace System.Threading { /// diff --git a/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs b/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs index 01e71d1..88b4b41 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/SpinWait.cs @@ -9,7 +9,6 @@ // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- using System.Diagnostics; -using Internal.Runtime.Augments; namespace System.Threading { @@ -195,18 +194,18 @@ namespace System.Threading if (_count >= sleep1Threshold && sleep1Threshold >= 0) { - RuntimeThread.Sleep(1); + Thread.Sleep(1); } else { int yieldsSoFar = _count >= YieldThreshold ? (_count - YieldThreshold) / 2 : _count; if ((yieldsSoFar % Sleep0EveryHowManyYields) == (Sleep0EveryHowManyYields - 1)) { - RuntimeThread.Sleep(0); + Thread.Sleep(0); } else { - RuntimeThread.Yield(); + Thread.Yield(); } } } @@ -228,15 +227,15 @@ namespace System.Threading // allow other useful work to run. Long YieldProcessor() loops can help to reduce contention, but Sleep(1) is // usually better for that. // - // RuntimeThread.OptimalMaxSpinWaitsPerSpinIteration: + // Thread.OptimalMaxSpinWaitsPerSpinIteration: // - See Thread::InitializeYieldProcessorNormalized(), which describes and calculates this value. // - int n = RuntimeThread.OptimalMaxSpinWaitsPerSpinIteration; + int n = Thread.OptimalMaxSpinWaitsPerSpinIteration; if (_count <= 30 && (1 << _count) < n) { n = 1 << _count; } - RuntimeThread.SpinWait(n); + Thread.SpinWait(n); } // Finally, increment our spin counter. diff --git a/src/System.Private.CoreLib/shared/System/Threading/SynchronizationContext.cs b/src/System.Private.CoreLib/shared/System/Threading/SynchronizationContext.cs index 33e025d..6f8bddf 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/SynchronizationContext.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/SynchronizationContext.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Thread = Internal.Runtime.Augments.RuntimeThread; - namespace System.Threading { public partial class SynchronizationContext diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs index e207a74..df7c934 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ConcurrentExclusiveSchedulerPair.cs @@ -18,8 +18,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; -using Thread = Internal.Runtime.Augments.RuntimeThread; - namespace System.Threading.Tasks { /// diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs index 5ad074c..a4c9619 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/Task.cs @@ -16,13 +16,8 @@ using System.Diagnostics; using System.Diagnostics.Tracing; using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; -using Internal.Runtime.Augments; using Internal.Runtime.CompilerServices; -#if CORERT -using Thread = Internal.Runtime.Augments.RuntimeThread; -#endif - namespace System.Threading.Tasks { /// diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs index 034d19d..63ae2bd 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskContinuation.cs @@ -7,10 +7,6 @@ using System.Diagnostics; using System.Runtime.ExceptionServices; using System.Runtime.CompilerServices; -#if CORERT -using Thread = Internal.Runtime.Augments.RuntimeThread; -#endif - namespace System.Threading.Tasks { // Task type used to implement: Task ContinueWith(Action) diff --git a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs index 339a9d8..9ab28ef 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Tasks/ThreadPoolTaskScheduler.cs @@ -17,8 +17,6 @@ using System.Diagnostics; using System.Collections.Generic; using System.Text; -using Internal.Runtime.Augments; - namespace System.Threading.Tasks { /// @@ -47,7 +45,7 @@ namespace System.Threading.Tasks if ((options & TaskCreationOptions.LongRunning) != 0) { // Run LongRunning tasks on their own dedicated thread. - RuntimeThread thread = RuntimeThread.Create(s_longRunningThreadWork); + Thread thread = new Thread(s_longRunningThreadWork); thread.IsBackground = true; // Keep this thread from blocking process shutdown thread.Start(task); } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Thread.Unix.cs b/src/System.Private.CoreLib/shared/System/Threading/Thread.Unix.cs index 252969e..902fcf2 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Thread.Unix.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Thread.Unix.cs @@ -8,10 +8,6 @@ namespace System.Threading { public sealed partial class Thread { - public ApartmentState GetApartmentState() => ApartmentState.Unknown; - private static Exception GetApartmentStateChangeFailedException() => new PlatformNotSupportedException(SR.PlatformNotSupported_COMInterop); - private bool TrySetApartmentStateUnchecked(ApartmentState state) => state == GetApartmentState(); - - public void DisableComObjectEagerCleanup() { } + private static Exception GetApartmentStateChangeFailedException() => new PlatformNotSupportedException(SR.PlatformNotSupported_ComInterop); } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Thread.Windows.cs b/src/System.Private.CoreLib/shared/System/Threading/Thread.Windows.cs index 6738158..44e5f38 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Thread.Windows.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Thread.Windows.cs @@ -8,11 +8,7 @@ namespace System.Threading { public sealed partial class Thread { - public ApartmentState GetApartmentState() => _runtimeThread.GetApartmentState(); private static Exception GetApartmentStateChangeFailedException() => new InvalidOperationException(SR.Thread_ApartmentState_ChangeFailed); - private bool TrySetApartmentStateUnchecked(ApartmentState state) => _runtimeThread.TrySetApartmentState(state); - - public void DisableComObjectEagerCleanup() => _runtimeThread.DisableComObjectEagerCleanup(); } } diff --git a/src/System.Private.CoreLib/shared/System/Threading/Thread.cs b/src/System.Private.CoreLib/shared/System/Threading/Thread.cs index e9e654a..0705daa 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Thread.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Thread.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Internal.Runtime.Augments; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; @@ -11,36 +10,26 @@ using System.Security.Principal; namespace System.Threading { +#if PROJECTN + [Internal.Runtime.CompilerServices.RelocatedType("System.Threading.Thread")] +#endif public sealed partial class Thread : CriticalFinalizerObject { - [ThreadStatic] - private static Thread t_currentThread; private static AsyncLocal s_asyncLocalPrincipal; - private readonly RuntimeThread _runtimeThread; - private Delegate _start; - private CultureInfo _startCulture; - private CultureInfo _startUICulture; - - private Thread(RuntimeThread runtimeThread) - { - Debug.Assert(runtimeThread != null); - _runtimeThread = runtimeThread; - } - public Thread(ThreadStart start) + : this() { if (start == null) { throw new ArgumentNullException(nameof(start)); } - _runtimeThread = RuntimeThread.Create(ThreadMain_ThreadStart); - Debug.Assert(_runtimeThread != null); - _start = start; + Create(start); } public Thread(ThreadStart start, int maxStackSize) + : this() { if (start == null) { @@ -48,27 +37,25 @@ namespace System.Threading } if (maxStackSize < 0) { - throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonnegativeNumber); + throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum); } - _runtimeThread = RuntimeThread.Create(ThreadMain_ThreadStart, maxStackSize); - Debug.Assert(_runtimeThread != null); - _start = start; + Create(start, maxStackSize); } public Thread(ParameterizedThreadStart start) + : this() { if (start == null) { throw new ArgumentNullException(nameof(start)); } - _runtimeThread = RuntimeThread.Create(ThreadMain_ParameterizedThreadStart); - Debug.Assert(_runtimeThread != null); - _start = start; + Create(start); } public Thread(ParameterizedThreadStart start, int maxStackSize) + : this() { if (start == null) { @@ -76,57 +63,10 @@ namespace System.Threading } if (maxStackSize < 0) { - throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonnegativeNumber); - } - - _runtimeThread = RuntimeThread.Create(ThreadMain_ParameterizedThreadStart, maxStackSize); - Debug.Assert(_runtimeThread != null); - _start = start; - } - - private Delegate InitializeNewThread() - { - t_currentThread = this; - - Delegate start = _start; - _start = null; - - if (_startCulture != null) - { - CultureInfo.CurrentCulture = _startCulture; - _startCulture = null; + throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum); } - if (_startUICulture != null) - { - CultureInfo.CurrentUICulture = _startUICulture; - _startUICulture = null; - } - - return start; - } - - private void ThreadMain_ThreadStart() - { - ((ThreadStart)InitializeNewThread())(); - } - - private void ThreadMain_ParameterizedThreadStart(object parameter) - { - ((ParameterizedThreadStart)InitializeNewThread())(parameter); - } - - public static Thread CurrentThread - { - get - { - Thread currentThread = t_currentThread; - if (currentThread == null) - { - t_currentThread = currentThread = new Thread(RuntimeThread.CurrentThread); - } - return currentThread; - } + Create(start, maxStackSize); } private void RequireCurrentThread() @@ -137,17 +77,17 @@ namespace System.Threading } } - private void SetCultureOnUnstartedThread(CultureInfo value, ref CultureInfo culture) + private void SetCultureOnUnstartedThread(CultureInfo value, bool uiCulture) { if (value == null) { throw new ArgumentNullException(nameof(value)); } - if ((_runtimeThread.ThreadState & ThreadState.Unstarted) == 0) + if ((ThreadState & ThreadState.Unstarted) == 0) { throw new InvalidOperationException(SR.Thread_Operation_RequiresCurrentThread); } - culture = value; + SetCultureOnUnstartedThreadNoCheck(value, uiCulture); } public CultureInfo CurrentCulture @@ -161,7 +101,7 @@ namespace System.Threading { if (this != CurrentThread) { - SetCultureOnUnstartedThread(value, ref _startCulture); + SetCultureOnUnstartedThread(value, uiCulture: false); return; } CultureInfo.CurrentCulture = value; @@ -179,7 +119,7 @@ namespace System.Threading { if (this != CurrentThread) { - SetCultureOnUnstartedThread(value, ref _startUICulture); + SetCultureOnUnstartedThread(value, uiCulture: true); return; } CultureInfo.CurrentUICulture = value; @@ -210,15 +150,6 @@ namespace System.Threading } } - public ExecutionContext ExecutionContext => ExecutionContext.Capture(); - public bool IsAlive => _runtimeThread.IsAlive; - public bool IsBackground { get { return _runtimeThread.IsBackground; } set { _runtimeThread.IsBackground = value; } } - public bool IsThreadPoolThread => _runtimeThread.IsThreadPoolThread; - public int ManagedThreadId => _runtimeThread.ManagedThreadId; - public string Name { get { return _runtimeThread.Name; } set { _runtimeThread.Name = value; } } - public ThreadPriority Priority { get { return _runtimeThread.Priority; } set { _runtimeThread.Priority = value; } } - public ThreadState ThreadState => _runtimeThread.ThreadState; - public void Abort() { throw new PlatformNotSupportedException(SR.PlatformNotSupported_ThreadAbort); @@ -297,16 +228,6 @@ namespace System.Threading return TrySetApartmentStateUnchecked(state); } - private static int ToTimeoutMilliseconds(TimeSpan timeout) - { - var timeoutMilliseconds = (long)timeout.TotalMilliseconds; - if (timeoutMilliseconds < -1 || timeoutMilliseconds > int.MaxValue) - { - throw new ArgumentOutOfRangeException(nameof(timeout), SR.ArgumentOutOfRange_TimeoutMilliseconds); - } - return (int)timeoutMilliseconds; - } - [Obsolete("Thread.GetCompressedStack is no longer supported. Please use the System.Threading.CompressedStack class")] public CompressedStack GetCompressedStack() { @@ -319,21 +240,13 @@ namespace System.Threading throw new InvalidOperationException(SR.Thread_GetSetCompressedStack_NotSupported); } - public static int GetCurrentProcessorId() => RuntimeThread.GetCurrentProcessorId(); public static AppDomain GetDomain() => AppDomain.CurrentDomain; - public static int GetDomainID() => GetDomain().Id; + public static int GetDomainID() => 1; public override int GetHashCode() => ManagedThreadId; - public void Interrupt() => _runtimeThread.Interrupt(); - public void Join() => _runtimeThread.Join(); - public bool Join(int millisecondsTimeout) => _runtimeThread.Join(millisecondsTimeout); - public bool Join(TimeSpan timeout) => Join(ToTimeoutMilliseconds(timeout)); + public void Join() => Join(-1); + public bool Join(TimeSpan timeout) => Join(WaitHandle.ToTimeoutMilliseconds(timeout)); public static void MemoryBarrier() => Interlocked.MemoryBarrier(); - public static void Sleep(int millisecondsTimeout) => RuntimeThread.Sleep(millisecondsTimeout); - public static void Sleep(TimeSpan timeout) => Sleep(ToTimeoutMilliseconds(timeout)); - public static void SpinWait(int iterations) => RuntimeThread.SpinWait(iterations); - public static bool Yield() => RuntimeThread.Yield(); - public void Start() => _runtimeThread.Start(); - public void Start(object parameter) => _runtimeThread.Start(parameter); + public static void Sleep(TimeSpan timeout) => Sleep(WaitHandle.ToTimeoutMilliseconds(timeout)); public static byte VolatileRead(ref byte address) => Volatile.Read(ref address); public static double VolatileRead(ref double address) => Volatile.Read(ref address); diff --git a/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs b/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs index ffcab54..017a8e7 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/ThreadPool.cs @@ -22,8 +22,6 @@ using System.Runtime.InteropServices; using System.Threading.Tasks; using Internal.Runtime.CompilerServices; -using Thread = Internal.Runtime.Augments.RuntimeThread; - namespace System.Threading { internal static class ThreadPoolGlobals diff --git a/src/System.Private.CoreLib/shared/System/Threading/Timer.cs b/src/System.Private.CoreLib/shared/System/Threading/Timer.cs index 3dfb5d9..180bcb5 100644 --- a/src/System.Private.CoreLib/shared/System/Threading/Timer.cs +++ b/src/System.Private.CoreLib/shared/System/Threading/Timer.cs @@ -2,13 +2,10 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -using Internal.Runtime.Augments; using System.Diagnostics; using System.Diagnostics.Tracing; using System.Threading.Tasks; -using Thread = Internal.Runtime.Augments.RuntimeThread; - namespace System.Threading { public delegate void TimerCallback(object state); @@ -446,7 +443,7 @@ namespace System.Threading { _executionContext = ExecutionContext.Capture(); } - _associatedTimerQueue = TimerQueue.Instances[RuntimeThread.GetCurrentProcessorId() % TimerQueue.Instances.Length]; + _associatedTimerQueue = TimerQueue.Instances[Thread.GetCurrentProcessorId() % TimerQueue.Instances.Length]; // After the following statement, the timer may fire. No more manipulation of timer state outside of // the lock is permitted beyond this point! diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs deleted file mode 100644 index 89e6396..0000000 --- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs +++ /dev/null @@ -1,287 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.ConstrainedExecution; -using System.Runtime.InteropServices; -using System.Security; -using System.Threading; - -namespace Internal.Runtime.Augments -{ - public class RuntimeThread : CriticalFinalizerObject - { - private static int s_optimalMaxSpinWaitsPerSpinIteration; - - internal RuntimeThread() { } - - public static RuntimeThread Create(ThreadStart start) => new Thread(start); - public static RuntimeThread Create(ThreadStart start, int maxStackSize) => new Thread(start, maxStackSize); - public static RuntimeThread Create(ParameterizedThreadStart start) => new Thread(start); - public static RuntimeThread Create(ParameterizedThreadStart start, int maxStackSize) => new Thread(start, maxStackSize); - - private Thread AsThread() - { - Debug.Assert(this is Thread); - return (Thread)this; - } - - public static RuntimeThread CurrentThread => Thread.CurrentThread; - - /*========================================================================= - ** Returns true if the thread has been started and is not dead. - =========================================================================*/ - public extern bool IsAlive - { - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } - - /*========================================================================= - ** Return whether or not this thread is a background thread. Background - ** threads do not affect when the Execution Engine shuts down. - ** - ** Exceptions: ThreadStateException if the thread is dead. - =========================================================================*/ - public bool IsBackground - { - get { return IsBackgroundNative(); } - set { SetBackgroundNative(value); } - } - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern bool IsBackgroundNative(); - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern void SetBackgroundNative(bool isBackground); - - /*========================================================================= - ** Returns true if the thread is a threadpool thread. - =========================================================================*/ - public extern bool IsThreadPoolThread - { - [MethodImpl(MethodImplOptions.InternalCall)] - get; - } - - public int ManagedThreadId => AsThread().ManagedThreadId; - public string Name { get { return AsThread().Name; } set { AsThread().Name = value; } } - - /*========================================================================= - ** Returns the priority of the thread. - ** - ** Exceptions: ThreadStateException if the thread is dead. - =========================================================================*/ - public ThreadPriority Priority - { - get { return (ThreadPriority)GetPriorityNative(); } - set { SetPriorityNative((int)value); } - } - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern int GetPriorityNative(); - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern void SetPriorityNative(int priority); - - /*========================================================================= - ** Returns the operating system identifier for the current thread. - =========================================================================*/ - internal static ulong CurrentOSThreadId - { - get - { - return GetCurrentOSThreadId(); - } - } - [DllImport(JitHelpers.QCall)] - private static extern ulong GetCurrentOSThreadId(); - - /*========================================================================= - ** Return the thread state as a consistent set of bits. This is more - ** general then IsAlive or IsBackground. - =========================================================================*/ - public ThreadState ThreadState - { - get { return (ThreadState)GetThreadStateNative(); } - } - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern int GetThreadStateNative(); - - public ApartmentState GetApartmentState() - { -#if FEATURE_COMINTEROP_APARTMENT_SUPPORT - return (ApartmentState)GetApartmentStateNative(); -#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT - Debug.Assert(false); // the Thread class in CoreFX should have handled this case - return ApartmentState.MTA; -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - } - - /*========================================================================= - ** An unstarted thread can be marked to indicate that it will host a - ** single-threaded or multi-threaded apartment. - =========================================================================*/ - public bool TrySetApartmentState(ApartmentState state) - { -#if FEATURE_COMINTEROP_APARTMENT_SUPPORT - return SetApartmentStateHelper(state, false); -#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT - Debug.Assert(false); // the Thread class in CoreFX should have handled this case - return false; -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - } - -#if FEATURE_COMINTEROP_APARTMENT_SUPPORT - internal bool SetApartmentStateHelper(ApartmentState state, bool fireMDAOnMismatch) - { - ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state, fireMDAOnMismatch); - - // Special case where we pass in Unknown and get back MTA. - // Once we CoUninitialize the thread, the OS will still - // report the thread as implicitly in the MTA if any - // other thread in the process is CoInitialized. - if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA)) - return true; - - if (retState != state) - return false; - - return true; - } - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern int GetApartmentStateNative(); - - [MethodImpl(MethodImplOptions.InternalCall)] - internal extern int SetApartmentStateNative(int state, bool fireMDAOnMismatch); -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - -#if FEATURE_COMINTEROP - [MethodImpl(MethodImplOptions.InternalCall)] - public extern void DisableComObjectEagerCleanup(); -#else // !FEATURE_COMINTEROP - public void DisableComObjectEagerCleanup() - { - Debug.Assert(false); // the Thread class in CoreFX should have handled this case - } -#endif // FEATURE_COMINTEROP - - /*========================================================================= - ** 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 - ** when it next begins to block. - =========================================================================*/ - public void Interrupt() => InterruptInternal(); - - // Internal helper (since we can't place security demands on - // ecalls/fcalls). - [MethodImpl(MethodImplOptions.InternalCall)] - private extern void InterruptInternal(); - - /*========================================================================= - ** 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 - ** Timeout.Infinite is given as the parameter, no timeout will occur. - ** - ** Exceptions: ArgumentException if timeout < -1 (Timeout.Infinite). - ** ThreadInterruptedException if the thread is interrupted while waiting. - ** ThreadStateException if the thread has not been started yet. - =========================================================================*/ - public void Join() => JoinInternal(Timeout.Infinite); - - public bool Join(int millisecondsTimeout) => JoinInternal(millisecondsTimeout); - - [MethodImpl(MethodImplOptions.InternalCall)] - private extern bool JoinInternal(int millisecondsTimeout); - - public static void Sleep(int millisecondsTimeout) => Thread.Sleep(millisecondsTimeout); - - [DllImport(JitHelpers.QCall)] - private static extern int GetOptimalMaxSpinWaitsPerSpinIterationInternal(); - - /// - /// Max value to be passed into for optimal delaying. This value is normalized to be - /// appropriate for the processor. - /// - internal static int OptimalMaxSpinWaitsPerSpinIteration - { - get - { - if (s_optimalMaxSpinWaitsPerSpinIteration != 0) - { - return s_optimalMaxSpinWaitsPerSpinIteration; - } - - // This is done lazily because the first call to the function below in the process triggers a measurement that - // takes a nontrivial amount of time if the measurement has not already been done in the backgorund. - // See Thread::InitializeYieldProcessorNormalized(), which describes and calculates this value. - s_optimalMaxSpinWaitsPerSpinIteration = GetOptimalMaxSpinWaitsPerSpinIterationInternal(); - Debug.Assert(s_optimalMaxSpinWaitsPerSpinIteration > 0); - return s_optimalMaxSpinWaitsPerSpinIteration; - } - } - - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern int GetCurrentProcessorNumber(); - - // The upper bits of t_currentProcessorIdCache are the currentProcessorId. The lower bits of - // the t_currentProcessorIdCache are counting down to get it periodically refreshed. - // TODO: Consider flushing the currentProcessorIdCache on Wait operations or similar - // actions that are likely to result in changing the executing core - [ThreadStatic] - private static int t_currentProcessorIdCache; - - private const int ProcessorIdCacheShift = 16; - private const int ProcessorIdCacheCountDownMask = (1 << ProcessorIdCacheShift) - 1; - private const int ProcessorIdRefreshRate = 5000; - - private static int RefreshCurrentProcessorId() - { - int currentProcessorId = GetCurrentProcessorNumber(); - - // On Unix, GetCurrentProcessorNumber() is implemented in terms of sched_getcpu, which - // doesn't exist on all platforms. On those it doesn't exist on, GetCurrentProcessorNumber() - // returns -1. As a fallback in that case and to spread the threads across the buckets - // by default, we use the current managed thread ID as a proxy. - if (currentProcessorId < 0) currentProcessorId = Environment.CurrentManagedThreadId; - - // Add offset to make it clear that it is not guaranteed to be 0-based processor number - currentProcessorId += 100; - - Debug.Assert(ProcessorIdRefreshRate <= ProcessorIdCacheCountDownMask); - - // Mask with int.MaxValue to ensure the execution Id is not negative - t_currentProcessorIdCache = ((currentProcessorId << ProcessorIdCacheShift) & int.MaxValue) | ProcessorIdRefreshRate; - - return currentProcessorId; - } - - // Cached processor id used as a hint for which per-core stack to access. It is periodically - // refreshed to trail the actual thread core affinity. - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static int GetCurrentProcessorId() - { - int currentProcessorIdCache = t_currentProcessorIdCache--; - if ((currentProcessorIdCache & ProcessorIdCacheCountDownMask) == 0) - return RefreshCurrentProcessorId(); - return (currentProcessorIdCache >> ProcessorIdCacheShift); - } - - public static void SpinWait(int iterations) => Thread.SpinWait(iterations); - public static bool Yield() => Thread.Yield(); - - public void Start() => AsThread().Start(); - public void Start(object parameter) => AsThread().Start(parameter); - - public void ResetThreadPoolThread() - { - // Currently implemented in unmanaged method Thread::InternalReset and - // called internally from the ThreadPool in NotifyWorkItemComplete. - } - } -} diff --git a/src/System.Private.CoreLib/src/System/Threading/Thread.cs b/src/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs similarity index 51% rename from src/System.Private.CoreLib/src/System/Threading/Thread.cs rename to src/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs index 45c7f9c..d4b0015 100644 --- a/src/System.Private.CoreLib/src/System/Threading/Thread.cs +++ b/src/System.Private.CoreLib/src/System/Threading/Thread.CoreCLR.cs @@ -2,35 +2,26 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -// -/*============================================================================= -** -** -** -** Purpose: Class for creating and managing a thread. -** -** -=============================================================================*/ - -using Internal.Runtime.Augments; +using System; +using System.Diagnostics; +using System.Globalization; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Runtime.InteropServices; namespace System.Threading { - using System.Runtime.InteropServices; - using System; - using System.Globalization; - using System.Runtime.CompilerServices; - using System.Runtime.ConstrainedExecution; - using System.Diagnostics; - internal class ThreadHelper { private Delegate _start; + internal CultureInfo _startCulture; + internal CultureInfo _startUICulture; private object _startArg = null; private ExecutionContext _executionContext = null; + internal ThreadHelper(Delegate start) { - _start = start; + _start = start; } internal void SetExecutionContextHelper(ExecutionContext ec) @@ -53,10 +44,28 @@ namespace System.Threading } } + private void InitializeCulture() + { + if (_startCulture != null) + { + CultureInfo.CurrentCulture = _startCulture; + _startCulture = null; + } + + if (_startUICulture != null) + { + CultureInfo.CurrentUICulture = _startUICulture; + _startUICulture = null; + } + } + // call back helper internal void ThreadStart(object obj) { _startArg = obj; + + InitializeCulture(); + ExecutionContext context = _executionContext; if (context != null) { @@ -71,6 +80,8 @@ namespace System.Threading // call back helper internal void ThreadStart() { + InitializeCulture(); + ExecutionContext context = _executionContext; if (context != null) { @@ -93,7 +104,7 @@ namespace System.Threading } } - internal sealed class Thread : RuntimeThread + public sealed partial class Thread { /*========================================================================= ** Data accessed from managed code that needs to be defined in @@ -143,51 +154,27 @@ namespace System.Threading ** ** Exceptions: ArgumentNullException if start == null. =========================================================================*/ - public Thread(ThreadStart start) + private void Create(ThreadStart start) { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } SetStartHelper((Delegate)start, 0); //0 will setup Thread with default stackSize } - internal Thread(ThreadStart start, int maxStackSize) + private void Create(ThreadStart start, int maxStackSize) { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } - if (0 > maxStackSize) - throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum); SetStartHelper((Delegate)start, maxStackSize); } - public Thread(ParameterizedThreadStart start) + + private void Create(ParameterizedThreadStart start) { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } SetStartHelper((Delegate)start, 0); } - internal Thread(ParameterizedThreadStart start, int maxStackSize) + private void Create(ParameterizedThreadStart start, int maxStackSize) { - if (start == null) - { - throw new ArgumentNullException(nameof(start)); - } - if (0 > maxStackSize) - throw new ArgumentOutOfRangeException(nameof(maxStackSize), SR.ArgumentOutOfRange_NeedNonNegNum); SetStartHelper((Delegate)start, maxStackSize); } - public override int GetHashCode() - { - return _managedThreadId; - } - - public extern new int ManagedThreadId + public extern int ManagedThreadId { [MethodImplAttribute(MethodImplOptions.InternalCall)] get; @@ -215,7 +202,7 @@ namespace System.Threading ** ** Exceptions: ThreadStateException if the thread has already been started. =========================================================================*/ - public new void Start(object parameter) + public void Start(object parameter) { //In the case of a null delegate (second call to start on same thread) // StartInternal method will take care of the error reporting @@ -230,7 +217,7 @@ namespace System.Threading Start(); } - public new void Start() + public void Start() { #if FEATURE_COMINTEROP_APARTMENT_SUPPORT // Eagerly initialize the COM Apartment state of the thread if we're allowed to. @@ -252,6 +239,21 @@ namespace System.Threading StartInternal(); } + private void SetCultureOnUnstartedThreadNoCheck(CultureInfo value, bool uiCulture) + { + Debug.Assert(m_Delegate != null); + + ThreadHelper t = (ThreadHelper)(m_Delegate.Target); + if (uiCulture) + { + t._startUICulture = value; + } + else + { + t._startCulture = value; + } + } + internal ExecutionContext ExecutionContext { get { return m_ExecutionContext; } @@ -285,20 +287,11 @@ namespace System.Threading [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void SleepInternal(int millisecondsTimeout); - public static new void Sleep(int millisecondsTimeout) + public static void Sleep(int millisecondsTimeout) { SleepInternal(millisecondsTimeout); } - public static void Sleep(TimeSpan timeout) - { - long tm = (long)timeout.TotalMilliseconds; - if (tm < -1 || tm > (long)int.MaxValue) - throw new ArgumentOutOfRangeException(nameof(timeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); - Sleep((int)tm); - } - - /* wait for a length of time proportional to 'iterations'. Each iteration is should only take a few machine instructions. Calling this API is preferable to coding a explicit busy loop because the hardware can be informed that it is busy waiting. */ @@ -306,7 +299,7 @@ namespace System.Threading [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void SpinWaitInternal(int iterations); - public static new void SpinWait(int iterations) + public static void SpinWait(int iterations) { SpinWaitInternal(iterations); } @@ -314,12 +307,12 @@ namespace System.Threading [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern bool YieldInternal(); - internal static new bool Yield() + public static bool Yield() { return YieldInternal(); } - public static new Thread CurrentThread => t_currentThread ?? InitializeCurrentThread(); + public static Thread CurrentThread => t_currentThread ?? InitializeCurrentThread(); [MethodImpl(MethodImplOptions.NoInlining)] private static Thread InitializeCurrentThread() @@ -369,18 +362,9 @@ namespace System.Threading private extern void StartupSetApartmentStateInternal(); #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT - /* - * This returns a unique id to identify an appdomain. - */ - internal static int GetDomainID() - { - return 1; - } - - // Retrieves the name of the thread. // - public new string Name + public string Name { get { @@ -402,6 +386,242 @@ namespace System.Threading [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] private static extern void InformThreadNameChange(ThreadHandle t, string name, int len); + /*========================================================================= + ** Returns true if the thread has been started and is not dead. + =========================================================================*/ + public extern bool IsAlive + { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + /*========================================================================= + ** Return whether or not this thread is a background thread. Background + ** threads do not affect when the Execution Engine shuts down. + ** + ** Exceptions: ThreadStateException if the thread is dead. + =========================================================================*/ + public bool IsBackground + { + get { return IsBackgroundNative(); } + set { SetBackgroundNative(value); } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern bool IsBackgroundNative(); + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void SetBackgroundNative(bool isBackground); + + /*========================================================================= + ** Returns true if the thread is a threadpool thread. + =========================================================================*/ + public extern bool IsThreadPoolThread + { + [MethodImpl(MethodImplOptions.InternalCall)] + get; + } + + /*========================================================================= + ** Returns the priority of the thread. + ** + ** Exceptions: ThreadStateException if the thread is dead. + =========================================================================*/ + public ThreadPriority Priority + { + get { return (ThreadPriority)GetPriorityNative(); } + set { SetPriorityNative((int)value); } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern int GetPriorityNative(); + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern void SetPriorityNative(int priority); + + /*========================================================================= + ** Returns the operating system identifier for the current thread. + =========================================================================*/ + internal static ulong CurrentOSThreadId + { + get + { + return GetCurrentOSThreadId(); + } + } + + [DllImport(JitHelpers.QCall)] + private static extern ulong GetCurrentOSThreadId(); + + /*========================================================================= + ** Return the thread state as a consistent set of bits. This is more + ** general then IsAlive or IsBackground. + =========================================================================*/ + public ThreadState ThreadState + { + get { return (ThreadState)GetThreadStateNative(); } + } + + [MethodImpl(MethodImplOptions.InternalCall)] + private extern int GetThreadStateNative(); + + public ApartmentState GetApartmentState() + { +#if FEATURE_COMINTEROP_APARTMENT_SUPPORT + return (ApartmentState)GetApartmentStateNative(); +#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT + Debug.Assert(false); // the Thread class in CoreFX should have handled this case + return ApartmentState.MTA; +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + } + + /*========================================================================= + ** An unstarted thread can be marked to indicate that it will host a + ** single-threaded or multi-threaded apartment. + =========================================================================*/ + public bool TrySetApartmentStateUnchecked(ApartmentState state) + { +#if FEATURE_COMINTEROP_APARTMENT_SUPPORT + return SetApartmentStateHelper(state, false); +#else // !FEATURE_COMINTEROP_APARTMENT_SUPPORT + Debug.Assert(false); // the Thread class in CoreFX should have handled this case + return false; +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + } + +#if FEATURE_COMINTEROP_APARTMENT_SUPPORT + internal bool SetApartmentStateHelper(ApartmentState state, bool fireMDAOnMismatch) + { + ApartmentState retState = (ApartmentState)SetApartmentStateNative((int)state, fireMDAOnMismatch); + + // Special case where we pass in Unknown and get back MTA. + // Once we CoUninitialize the thread, the OS will still + // report the thread as implicitly in the MTA if any + // other thread in the process is CoInitialized. + if ((state == System.Threading.ApartmentState.Unknown) && (retState == System.Threading.ApartmentState.MTA)) + return true; + + if (retState != state) + return false; + + return true; + } + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern int GetApartmentStateNative(); + + [MethodImpl(MethodImplOptions.InternalCall)] + internal extern int SetApartmentStateNative(int state, bool fireMDAOnMismatch); +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT + +#if FEATURE_COMINTEROP + [MethodImpl(MethodImplOptions.InternalCall)] + public extern void DisableComObjectEagerCleanup(); +#else // !FEATURE_COMINTEROP + public void DisableComObjectEagerCleanup() + { + } +#endif // FEATURE_COMINTEROP + + /// + /// 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 + /// when it next begins to block. + /// + [MethodImpl(MethodImplOptions.InternalCall)] + public extern void Interrupt(); + + /// + /// 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 + /// -1 is given as the parameter, no timeout will occur. + /// + /// if timeout < -1 (Timeout.Infinite) + /// if the thread is interrupted while waiting + /// if the thread has not been started yet + [MethodImpl(MethodImplOptions.InternalCall)] + public extern bool Join(int millisecondsTimeout); + + private static int s_optimalMaxSpinWaitsPerSpinIteration; + + [DllImport(JitHelpers.QCall)] + private static extern int GetOptimalMaxSpinWaitsPerSpinIterationInternal(); + + /// + /// Max value to be passed into for optimal delaying. This value is normalized to be + /// appropriate for the processor. + /// + internal static int OptimalMaxSpinWaitsPerSpinIteration + { + get + { + if (s_optimalMaxSpinWaitsPerSpinIteration != 0) + { + return s_optimalMaxSpinWaitsPerSpinIteration; + } + + // This is done lazily because the first call to the function below in the process triggers a measurement that + // takes a nontrivial amount of time if the measurement has not already been done in the backgorund. + // See Thread::InitializeYieldProcessorNormalized(), which describes and calculates this value. + s_optimalMaxSpinWaitsPerSpinIteration = GetOptimalMaxSpinWaitsPerSpinIterationInternal(); + Debug.Assert(s_optimalMaxSpinWaitsPerSpinIteration > 0); + return s_optimalMaxSpinWaitsPerSpinIteration; + } + } + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private static extern int GetCurrentProcessorNumber(); + + // The upper bits of t_currentProcessorIdCache are the currentProcessorId. The lower bits of + // the t_currentProcessorIdCache are counting down to get it periodically refreshed. + // TODO: Consider flushing the currentProcessorIdCache on Wait operations or similar + // actions that are likely to result in changing the executing core + [ThreadStatic] + private static int t_currentProcessorIdCache; + + private const int ProcessorIdCacheShift = 16; + private const int ProcessorIdCacheCountDownMask = (1 << ProcessorIdCacheShift) - 1; + private const int ProcessorIdRefreshRate = 5000; + + private static int RefreshCurrentProcessorId() + { + int currentProcessorId = GetCurrentProcessorNumber(); + + // On Unix, GetCurrentProcessorNumber() is implemented in terms of sched_getcpu, which + // doesn't exist on all platforms. On those it doesn't exist on, GetCurrentProcessorNumber() + // returns -1. As a fallback in that case and to spread the threads across the buckets + // by default, we use the current managed thread ID as a proxy. + if (currentProcessorId < 0) currentProcessorId = Environment.CurrentManagedThreadId; + + // Add offset to make it clear that it is not guaranteed to be 0-based processor number + currentProcessorId += 100; + + Debug.Assert(ProcessorIdRefreshRate <= ProcessorIdCacheCountDownMask); + + // Mask with int.MaxValue to ensure the execution Id is not negative + t_currentProcessorIdCache = ((currentProcessorId << ProcessorIdCacheShift) & int.MaxValue) | ProcessorIdRefreshRate; + + return currentProcessorId; + } + + // Cached processor id used as a hint for which per-core stack to access. It is periodically + // refreshed to trail the actual thread core affinity. + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static int GetCurrentProcessorId() + { + int currentProcessorIdCache = t_currentProcessorIdCache--; + if ((currentProcessorIdCache & ProcessorIdCacheCountDownMask) == 0) + return RefreshCurrentProcessorId(); + return (currentProcessorIdCache >> ProcessorIdCacheShift); + } + + internal void ResetThreadPoolThread() + { + // Currently implemented in unmanaged method Thread::InternalReset and + // called internally from the ThreadPool in NotifyWorkItemComplete. + } } // End of class Thread // declaring a local var of this enum type and passing it by ref into a function that needs to do a diff --git a/src/vm/ecalllist.h b/src/vm/ecalllist.h index 30492d1..43049a3 100644 --- a/src/vm/ecalllist.h +++ b/src/vm/ecalllist.h @@ -620,7 +620,22 @@ FCFuncStart(gMathFFuncs) FCIntrinsic("Tanh", COMSingle::Tanh, CORINFO_INTRINSIC_Tanh) FCFuncEnd() -FCFuncStart(gRuntimeThreadFuncs) +FCFuncStart(gThreadFuncs) + FCDynamic("InternalGetCurrentThread", CORINFO_INTRINSIC_Illegal, ECall::InternalGetCurrentThread) + FCFuncElement("StartInternal", ThreadNative::Start) +#undef Sleep + FCFuncElement("SleepInternal", ThreadNative::Sleep) +#define Sleep(a) Dont_Use_Sleep(a) + FCFuncElement("SetStart", ThreadNative::SetStart) + QCFuncElement("InformThreadNameChange", ThreadNative::InformThreadNameChange) + FCFuncElement("SpinWaitInternal", ThreadNative::SpinWait) + QCFuncElement("YieldInternal", ThreadNative::YieldThread) + FCIntrinsic("GetCurrentThreadNative", ThreadNative::GetCurrentThread, CORINFO_INTRINSIC_GetCurrentManagedThread) + FCIntrinsic("get_ManagedThreadId", ThreadNative::GetManagedThreadId, CORINFO_INTRINSIC_GetManagedThreadId) + FCFuncElement("InternalFinalize", ThreadNative::Finalize) +#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT + FCFuncElement("StartupSetApartmentStateInternal", ThreadNative::StartupSetApartmentState) +#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT FCFuncElement("get_IsAlive", ThreadNative::IsAlive) FCFuncElement("IsBackgroundNative", ThreadNative::IsBackground) FCFuncElement("SetBackgroundNative", ThreadNative::SetBackground) @@ -636,30 +651,12 @@ FCFuncStart(gRuntimeThreadFuncs) #ifdef FEATURE_COMINTEROP FCFuncElement("DisableComObjectEagerCleanup", ThreadNative::DisableComObjectEagerCleanup) #endif // FEATURE_COMINTEROP - FCFuncElement("InterruptInternal", ThreadNative::Interrupt) - FCFuncElement("JoinInternal", ThreadNative::Join) + FCFuncElement("Interrupt", ThreadNative::Interrupt) + FCFuncElement("Join", ThreadNative::Join) QCFuncElement("GetOptimalMaxSpinWaitsPerSpinIterationInternal", ThreadNative::GetOptimalMaxSpinWaitsPerSpinIteration) FCFuncElement("GetCurrentProcessorNumber", ThreadNative::GetCurrentProcessorNumber) FCFuncEnd() -FCFuncStart(gThreadFuncs) - FCDynamic("InternalGetCurrentThread", CORINFO_INTRINSIC_Illegal, ECall::InternalGetCurrentThread) - FCFuncElement("StartInternal", ThreadNative::Start) -#undef Sleep - FCFuncElement("SleepInternal", ThreadNative::Sleep) -#define Sleep(a) Dont_Use_Sleep(a) - FCFuncElement("SetStart", ThreadNative::SetStart) - QCFuncElement("InformThreadNameChange", ThreadNative::InformThreadNameChange) - FCFuncElement("SpinWaitInternal", ThreadNative::SpinWait) - QCFuncElement("YieldInternal", ThreadNative::YieldThread) - FCIntrinsic("GetCurrentThreadNative", ThreadNative::GetCurrentThread, CORINFO_INTRINSIC_GetCurrentManagedThread) - FCIntrinsic("get_ManagedThreadId", ThreadNative::GetManagedThreadId, CORINFO_INTRINSIC_GetManagedThreadId) - FCFuncElement("InternalFinalize", ThreadNative::Finalize) -#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT - FCFuncElement("StartupSetApartmentStateInternal", ThreadNative::StartupSetApartmentState) -#endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT -FCFuncEnd() - FCFuncStart(gThreadPoolFuncs) FCFuncElement("PostQueuedCompletionStatus", ThreadPoolNative::CorPostQueuedCompletionStatus) FCFuncElement("GetAvailableThreadsNative", ThreadPoolNative::CorGetAvailableThreads) @@ -1269,7 +1266,6 @@ FCClassElement("RuntimeHelpers", "System.Runtime.CompilerServices", gRuntimeHelp FCClassElement("RuntimeImports", "System.Runtime", gRuntimeImportsFuncs) FCClassElement("RuntimeMethodHandle", "System", gRuntimeMethodHandle) FCClassElement("RuntimeModule", "System.Reflection", gCOMModuleFuncs) -FCClassElement("RuntimeThread", "Internal.Runtime.Augments", gRuntimeThreadFuncs) FCClassElement("RuntimeType", "System", gSystem_RuntimeType) FCClassElement("RuntimeTypeHandle", "System", gCOMTypeHandleFuncs) FCClassElement("SafeTypeNameParserHandle", "System", gSafeTypeNameParserHandle) diff --git a/tests/src/baseservices/threading/coverage/OSThreadId/OSThreadId.cs b/tests/src/baseservices/threading/coverage/OSThreadId/OSThreadId.cs index 85895a7..af9a055 100644 --- a/tests/src/baseservices/threading/coverage/OSThreadId/OSThreadId.cs +++ b/tests/src/baseservices/threading/coverage/OSThreadId/OSThreadId.cs @@ -15,7 +15,7 @@ namespace Threading.Tests public static int Main(string[] args) { // The property to be tested is internal. - Type runtimeThreadType = typeof(object).Assembly.GetType("Internal.Runtime.Augments.RuntimeThread"); + Type runtimeThreadType = typeof(object).Assembly.GetType("System.Threading.Thread"); Assert(runtimeThreadType != null); PropertyInfo osThreadIdProperty = runtimeThreadType.GetProperty("CurrentOSThreadId", BindingFlags.NonPublic | BindingFlags.Static); Assert(osThreadIdProperty != null);