<data name="AppDomain_AppBaseNotSet" xml:space="preserve">
<value>The ApplicationBase must be set before retrieving this property.</value>
</data>
+ <data name="AppDomain_Name" xml:space="preserve">
+ <value>Name:</value>
+ </data>
+ <data name="AppDomain_NoContextPolicies" xml:space="preserve">
+ <value>There are no context policies.</value>
+ </data>
+ <data name="AppDomain_Policy_PrincipalTwice" xml:space="preserve">
+ <value>Default principal object cannot be set twice.</value>
+ </data>
<data name="AmbiguousImplementationException_NullMessage" xml:space="preserve">
<value>Ambiguous implementation found.</value>
</data>
<data name="Arg_CannotMixComparisonInfrastructure" xml:space="preserve">
<value>The usage of IKeyComparer and IHashCodeProvider/IComparer interfaces cannot be mixed; use one or the other.</value>
</data>
+ <data name="Arg_CannotUnloadAppDomainException" xml:space="preserve">
+ <value>Attempt to unload the AppDomain failed.</value>
+ </data>
<data name="Arg_CATypeResolutionFailed" xml:space="preserve">
<value>Failed to resolve type from string "{0}" which was embedded in custom attribute blob.</value>
</data>
<data name="Arg_MustBeType" xml:space="preserve">
<value>Type must be a type provided by the runtime.</value>
</data>
+ <data name="Arg_MustBeTrue" xml:space="preserve">
+ <value>Argument must be true.</value>
+ </data>
<data name="Arg_MustBeUInt16" xml:space="preserve">
<value>Object must be of type UInt16.</value>
</data>
<data name="Argument_ArraysInvalid" xml:space="preserve">
<value>Array or pointer types are not valid.</value>
</data>
+ <data name="Argument_AttributeNamesMustBeUnique" xml:space="preserve">
+ <value>Attribute names must be unique.</value>
+ </data>
<data name="Argument_BadAttributeOnInterfaceMethod" xml:space="preserve">
<value>Interface method must be abstract and virtual.</value>
</data>
<data name="Argument_InvalidDigitSubstitution" xml:space="preserve">
<value>The DigitSubstitution property must be of a valid member of the DigitShapes enumeration. Valid entries include Context, NativeNational or None.</value>
</data>
+ <data name="Argument_InvalidElementName" xml:space="preserve">
+ <value>Invalid element name '{0}'.</value>
+ </data>
+ <data name="Argument_InvalidElementTag" xml:space="preserve">
+ <value>Invalid element tag '{0}'.</value>
+ </data>
+ <data name="Argument_InvalidElementText" xml:space="preserve">
+ <value>Invalid element text '{0}'.</value>
+ </data>
+ <data name="Argument_InvalidElementValue" xml:space="preserve">
+ <value>Invalid element value '{0}'.</value>
+ </data>
<data name="Argument_InvalidEnum" xml:space="preserve">
<value>The Enum type should contain one and only one instance field.</value>
</data>
<data name="ArgumentNull_Buffer" xml:space="preserve">
<value>Buffer cannot be null.</value>
</data>
+ <data name="ArgumentNull_Child" xml:space="preserve">
+ <value>Cannot have a null child.</value>
+ </data>
<data name="ArgumentNull_Collection" xml:space="preserve">
<value>Collection cannot be null.</value>
</data>
<data name="InvalidOperation_TypeNotCreated" xml:space="preserve">
<value>Type has not been created.</value>
</data>
+ <data name="InvalidOperation_UnderlyingArrayListChanged" xml:space="preserve">
+ <value>This range in the underlying list is invalid. A possible cause is that elements were removed.</value>
+ </data>
<data name="InvalidOperation_UnknownEnumType" xml:space="preserve">
<value>Unknown enum type.</value>
</data>
<data name="NotSupported_PIAInAppxProcess" xml:space="preserve">
<value>A Primary Interop Assembly is not supported in AppX.</value>
</data>
+ <data name="NotSupported_RangeCollection" xml:space="preserve">
+ <value>The specified operation is not supported on Ranges.</value>
+ </data>
<data name="NotSupported_Reading" xml:space="preserve">
<value>Accessor does not support reading.</value>
</data>
<data name="PlatformNotSupported_IExpando" xml:space="preserve">
<value>Marshalling an IDispatchEx to an IReflect or IExpando is not supported on this platform.</value>
</data>
+ <data name="PlatformNotSupported_AppDomains" xml:space="preserve">
+ <value>Secondary AppDomains are not supported on this platform.</value>
+ </data>
+ <data name="PlatformNotSupported_CAS" xml:space="preserve">
+ <value>Code Access Security is not supported on this platform.</value>
+ </data>
+ <data name="PlatformNotSupported_AppDomain_ResMon" xml:space="preserve">
+ <value>AppDomain resource monitoring is not supported on this platform.</value>
+ </data>
+ <data name="PlatformNotSupported_Principal" xml:space="preserve">
+ <value>Windows Principal functionality is not supported on this platform.</value>
+ </data>
+ <data name="PlatformNotSupported_ThreadAbort" xml:space="preserve">
+ <value>Thread abort is not supported on this platform.</value>
+ </data>
+ <data name="PlatformNotSupported_ThreadSuspend" xml:space="preserve">
+ <value>Thread suspend is not supported on this platform.</value>
+ </data>
<data name="Policy_CannotLoadSemiTrustAssembliesDuringInit" xml:space="preserve">
<value>All assemblies loaded as part of AppDomain initialization must be fully trusted.</value>
</data>
<data name="TaskT_TransitionToFinal_AlreadyCompleted" xml:space="preserve">
<value>An attempt was made to transition a task to a final state when it had already completed.</value>
</data>
+ <data name="Thread_ApartmentState_ChangeFailed" xml:space="preserve">
+ <value>Failed to set the specified COM apartment state.</value>
+ </data>
+ <data name="Thread_GetSetCompressedStack_NotSupported" xml:space="preserve">
+ <value>Use CompressedStack.(Capture/Run) instead.</value>
+ </data>
+ <data name="Thread_Operation_RequiresCurrentThread" xml:space="preserve">
+ <value>This operation must be performed on the same thread as that represented by the Thread instance.</value>
+ </data>
<data name="Threading_AbandonedMutexException" xml:space="preserve">
<value>The wait completed due to an abandoned mutex.</value>
</data>
<!-- Sources -->
<ItemGroup>
<Compile Include="$(BclSourcesRoot)\Internal\Console.cs" />
- <Compile Include="$(BclSourcesRoot)\Internal\Runtime\Augments\RuntimeThread.cs" />
<Compile Include="$(BclSourcesRoot)\Microsoft\Win32\UnsafeNativeMethods.cs" />
<Compile Include="$(BclSourcesRoot)\System\__Canon.cs" />
<Compile Include="$(BclSourcesRoot)\System\Activator.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Monitor.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Overlapped.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\SynchronizationContext.CoreCLR.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Threading\Thread.cs" />
+ <Compile Include="$(BclSourcesRoot)\System\Threading\Thread.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ThreadPool.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\Timer.CoreCLR.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\WaitHandle.CoreCLR.cs" />
+++ /dev/null
-// 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();
-
- /// <summary>
- /// Max value to be passed into <see cref="SpinWait(int)"/> for optimal delaying. This value is normalized to be
- /// appropriate for the processor.
- /// </summary>
- 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.
- }
- }
-}
// 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)
}
}
+ 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)
{
// call back helper
internal void ThreadStart()
{
+ InitializeCulture();
+
ExecutionContext context = _executionContext;
if (context != null)
{
}
}
- internal sealed class Thread : RuntimeThread
+ public sealed partial class Thread
{
/*=========================================================================
** Data accessed from managed code that needs to be defined in
**
** 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;
**
** 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
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.
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; }
[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. */
[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);
}
[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()
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
{
[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
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public extern void Interrupt();
+
+ /// <summary>
+ /// Waits for the thread to die or for timeout milliseconds to elapse.
+ /// </summary>
+ /// <returns>
+ /// Returns true if the thread died, or false if the wait timed out. If
+ /// -1 is given as the parameter, no timeout will occur.
+ /// </returns>
+ /// <exception cref="ArgumentException">if timeout < -1 (Timeout.Infinite)</exception>
+ /// <exception cref="ThreadInterruptedException">if the thread is interrupted while waiting</exception>
+ /// <exception cref="ThreadStateException">if the thread has not been started yet</exception>
+ [MethodImpl(MethodImplOptions.InternalCall)]
+ public extern bool Join(int millisecondsTimeout);
+
+ private static int s_optimalMaxSpinWaitsPerSpinIteration;
+
+ [DllImport(JitHelpers.QCall)]
+ private static extern int GetOptimalMaxSpinWaitsPerSpinIterationInternal();
+
+ /// <summary>
+ /// Max value to be passed into <see cref="SpinWait(int)"/> for optimal delaying. This value is normalized to be
+ /// appropriate for the processor.
+ /// </summary>
+ 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
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)
#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)
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)
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);
--- /dev/null
+// 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);
+ }
+}
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Internal\Padding.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)Internal\Runtime\Augments\RuntimeThread.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Internal\Runtime\CompilerServices\Unsafe.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Internal\Threading\Tasks\AsyncCausalitySupport.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\CriticalHandleMinusOneIsInvalid.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Action.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\AccessViolationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\AppContext.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\AppDomain.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\AppDomainSetup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ApplicationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\AggregateException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ArgumentException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Buffers\Text\Utf8Parser\Utf8Parser.TimeSpanSplitter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Byte.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\ByReference.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\CannotUnloadAppDomainException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Char.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CharEnumerator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\CLSCompliantAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Collections\ArrayList.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Comparer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Concurrent\ConcurrentQueue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Collections\Concurrent\ConcurrentQueueSegment.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Lazy.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LocalAppContextSwitches.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\LocalAppContextSwitches.Common.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\LocalDataStoreSlot.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Marvin.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Marvin.OrdinalIgnoreCase.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Math.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\SByte.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\AllowPartiallyTrustedCallersAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\CryptographicException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\IPermission.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\ISecurityEncodable.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\IStackWalk.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\PartialTrustVisibilityLevel.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\PermissionSet.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\Permissions\PermissionState.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\Principal\IIdentity.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\Principal\IPrincipal.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\Principal\PrincipalPolicy.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecurityCriticalAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecurityCriticalScope.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Security\SecurityElement.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecurityException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecurityRulesAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecurityRuleSet.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\CancellationToken.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\CancellationTokenRegistration.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\CancellationTokenSource.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\CompressedStack.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\DeferredDisposableLifetime.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventResetMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\EventWaitHandle.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SpinWait.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationContext.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\SynchronizationLockException.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\ThreadLocal.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Volatile.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\AsyncCausalityTracerConstants.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Windows.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Windows.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Windows.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Windows.cs" />
</ItemGroup>
<ItemGroup Condition="'$(FeatureAsyncCausalityTracer)' != 'true'">
<Compile Include="$(MSBuildThisFileDirectory)System\Threading\Tasks\AsyncCausalityTracer.Noop.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\MemoryFailPoint.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Runtime\InteropServices\Marshal.Unix.cs" Condition="'$(TargetsCoreRT)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Security\SecureString.Unix.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Threading\Thread.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\TimeZoneInfo.Unix.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetsUnix) or '$(EnableWinRT)'=='true'">
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();
}
if (assemblyName.Length == 0 || assemblyName[0] == '\0')
{
- throw new ArgumentException(SR.ZeroLengthString);
+ throw new ArgumentException(SR.Argument_StringZeroLength, nameof(assemblyName));
}
return assemblyName;
MethodInfo entry = assembly.EntryPoint;
if (entry == null)
{
- throw new MissingMethodException(SR.EntryPointNotFound + assembly.FullName);
+ throw new MissingMethodException(SR.Arg_EntryPointNotFoundException);
}
object result = entry.Invoke(
{
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);
namespace System
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
public sealed class AppDomainSetup
{
internal AppDomainSetup() { }
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
-using Internal.Runtime.Augments;
using Internal.Runtime.CompilerServices;
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;
// 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;
{
[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
[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)
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)
using System.Text;
using System.Threading;
using Microsoft.Win32;
-using Internal.Runtime.Augments;
#if ES_BUILD_STANDALONE
using EventDescriptor = Microsoft.Diagnostics.Tracing.EventDescriptor;
// 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
}
}
}
{
if (!m_osThreadId.HasValue)
{
- m_osThreadId = (long)RuntimeThread.CurrentOSThreadId;
+ m_osThreadId = (long)Thread.CurrentOSThreadId;
}
return m_osThreadId.Value;
// 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;
// See the LICENSE file in the project root for more information.
using System.IO;
-using Internal.Runtime.Augments;
namespace System
{
namespace System
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Threading.Thread")]
+#endif
public sealed class LocalDataStoreSlot
{
internal LocalDataStoreSlot(ThreadLocal<object> data)
using System.Text;
using Internal.Runtime.CompilerServices;
-#if CORERT
-using Thread = Internal.Runtime.Augments.RuntimeThread;
-#endif
-
namespace System.Runtime.CompilerServices
{
/// <summary>
namespace System.Security
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
public partial interface IPermission : ISecurityEncodable
{
IPermission Copy();
namespace System.Security
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
public partial interface ISecurityEncodable
{
void FromXml(SecurityElement e);
namespace System.Security
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
public partial interface IStackWalk
{
void Assert();
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) { }
namespace System.Security.Permissions
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
public enum PermissionState
{
None = 0,
namespace System.Security.Principal
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Security.Principal")]
+#endif
public interface IIdentity
{
// Access to the name string
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.
namespace System.Security
{
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
internal interface ISecurityElementFactory
{
SecurityElement CreateSecurityElement();
string Attribute(string attributeName);
}
+#if PROJECTN
+ [Internal.Runtime.CompilerServices.RelocatedType("System.Runtime.Extensions")]
+#endif
public sealed class SecurityElement : ISecurityElementFactory
{
internal string _tag;
using System.Runtime.ExceptionServices;
using System.Runtime.Serialization;
-using Thread = Internal.Runtime.Augments.RuntimeThread;
-
namespace System.Threading
{
public delegate void ContextCallback(object state);
// 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;
//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:
{
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))
using System.Diagnostics;
using System.Threading.Tasks;
-using Thread = Internal.Runtime.Augments.RuntimeThread;
-
namespace System.Threading
{
/// <summary>
// =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
using System.Diagnostics;
-using Internal.Runtime.Augments;
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();
}
}
}
// 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.
// 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
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
-using Thread = Internal.Runtime.Augments.RuntimeThread;
-
namespace System.Threading.Tasks
{
/// <summary>
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
{
/// <summary>
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<Task,...>)
using System.Collections.Generic;
using System.Text;
-using Internal.Runtime.Augments;
-
namespace System.Threading.Tasks
{
/// <summary>
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);
}
{
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);
}
}
{
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();
}
}
// 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;
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<IPrincipal> 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)
{
}
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)
{
}
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()
}
}
- 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
{
if (this != CurrentThread)
{
- SetCultureOnUnstartedThread(value, ref _startCulture);
+ SetCultureOnUnstartedThread(value, uiCulture: false);
return;
}
CultureInfo.CurrentCulture = value;
{
if (this != CurrentThread)
{
- SetCultureOnUnstartedThread(value, ref _startUICulture);
+ SetCultureOnUnstartedThread(value, uiCulture: true);
return;
}
CultureInfo.CurrentUICulture = value;
}
}
- 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);
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()
{
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);
using System.Threading.Tasks;
using Internal.Runtime.CompilerServices;
-using Thread = Internal.Runtime.Augments.RuntimeThread;
-
namespace System.Threading
{
internal static class ThreadPoolGlobals
// 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);
{
_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!