Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/System.Private.CoreLib/src/Internal/Runtime')
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs51
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs48
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs20
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs138
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs63
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs67
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs90
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs2
-rw-r--r--src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs25
11 files changed, 381 insertions, 127 deletions
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
index 6d28d393b..76ead8cb7 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/EnvironmentAugments.Unix.cs
@@ -27,10 +27,55 @@ namespace Internal.Runtime.Augments
public static IEnumerable<KeyValuePair<string,string>> EnumerateEnvironmentVariables()
{
- if ("".Length != 0)
- throw new NotImplementedException(); // Need to return something better than an empty environment block.
+ IntPtr block = Interop.Sys.GetEnviron();
+ if (block == IntPtr.Zero)
+ yield break;
- return Array.Empty<KeyValuePair<string,string>>();
+ // Per man page, environment variables come back as an array of pointers to strings
+ // Parse each pointer of strings individually
+ while (ParseEntry(block, out string key, out string value))
+ {
+ if (key != null && value != null)
+ yield return new KeyValuePair<string, string>(key, value);
+
+ // Increment to next environment variable entry
+ block += IntPtr.Size;
+ }
+
+ // Use a local, unsafe function since we cannot use `yield return` inside of an `unsafe` block
+ unsafe bool ParseEntry(IntPtr current, out string key, out string value)
+ {
+ // Setup
+ key = null;
+ value = null;
+
+ // Point to current entry
+ byte* entry = *(byte**)current;
+
+ // Per man page, "The last pointer in this array has the value NULL"
+ // Therefore, if entry is null then we're at the end and can bail
+ if (entry == null)
+ return false;
+
+ // Parse each byte of the entry until we hit either the separator '=' or '\0'.
+ // This finds the split point for creating key/value strings below.
+ // On some old OS, the environment block can be corrupted.
+ // Some will not have '=', so we need to check for '\0'.
+ byte* splitpoint = entry;
+ while (*splitpoint != '=' && *splitpoint != '\0')
+ splitpoint++;
+
+ // Skip over entries starting with '=' and entries with no value (just a null-terminating char '\0')
+ if (splitpoint == entry || *splitpoint == '\0')
+ return true;
+
+ // The key is the bytes from start (0) until our splitpoint
+ key = new string((sbyte*)entry, 0, checked((int)(splitpoint - entry)));
+ // The value is the rest of the bytes starting after the splitpoint
+ value = new string((sbyte*)(splitpoint + 1));
+
+ return true;
+ }
}
private static void ExitRaw()
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs
index c37c0d064..bf19ab608 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/ReflectionExecutionDomainCallbacks.cs
@@ -47,7 +47,7 @@ namespace Internal.Runtime.Augments
// Flotsam and jetsam.
public abstract Exception CreateMissingMetadataException(Type typeWithMissingMetadata);
- public abstract String GetBetterDiagnosticInfoIfAvailable(RuntimeTypeHandle runtimeTypeHandle);
+ public abstract string GetBetterDiagnosticInfoIfAvailable(RuntimeTypeHandle runtimeTypeHandle);
public abstract MethodBase GetMethodBaseFromStartAddressIfAvailable(IntPtr methodStartAddress);
public abstract int ValueTypeGetHashCodeUsingReflection(object valueType);
public abstract bool ValueTypeEqualsUsingReflection(object left, object right);
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
index 0213e8821..23c22a965 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs
@@ -87,11 +87,11 @@ namespace Internal.Runtime.Augments
//
// In these cases, this helper returns "null" and ConstructorInfo.Invoke() must deal with these specially.
//
- public static Object NewObject(RuntimeTypeHandle typeHandle)
+ public static object NewObject(RuntimeTypeHandle typeHandle)
{
EETypePtr eeType = typeHandle.ToEETypePtr();
if (eeType.IsNullable
- || eeType == EETypePtr.EETypePtrOf<String>()
+ || eeType == EETypePtr.EETypePtrOf<string>()
)
return null;
return RuntimeImports.RhNewObject(eeType);
@@ -102,7 +102,7 @@ namespace Internal.Runtime.Augments
// Unlike the NewObject API, this is the raw version that does not special case any EEType, and should be used with
// caution for very specific scenarios.
//
- public static Object RawNewObject(RuntimeTypeHandle typeHandle)
+ public static object RawNewObject(RuntimeTypeHandle typeHandle)
{
return RuntimeImports.RhNewObject(typeHandle.ToEETypePtr());
}
@@ -192,7 +192,7 @@ namespace Internal.Runtime.Augments
//
// Helper to create a delegate on a runtime-supplied type.
//
- public static Delegate CreateDelegate(RuntimeTypeHandle typeHandleForDelegate, IntPtr ldftnResult, Object thisObject, bool isStatic, bool isOpen)
+ public static Delegate CreateDelegate(RuntimeTypeHandle typeHandleForDelegate, IntPtr ldftnResult, object thisObject, bool isStatic, bool isOpen)
{
return Delegate.CreateDelegate(typeHandleForDelegate.ToEETypePtr(), ldftnResult, thisObject, isStatic: isStatic, isOpen: isOpen);
}
@@ -248,7 +248,7 @@ namespace Internal.Runtime.Augments
return new IntPtr(RuntimeImports.RhGetThreadStaticFieldAddress(typeHandle.ToEETypePtr(), threadStaticsBlockOffset, fieldOffset));
}
- public static unsafe void StoreValueTypeField(IntPtr address, Object fieldValue, RuntimeTypeHandle fieldType)
+ public static unsafe void StoreValueTypeField(IntPtr address, object fieldValue, RuntimeTypeHandle fieldType)
{
RuntimeImports.RhUnbox(fieldValue, *(void**)&address, fieldType.ToEETypePtr());
}
@@ -258,7 +258,7 @@ namespace Internal.Runtime.Augments
return ref obj.GetRawData();
}
- public static unsafe Object LoadValueTypeField(IntPtr address, RuntimeTypeHandle fieldType)
+ public static unsafe object LoadValueTypeField(IntPtr address, RuntimeTypeHandle fieldType)
{
return RuntimeImports.RhBox(fieldType.ToEETypePtr(), *(void**)&address);
}
@@ -268,12 +268,12 @@ namespace Internal.Runtime.Augments
return Pointer.Box(*(void**)address, Type.GetTypeFromHandle(fieldType));
}
- public static unsafe void StoreValueTypeField(ref byte address, Object fieldValue, RuntimeTypeHandle fieldType)
+ public static unsafe void StoreValueTypeField(ref byte address, object fieldValue, RuntimeTypeHandle fieldType)
{
RuntimeImports.RhUnbox(fieldValue, ref address, fieldType.ToEETypePtr());
}
- public static unsafe void StoreValueTypeField(Object obj, int fieldOffset, Object fieldValue, RuntimeTypeHandle fieldType)
+ public static unsafe void StoreValueTypeField(object obj, int fieldOffset, object fieldValue, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -283,7 +283,7 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe Object LoadValueTypeField(Object obj, int fieldOffset, RuntimeTypeHandle fieldType)
+ public static unsafe object LoadValueTypeField(object obj, int fieldOffset, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -293,7 +293,7 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe Object LoadPointerTypeField(Object obj, int fieldOffset, RuntimeTypeHandle fieldType)
+ public static unsafe object LoadPointerTypeField(object obj, int fieldOffset, RuntimeTypeHandle fieldType)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -303,17 +303,17 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe void StoreReferenceTypeField(IntPtr address, Object fieldValue)
+ public static unsafe void StoreReferenceTypeField(IntPtr address, object fieldValue)
{
- Volatile.Write<Object>(ref Unsafe.As<IntPtr, Object>(ref *(IntPtr*)address), fieldValue);
+ Volatile.Write<Object>(ref Unsafe.As<IntPtr, object>(ref *(IntPtr*)address), fieldValue);
}
- public static unsafe Object LoadReferenceTypeField(IntPtr address)
+ public static unsafe object LoadReferenceTypeField(IntPtr address)
{
- return Volatile.Read<Object>(ref Unsafe.As<IntPtr, Object>(ref *(IntPtr*)address));
+ return Volatile.Read<Object>(ref Unsafe.As<IntPtr, object>(ref *(IntPtr*)address));
}
- public static unsafe void StoreReferenceTypeField(Object obj, int fieldOffset, Object fieldValue)
+ public static unsafe void StoreReferenceTypeField(object obj, int fieldOffset, object fieldValue)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -323,7 +323,7 @@ namespace Internal.Runtime.Augments
}
}
- public static unsafe Object LoadReferenceTypeField(Object obj, int fieldOffset)
+ public static unsafe object LoadReferenceTypeField(object obj, int fieldOffset)
{
fixed (IntPtr* pObj = &obj.m_pEEType)
{
@@ -473,7 +473,7 @@ namespace Internal.Runtime.Augments
// Note that this is not versionable as it is exposed as a const (and needs to be a const so we can used as a custom attribute argument - which
// is the other reason this string is not versionable.)
//
- public const String HiddenScopeAssemblyName = "HiddenScope, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
+ public const string HiddenScopeAssemblyName = "HiddenScope, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a";
//
// This implements the "IsAssignableFrom()" api for runtime-created types. By policy, we let the underlying runtime decide assignability.
@@ -716,7 +716,7 @@ namespace Internal.Runtime.Augments
return true;
}
- public static Object CheckArgument(Object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
+ public static object CheckArgument(object srcObject, RuntimeTypeHandle dstType, BinderBundle binderBundle)
{
return InvokeUtils.CheckArgument(srcObject, dstType, binderBundle);
}
@@ -728,7 +728,7 @@ namespace Internal.Runtime.Augments
return InvokeUtils.CheckArgument(srcObject, dstType.ToEETypePtr(), InvokeUtils.CheckArgumentSemantics.SetFieldDirect, binderBundle: null);
}
- public static bool IsAssignable(Object srcObject, RuntimeTypeHandle dstType)
+ public static bool IsAssignable(object srcObject, RuntimeTypeHandle dstType)
{
EETypePtr srcEEType = srcObject.EETypePtr;
return RuntimeImports.AreTypesAssignable(srcEEType, dstType.ToEETypePtr());
@@ -751,9 +751,9 @@ namespace Internal.Runtime.Augments
//
// Useful helper for finding .pdb's. (This design is admittedly tied to the single-module design of Project N.)
//
- public static String TryGetFullPathToMainApplication()
+ public static string TryGetFullPathToMainApplication()
{
- Func<String> delegateToAnythingInsideMergedApp = TryGetFullPathToMainApplication;
+ Func<string> delegateToAnythingInsideMergedApp = TryGetFullPathToMainApplication;
IntPtr ipToAnywhereInsideMergedApp = delegateToAnythingInsideMergedApp.GetFunctionPointer(out RuntimeTypeHandle _, out bool _, out bool _);
IntPtr moduleBase = RuntimeImports.RhGetOSModuleFromPointer(ipToAnywhereInsideMergedApp);
return TryGetFullPathToApplicationModule(moduleBase);
@@ -763,7 +763,7 @@ namespace Internal.Runtime.Augments
/// Locate the file path for a given native application module.
/// </summary>
/// <param name="moduleBase">Module base address</param>
- public static unsafe String TryGetFullPathToApplicationModule(IntPtr moduleBase)
+ public static unsafe string TryGetFullPathToApplicationModule(IntPtr moduleBase)
{
#if PLATFORM_UNIX
byte* pModuleNameUtf8;
@@ -772,7 +772,7 @@ namespace Internal.Runtime.Augments
#else // PLATFORM_UNIX
char* pModuleName;
int numChars = RuntimeImports.RhGetModuleFileName(moduleBase, out pModuleName);
- String modulePath = new String(pModuleName, 0, numChars);
+ string modulePath = new string(pModuleName, 0, numChars);
#endif // PLATFORM_UNIX
return modulePath;
}
@@ -1111,7 +1111,7 @@ namespace Internal.Runtime.Augments
return RuntimeImports.RhBoxAny((void*)pData, new EETypePtr(pEEType));
}
- public static IntPtr RhHandleAlloc(Object value, GCHandleType type)
+ public static IntPtr RhHandleAlloc(object value, GCHandleType type)
{
return RuntimeImports.RhHandleAlloc(value, type);
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs
index 7b9d380e7..bc3a042eb 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Unix.cs
@@ -144,6 +144,14 @@ namespace Internal.Runtime.Augments
return IntPtr.Zero;
}
+ private void InitializeComOnNewThread()
+ {
+ }
+
+ internal static void InitializeCom()
+ {
+ }
+
public void Interrupt() => WaitSubsystem.Interrupt(this);
internal static void UninterruptibleSleep0() => WaitSubsystem.UninterruptibleSleep0();
private static void SleepInternal(int millisecondsTimeout) => WaitSubsystem.Sleep(millisecondsTimeout);
@@ -159,5 +167,17 @@ namespace Internal.Runtime.Augments
{
throw new PlatformNotSupportedException();
}
+
+ private static int ComputeCurrentProcessorId()
+ {
+ int processorId = Interop.Sys.SchedGetCpu();
+
+ // sched_getcpu doesn't exist on all platforms. On those it doesn't exist on, the shim
+ // 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 (processorId < 0) processorId = Environment.CurrentManagedThreadId;
+
+ return processorId;
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs
index 6d0e937dc..e9fe5485b 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.Windows.cs
@@ -21,8 +21,13 @@ namespace Internal.Runtime.Augments
[ThreadStatic]
private static ApartmentType t_apartmentType;
+ [ThreadStatic]
+ private static bool t_comInitializedByUs;
+
private SafeWaitHandle _osHandle;
+ private ApartmentState _initialAppartmentState = ApartmentState.Unknown;
+
/// <summary>
/// Used by <see cref="WaitHandle"/>'s multi-wait functions
/// </summary>
@@ -99,7 +104,7 @@ namespace Internal.Runtime.Augments
// Throw an ApplicationException for compatibility with CoreCLR. First save the error code.
int errorCode = Marshal.GetLastWin32Error();
var ex = new ApplicationException();
- ex.SetErrorCode(errorCode);
+ ex.HResult = errorCode;
throw ex;
}
@@ -283,10 +288,103 @@ namespace Internal.Runtime.Augments
return 0;
}
- public ApartmentState GetApartmentState() { throw null; }
- public bool TrySetApartmentState(ApartmentState state) { throw null; }
- public void DisableComObjectEagerCleanup() { throw null; }
- public void Interrupt() { throw null; }
+ public ApartmentState GetApartmentState()
+ {
+ if (this != CurrentThread)
+ {
+ if (HasStarted())
+ throw new ThreadStateException();
+ return _initialAppartmentState;
+ }
+
+ switch (GetCurrentApartmentType())
+ {
+ case ApartmentType.STA:
+ return ApartmentState.STA;
+ case ApartmentType.MTA:
+ return ApartmentState.MTA;
+ default:
+ return ApartmentState.Unknown;
+ }
+ }
+
+ public bool TrySetApartmentState(ApartmentState state)
+ {
+ if (this != CurrentThread)
+ {
+ using (LockHolder.Hold(_lock))
+ {
+ if (HasStarted())
+ throw new ThreadStateException();
+ _initialAppartmentState = state;
+ return true;
+ }
+ }
+
+ if (state != ApartmentState.Unknown)
+ {
+ InitializeCom(state);
+ }
+ else
+ {
+ UninitializeCom();
+ }
+
+ // Clear the cache and check whether new state matches the desired state
+ t_apartmentType = ApartmentType.Unknown;
+ return state == GetApartmentState();
+ }
+
+ private void InitializeComOnNewThread()
+ {
+ InitializeCom(_initialAppartmentState);
+ }
+
+ internal static void InitializeCom(ApartmentState state = ApartmentState.MTA)
+ {
+ if (t_comInitializedByUs)
+ return;
+
+#if ENABLE_WINRT
+ int hr = Interop.WinRT.RoInitialize(
+ (state == ApartmentState.STA) ? Interop.WinRT.RO_INIT_SINGLETHREADED
+ : Interop.WinRT.RO_INIT_MULTITHREADED);
+#else
+ int hr = Interop.Ole32.CoInitializeEx(IntPtr.Zero,
+ (state == ApartmentState.STA) ? Interop.Ole32.COINIT_APARTMENTTHREADED
+ : Interop.Ole32.COINIT_MULTITHREADED);
+#endif
+ // RPC_E_CHANGED_MODE indicates this thread has been already initialized with a different
+ // concurrency model. We stay away and let whoever else initialized the COM to be in control.
+ if (hr == HResults.RPC_E_CHANGED_MODE)
+ return;
+ if (hr < 0)
+ throw new OutOfMemoryException();
+
+ t_comInitializedByUs = true;
+
+ // If the thread has already been CoInitialized to the proper mode, then
+ // we don't want to leave an outstanding CoInit so we CoUninit.
+ if (hr > 0)
+ UninitializeCom();
+ }
+
+ private static void UninitializeCom()
+ {
+ if (!t_comInitializedByUs)
+ return;
+
+#if ENABLE_WINRT
+ Interop.WinRT.RoUninitialize();
+#else
+ Interop.Ole32.CoUninitialize();
+#endif
+ t_comInitializedByUs = false;
+ }
+
+ // TODO: https://github.com/dotnet/corefx/issues/20766
+ public void DisableComObjectEagerCleanup() { }
+ public void Interrupt() { throw new PlatformNotSupportedException(); }
internal static void UninterruptibleSleep0()
{
@@ -324,40 +422,40 @@ namespace Internal.Runtime.Augments
if (currentThreadType != ApartmentType.Unknown)
return currentThreadType;
- Interop._APTTYPE aptType;
- Interop._APTTYPEQUALIFIER aptTypeQualifier;
- int result = Interop.mincore.CoGetApartmentType(out aptType, out aptTypeQualifier);
+ Interop.APTTYPE aptType;
+ Interop.APTTYPEQUALIFIER aptTypeQualifier;
+ int result = Interop.Ole32.CoGetApartmentType(out aptType, out aptTypeQualifier);
ApartmentType type = ApartmentType.Unknown;
- switch ((Interop.Constants)result)
+ switch (result)
{
- case Interop.Constants.CoENotInitialized:
+ case HResults.CO_E_NOTINITIALIZED:
type = ApartmentType.None;
break;
- case Interop.Constants.SOk:
+ case HResults.S_OK:
switch (aptType)
{
- case Interop._APTTYPE.APTTYPE_STA:
- case Interop._APTTYPE.APTTYPE_MAINSTA:
+ case Interop.APTTYPE.APTTYPE_STA:
+ case Interop.APTTYPE.APTTYPE_MAINSTA:
type = ApartmentType.STA;
break;
- case Interop._APTTYPE.APTTYPE_MTA:
+ case Interop.APTTYPE.APTTYPE_MTA:
type = ApartmentType.MTA;
break;
- case Interop._APTTYPE.APTTYPE_NA:
+ case Interop.APTTYPE.APTTYPE_NA:
switch (aptTypeQualifier)
{
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MTA:
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MTA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_IMPLICIT_MTA:
type = ApartmentType.MTA;
break;
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_STA:
- case Interop._APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MAINSTA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_STA:
+ case Interop.APTTYPEQUALIFIER.APTTYPEQUALIFIER_NA_ON_MAINSTA:
type = ApartmentType.STA;
break;
@@ -386,5 +484,7 @@ namespace Internal.Runtime.Augments
STA,
MTA
}
+
+ private static int ComputeCurrentProcessorId() => (int)Interop.mincore.GetCurrentProcessorNumber();
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs
index b21d9ced8..b3e9a14fe 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeThread.cs
@@ -7,6 +7,7 @@ using System;
using System.Diagnostics;
using System.Globalization;
using System.Runtime;
+using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
@@ -79,6 +80,14 @@ namespace Internal.Runtime.Augments
}
}
+ internal static ulong CurrentOSThreadId
+ {
+ get
+ {
+ return RuntimeImports.RhCurrentOSThreadId();
+ }
+ }
+
// Slow path executed once per thread
private static RuntimeThread InitializeExistingThread(bool threadPoolThread)
{
@@ -103,7 +112,7 @@ namespace Internal.Runtime.Augments
if (threadPoolThread)
{
- RoInitialize();
+ InitializeCom();
}
return currentThread;
@@ -142,16 +151,6 @@ namespace Internal.Runtime.Augments
}
/// <summary>
- /// Ensures the Windows Runtime is initialized on the current thread.
- /// </summary>
- internal static void RoInitialize()
- {
-#if ENABLE_WINRT
- Interop.WinRT.RoInitialize();
-#endif
- }
-
- /// <summary>
/// Returns true if the underlying OS thread has been created and started execution of managed code.
/// </summary>
private bool HasStarted()
@@ -370,6 +369,7 @@ namespace Internal.Runtime.Augments
return JoinInternal(millisecondsTimeout);
}
+ [MethodImpl(MethodImplOptions.NoInlining)] // Slow path method. Make sure that the caller frame does not pay for PInvoke overhead.
public static void Sleep(int millisecondsTimeout) => SleepInternal(VerifyTimeoutMilliseconds(millisecondsTimeout));
/// <summary>
@@ -381,6 +381,8 @@ namespace Internal.Runtime.Augments
internal static readonly int OptimalMaxSpinWaitsPerSpinIteration = 64;
public static void SpinWait(int iterations) => RuntimeImports.RhSpinWait(iterations);
+
+ [MethodImpl(MethodImplOptions.NoInlining)] // Slow path method. Make sure that the caller frame does not pay for PInvoke overhead.
public static bool Yield() => RuntimeImports.RhYield();
public void Start() => StartInternal(null);
@@ -455,7 +457,7 @@ namespace Internal.Runtime.Augments
{
t_currentThread = thread;
System.Threading.ManagedThreadId.SetForCurrentThread(thread._managedThreadId);
- RoInitialize();
+ thread.InitializeComOnNewThread();
}
catch (OutOfMemoryException)
{
@@ -491,5 +493,42 @@ namespace Internal.Runtime.Augments
thread.SetThreadStateBit(ThreadState.Stopped);
}
}
+
+ // 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 = ComputeCurrentProcessorId();
+
+ // 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);
+ }
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
index ad79c2510..dc598bbb7 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/InteropHelpers.cs
@@ -3,10 +3,11 @@
// See the LICENSE file in the project root for more information.
using System;
-using System.Text;
-using System.Runtime.InteropServices;
using System.Diagnostics;
-using Interlocked = System.Threading.Interlocked;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
namespace Internal.Runtime.CompilerHelpers
{
@@ -15,7 +16,7 @@ namespace Internal.Runtime.CompilerHelpers
/// </summary>
internal static class InteropHelpers
{
- internal static unsafe byte* StringToAnsiString(String str, bool bestFit, bool throwOnUnmappableChar)
+ internal static unsafe byte* StringToAnsiString(string str, bool bestFit, bool throwOnUnmappableChar)
{
return PInvokeMarshal.StringToAnsiString(str, bestFit, throwOnUnmappableChar);
}
@@ -37,7 +38,7 @@ namespace Internal.Runtime.CompilerHelpers
return PInvokeMarshal.ByValAnsiStringToString(buffer, length);
}
- internal static unsafe void StringToUnicodeFixedArray(String str, UInt16* buffer, int length)
+ internal static unsafe void StringToUnicodeFixedArray(string str, ushort* buffer, int length)
{
if (buffer == null)
return;
@@ -58,16 +59,16 @@ namespace Internal.Runtime.CompilerHelpers
}
}
- internal static unsafe string UnicodeToStringFixedArray(UInt16* buffer, int length)
+ internal static unsafe string UnicodeToStringFixedArray(ushort* buffer, int length)
{
if (buffer == null)
- return String.Empty;
+ return string.Empty;
- string result = String.Empty;
+ string result = string.Empty;
if (length > 0)
{
- result = new String(' ', length);
+ result = new string(' ', length);
fixed (char* pTemp = result)
{
@@ -78,7 +79,7 @@ namespace Internal.Runtime.CompilerHelpers
return result;
}
- internal static unsafe char* StringToUnicodeBuffer(String str)
+ internal static unsafe char* StringToUnicodeBuffer(string str)
{
if (str == null)
return null;
@@ -98,7 +99,7 @@ namespace Internal.Runtime.CompilerHelpers
public static unsafe string UnicodeBufferToString(char* buffer)
{
- return new String(buffer);
+ return new string(buffer);
}
public static unsafe byte* AllocMemoryForAnsiStringBuilder(StringBuilder sb)
@@ -208,6 +209,7 @@ namespace Internal.Runtime.CompilerHelpers
return ResolvePInvokeSlow(pCell);
}
+ [MethodImpl(MethodImplOptions.NoInlining)]
internal static unsafe IntPtr ResolvePInvokeSlow(MethodFixupCell* pCell)
{
ModuleFixupCell* pModuleCell = pCell->Module;
@@ -304,8 +306,8 @@ namespace Internal.Runtime.CompilerHelpers
{
byte* methodName = (byte*)pCell->MethodName;
-#if !PLATFORM_UNIX
- pCell->Target = Interop.mincore.GetProcAddress(hModule, methodName);
+#if PLATFORM_WINDOWS
+ pCell->Target = GetProcAddress(hModule, methodName, pCell->CharSetMangling);
#else
pCell->Target = Interop.Sys.GetProcAddress(hModule, methodName);
#endif
@@ -316,6 +318,44 @@ namespace Internal.Runtime.CompilerHelpers
}
}
+#if PLATFORM_WINDOWS
+ private static unsafe IntPtr GetProcAddress(IntPtr hModule, byte* methodName, CharSet charSetMangling)
+ {
+ // First look for the unmangled name. If it is unicode function, we are going
+ // to need to check for the 'W' API because it takes precedence over the
+ // unmangled one (on NT some APIs have unmangled ANSI exports).
+
+ var exactMatch = Interop.mincore.GetProcAddress(hModule, methodName);
+
+ if ((charSetMangling == CharSet.Ansi && exactMatch != IntPtr.Zero) || charSetMangling == 0)
+ {
+ return exactMatch;
+ }
+
+ int nameLength = strlen(methodName);
+
+ // We need to add an extra byte for the suffix, and an extra byte for the null terminator
+ byte* probedMethodName = stackalloc byte[nameLength + 2];
+
+ for (int i = 0; i < nameLength; i++)
+ {
+ probedMethodName[i] = methodName[i];
+ }
+
+ probedMethodName[nameLength + 1] = 0;
+
+ probedMethodName[nameLength] = (charSetMangling == CharSet.Ansi) ? (byte)'A' : (byte)'W';
+
+ IntPtr probedMethod = Interop.mincore.GetProcAddress(hModule, probedMethodName);
+ if (probedMethod != IntPtr.Zero)
+ {
+ return probedMethod;
+ }
+
+ return exactMatch;
+ }
+#endif
+
internal static unsafe int strlen(byte* pString)
{
byte* p = pString;
@@ -379,6 +419,7 @@ namespace Internal.Runtime.CompilerHelpers
public IntPtr Target;
public IntPtr MethodName;
public ModuleFixupCell* Module;
+ public CharSet CharSetMangling;
}
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
index c31521d80..6947cc9f3 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/MathHelpers.cs
@@ -24,64 +24,64 @@ namespace Internal.Runtime.CompilerHelpers
// Helper to multiply two 32-bit uints
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static UInt64 Mul32x32To64(UInt32 a, UInt32 b)
+ private static ulong Mul32x32To64(uint a, uint b)
{
- return a * (UInt64)b;
+ return a * (ulong)b;
}
// Helper to get high 32-bit of 64-bit int
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static UInt32 Hi32Bits(Int64 a)
+ private static uint Hi32Bits(long a)
{
- return (UInt32)(a >> 32);
+ return (uint)(a >> 32);
}
// Helper to get high 32-bit of 64-bit int
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- private static UInt32 Hi32Bits(UInt64 a)
+ private static uint Hi32Bits(ulong a)
{
- return (UInt32)(a >> 32);
+ return (uint)(a >> 32);
}
[RuntimeExport("LMulOvf")]
- public static Int64 LMulOvf(Int64 i, Int64 j)
+ public static long LMulOvf(long i, long j)
{
- Int64 ret;
+ long ret;
// Remember the sign of the result
- Int32 sign = (Int32)(Hi32Bits(i) ^ Hi32Bits(j));
+ int sign = (int)(Hi32Bits(i) ^ Hi32Bits(j));
// Convert to unsigned multiplication
if (i < 0) i = -i;
if (j < 0) j = -j;
// Get the upper 32 bits of the numbers
- UInt32 val1High = Hi32Bits(i);
- UInt32 val2High = Hi32Bits(j);
+ uint val1High = Hi32Bits(i);
+ uint val2High = Hi32Bits(j);
- UInt64 valMid;
+ ulong valMid;
if (val1High == 0)
{
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val2High, (UInt32)i);
+ valMid = Mul32x32To64(val2High, (uint)i);
}
else
{
if (val2High != 0)
goto ThrowExcep;
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val1High, (UInt32)j);
+ valMid = Mul32x32To64(val1High, (uint)j);
}
// See if any bits after bit 32 are set
if (Hi32Bits(valMid) != 0)
goto ThrowExcep;
- ret = (Int64)(Mul32x32To64((UInt32)i, (UInt32)j) + (valMid << 32));
+ ret = (long)(Mul32x32To64((uint)i, (uint)j) + (valMid << 32));
// check for overflow
- if (Hi32Bits(ret) < (UInt32)valMid)
+ if (Hi32Bits(ret) < (uint)valMid)
goto ThrowExcep;
if (sign >= 0)
@@ -104,39 +104,39 @@ namespace Internal.Runtime.CompilerHelpers
}
[RuntimeExport("ULMulOvf")]
- public static UInt64 ULMulOvf(UInt64 i, UInt64 j)
+ public static ulong ULMulOvf(ulong i, ulong j)
{
- UInt64 ret;
+ ulong ret;
// Get the upper 32 bits of the numbers
- UInt32 val1High = Hi32Bits(i);
- UInt32 val2High = Hi32Bits(j);
+ uint val1High = Hi32Bits(i);
+ uint val2High = Hi32Bits(j);
- UInt64 valMid;
+ ulong valMid;
if (val1High == 0)
{
if (val2High == 0)
- return Mul32x32To64((UInt32)i, (UInt32)j);
+ return Mul32x32To64((uint)i, (uint)j);
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val2High, (UInt32)i);
+ valMid = Mul32x32To64(val2High, (uint)i);
}
else
{
if (val2High != 0)
goto ThrowExcep;
// Compute the 'middle' bits of the long multiplication
- valMid = Mul32x32To64(val1High, (UInt32)j);
+ valMid = Mul32x32To64(val1High, (uint)j);
}
// See if any bits after bit 32 are set
if (Hi32Bits(valMid) != 0)
goto ThrowExcep;
- ret = Mul32x32To64((UInt32)i, (UInt32)j) + (valMid << 32);
+ ret = Mul32x32To64((uint)i, (uint)j) + (valMid << 32);
// check for overflow
- if (Hi32Bits(ret) < (UInt32)valMid)
+ if (Hi32Bits(ret) < (uint)valMid)
goto ThrowExcep;
return ret;
@@ -212,7 +212,7 @@ namespace Internal.Runtime.CompilerHelpers
// Note that this expression also works properly for val = NaN case
// We need to compare with the very next double to two63. 0x402 is epsilon to get us there.
if (val > -two63 - 0x402 && val < two63)
- return ((Int64)val);
+ return ((long)val);
return ThrowIntOvf();
}
@@ -222,13 +222,13 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpIDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int32 RhpIDiv(Int32 i, Int32 j);
+ private static extern int RhpIDiv(int i, int j);
- public static int IDiv(Int32 i, Int32 j)
+ public static int IDiv(int i, int j)
{
if (j == 0)
return ThrowIntDivByZero();
- else if (j == -1 && i == Int32.MinValue)
+ else if (j == -1 && i == int.MinValue)
return ThrowIntArithExc();
else
return RhpIDiv(i, j);
@@ -236,9 +236,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpUDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt32 RhpUDiv(UInt32 i, UInt32 j);
+ private static extern uint RhpUDiv(uint i, uint j);
- public static long UDiv(UInt32 i, UInt32 j)
+ public static long UDiv(uint i, uint j)
{
if (j == 0)
return ThrowUIntDivByZero();
@@ -248,9 +248,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpULDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt64 RhpULDiv(UInt64 i, UInt64 j);
+ private static extern ulong RhpULDiv(ulong i, ulong j);
- public static ulong ULDiv(UInt64 i, UInt64 j)
+ public static ulong ULDiv(ulong i, ulong j)
{
if (j == 0)
return ThrowULngDivByZero();
@@ -260,13 +260,13 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpLDiv")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int64 RhpLDiv(Int64 i, Int64 j);
+ private static extern long RhpLDiv(long i, long j);
- public static long LDiv(Int64 i, Int64 j)
+ public static long LDiv(long i, long j)
{
if (j == 0)
return ThrowLngDivByZero();
- else if (j == -1 && i == Int64.MinValue)
+ else if (j == -1 && i == long.MinValue)
return ThrowLngArithExc();
else
return RhpLDiv(i, j);
@@ -274,9 +274,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpIMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int32 RhpIMod(Int32 i, Int32 j);
+ private static extern int RhpIMod(int i, int j);
- public static int IMod(Int32 i, Int32 j)
+ public static int IMod(int i, int j)
{
if (j == 0)
return ThrowIntDivByZero();
@@ -286,9 +286,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpUMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt32 RhpUMod(UInt32 i, UInt32 j);
+ private static extern uint RhpUMod(uint i, uint j);
- public static long UMod(UInt32 i, UInt32 j)
+ public static long UMod(uint i, uint j)
{
if (j == 0)
return ThrowUIntDivByZero();
@@ -298,9 +298,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpULMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern UInt64 RhpULMod(UInt64 i, UInt64 j);
+ private static extern ulong RhpULMod(ulong i, ulong j);
- public static ulong ULMod(UInt64 i, UInt64 j)
+ public static ulong ULMod(ulong i, ulong j)
{
if (j == 0)
return ThrowULngDivByZero();
@@ -310,9 +310,9 @@ namespace Internal.Runtime.CompilerHelpers
[RuntimeImport(RuntimeLibrary, "RhpLMod")]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
- private static extern Int64 RhpLMod(Int64 i, Int64 j);
+ private static extern long RhpLMod(long i, long j);
- public static long LMod(Int64 i, Int64 j)
+ public static long LMod(long i, long j)
{
if (j == 0)
return ThrowLngDivByZero();
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs
index 30694aead..018c8005c 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerHelpers/SynchronizedMethodHelpers.cs
@@ -54,7 +54,7 @@ namespace Internal.Runtime.CompilerHelpers
lockTaken = false;
}
- private static Object GetStaticLockObject(IntPtr pEEType)
+ private static object GetStaticLockObject(IntPtr pEEType)
{
return Internal.Reflection.Core.NonPortable.RuntimeTypeUnifier.GetRuntimeTypeForEEType(new System.EETypePtr(pEEType));
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs
index a848f5a94..74363b72b 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/RelocatedTypeAttribute.cs
@@ -19,7 +19,7 @@ namespace Internal.Runtime.CompilerServices
/// </summary>
/// <param name="originalAssemblySimpleName">Simple name of the CoreFX assembly the type was relocated from.
/// For example, System.Collections (with no version or public key token)</param>
- public RelocatedTypeAttribute(String originalAssemblySimpleName)
+ public RelocatedTypeAttribute(string originalAssemblySimpleName)
{
}
}
diff --git a/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs b/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs
index db6977ee5..be6537858 100644
--- a/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs
+++ b/src/System.Private.CoreLib/src/Internal/Runtime/ThreadStatics.cs
@@ -4,6 +4,7 @@
using System;
using System.Runtime;
+using System.Runtime.CompilerServices;
using Internal.Runtime.CompilerHelpers;
namespace Internal.Runtime
@@ -18,21 +19,29 @@ namespace Internal.Runtime
/// This method is called from a ReadyToRun helper to get base address of thread
/// static storage for the given type.
/// </summary>
- internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot* pModuleData, Int32 typeTlsIndex)
+ internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot* pModuleData, int typeTlsIndex)
{
// Get the array that holds thread static memory blocks for each type in the given module
- Int32 moduleIndex = pModuleData->ModuleIndex;
- object[] storage = (object[])RuntimeImports.RhGetThreadStaticStorageForModule(moduleIndex);
+ object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(pModuleData->ModuleIndex);
// Check whether thread static storage has already been allocated for this module and type.
- if ((storage != null) && (typeTlsIndex < storage.Length) && (storage[typeTlsIndex] != null))
+ if ((storage != null) && ((uint)typeTlsIndex < (uint)storage.Length) && (storage[typeTlsIndex] != null))
{
return storage[typeTlsIndex];
}
+ return GetThreadStaticBaseForTypeSlow(pModuleData, typeTlsIndex);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ internal static unsafe object GetThreadStaticBaseForTypeSlow(TypeManagerSlot* pModuleData, int typeTlsIndex)
+ {
+ // Get the array that holds thread static memory blocks for each type in the given module
+ object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(pModuleData->ModuleIndex);
+
// This the first access to the thread statics of the type corresponding to typeTlsIndex.
// Make sure there is enough storage allocated to hold it.
- storage = EnsureThreadStaticStorage(moduleIndex, storage, requiredSize: typeTlsIndex + 1);
+ storage = EnsureThreadStaticStorage(pModuleData->ModuleIndex, storage, requiredSize: typeTlsIndex + 1);
// Allocate an object that will represent a memory block for all thread static fields of the type
object threadStaticBase = AllocateThreadStaticStorageForType(pModuleData->TypeManager, typeTlsIndex);
@@ -45,7 +54,7 @@ namespace Internal.Runtime
/// if it is required, this method extends thread static storage of the given module
/// to the specified size and then registers the memory with the runtime.
/// </summary>
- private static object[] EnsureThreadStaticStorage(Int32 moduleIndex, object[] existingStorage, Int32 requiredSize)
+ private static object[] EnsureThreadStaticStorage(int moduleIndex, object[] existingStorage, int requiredSize)
{
if ((existingStorage != null) && (requiredSize < existingStorage.Length))
{
@@ -73,9 +82,9 @@ namespace Internal.Runtime
/// This method allocates an object that represents a memory block for all thread static fields of the type
/// that corresponds to the specified TLS index.
/// </summary>
- private static unsafe object AllocateThreadStaticStorageForType(TypeManagerHandle typeManager, Int32 typeTlsIndex)
+ private static unsafe object AllocateThreadStaticStorageForType(TypeManagerHandle typeManager, int typeTlsIndex)
{
- Int32 length;
+ int length;
IntPtr* threadStaticRegion;
// Get a pointer to the beginning of the module's Thread Static section. Then get a pointer