diff options
author | Anton Lapounov <antonl@microsoft.com> | 2017-01-20 01:11:48 +0300 |
---|---|---|
committer | Anton Lapounov <antonl@microsoft.com> | 2017-01-20 01:11:48 +0300 |
commit | 70874488d0b71ae376c302827288f8c4806c9b26 (patch) | |
tree | fde28677dcc0459c10ab89efdfbbd1f2ddda4cc4 | |
parent | 1ac148442ddab83c8023a498e086bae7eeabe1fd (diff) |
Use native thread id in the Lock class so it may be implemented as a compiler intrinsic on Windows.
CR: SergeyK, EJan
[tfs-changeset: 1645128]
7 files changed, 34 insertions, 13 deletions
diff --git a/src/Common/src/Interop/Windows/Interop.Libraries.cs b/src/Common/src/Interop/Windows/Interop.Libraries.cs index 6740c2cb2..0c1679ed2 100644 --- a/src/Common/src/Interop/Windows/Interop.Libraries.cs +++ b/src/Common/src/Interop/Windows/Interop.Libraries.cs @@ -15,6 +15,7 @@ internal static partial class Interop internal const string IO = "api-ms-win-core-io-l1-1-0.dll"; internal const string Memory = "api-ms-win-core-memory-l1-1-0.dll"; internal const string ProcessEnvironment = "api-ms-win-core-processenvironment-l1-1-0.dll"; + internal const string ProcessThreads = "api-ms-win-core-processthreads-l1-1-0.dll"; internal const string RealTime = "api-ms-win-core-realtime-l1-1-0.dll"; internal const string SysInfo = "api-ms-win-core-sysinfo-l1-2-0.dll"; internal const string Kernel32 = "api-ms-win-core-kernel32-legacy-l1-1-0.dll"; diff --git a/src/Common/src/Interop/Windows/mincore/Interop.GetCurrentThreadId.cs b/src/Common/src/Interop/Windows/mincore/Interop.GetCurrentThreadId.cs new file mode 100644 index 000000000..10e850f03 --- /dev/null +++ b/src/Common/src/Interop/Windows/mincore/Interop.GetCurrentThreadId.cs @@ -0,0 +1,14 @@ +// 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.Runtime.InteropServices; + +internal static partial class Interop +{ + internal static partial class mincore + { + [DllImport(Libraries.ProcessThreads)] + internal extern static uint GetCurrentThreadId(); + } +} diff --git a/src/System.Private.CoreLib/src/Interop/Interop.manual.cs b/src/System.Private.CoreLib/src/Interop/Interop.manual.cs index 08b9a91e5..ffc17b236 100644 --- a/src/System.Private.CoreLib/src/Interop/Interop.manual.cs +++ b/src/System.Private.CoreLib/src/Interop/Interop.manual.cs @@ -86,9 +86,6 @@ internal partial class Interop [DllImport("api-ms-win-core-synch-l1-1-0.dll", EntryPoint = "CreateSemaphoreExW", CharSet = CharSet.Unicode)] internal static extern IntPtr CreateSemaphoreEx(IntPtr lpSemaphoreAttributes, int lInitialCount, int lMaximumCount, string lpName, uint dwFlags, uint dwDesiredAccess); - [DllImport("api-ms-win-core-processthreads-l1-1-0.dll")] - internal extern static uint GetCurrentThreadId(); - [DllImport("api-ms-win-core-debug-l1-1-0.dll", EntryPoint = "IsDebuggerPresent", CharSet = CharSet.Unicode)] internal extern static bool IsDebuggerPresent(); diff --git a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj index 4998a45c6..41cce6086 100644 --- a/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj +++ b/src/System.Private.CoreLib/src/System.Private.CoreLib.csproj @@ -752,6 +752,9 @@ <Compile Include="..\..\Common\src\Interop\Windows\Interop.BOOL.cs"> <Link>Interop\Windows\Interop.BOOL.cs</Link> </Compile> + <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.GetCurrentThreadId.cs"> + <Link>Interop\Windows\mincore\Interop.GetCurrentThreadId.cs</Link> + </Compile> <Compile Include="..\..\Common\src\Interop\Windows\mincore\Interop.SetLastError.cs"> <Link>Interop\Windows\mincore\Interop.SetLastError.cs</Link> </Compile> diff --git a/src/System.Private.CoreLib/src/System/Environment.Unix.cs b/src/System.Private.CoreLib/src/System/Environment.Unix.cs index bcfdbe4f6..7cf60c683 100644 --- a/src/System.Private.CoreLib/src/System/Environment.Unix.cs +++ b/src/System.Private.CoreLib/src/System/Environment.Unix.cs @@ -9,6 +9,8 @@ namespace System { public static partial class Environment { + internal static int CurrentNativeThreadId => ManagedThreadId.Current; + internal static long TickCount64 { get diff --git a/src/System.Private.CoreLib/src/System/Environment.Windows.cs b/src/System.Private.CoreLib/src/System/Environment.Windows.cs index 7576857a9..3c35f0f7a 100644 --- a/src/System.Private.CoreLib/src/System/Environment.Windows.cs +++ b/src/System.Private.CoreLib/src/System/Environment.Windows.cs @@ -6,6 +6,8 @@ namespace System { public static partial class Environment { + internal static int CurrentNativeThreadId => unchecked((int)Interop.mincore.GetCurrentThreadId()); + internal static long TickCount64 => (long)Interop.mincore.GetTickCount64(); public static int ProcessorCount diff --git a/src/System.Private.CoreLib/src/System/Threading/Lock.cs b/src/System.Private.CoreLib/src/System/Threading/Lock.cs index e81d5c3cf..1a122c21b 100644 --- a/src/System.Private.CoreLib/src/System/Threading/Lock.cs +++ b/src/System.Private.CoreLib/src/System/Threading/Lock.cs @@ -2,9 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable 0420 //passing volatile field by reference - - using System.Diagnostics; using System.Runtime.CompilerServices; @@ -57,12 +54,14 @@ namespace System.Threading } } - /// <remarks>Inlined version of Lock.Acquire has CurrentManagedThreadId not inlined, non-inlined version has it inlined. - /// So it saves code to keep this function non inlining while keep the same runtime cost</remarks> + // On platforms where CurrentNativeThreadId redirects to ManagedThreadId.Current the inlined + // version of Lock.Acquire has the ManagedThreadId.Current call not inlined, while the non-inlined + // version has it inlined. So it saves code to keep this function not inlined while having + // the same runtime cost. [MethodImpl(MethodImplOptions.NoInlining)] public void Acquire() { - int currentThreadId = Environment.CurrentManagedThreadId; + int currentThreadId = Environment.CurrentNativeThreadId; // // Make one quick attempt to acquire an uncontended lock @@ -95,7 +94,7 @@ namespace System.Threading if (millisecondsTimeout < -1) throw new ArgumentOutOfRangeException(nameof(millisecondsTimeout), SR.ArgumentOutOfRange_NeedNonNegOrNegative1); - int currentThreadId = Environment.CurrentManagedThreadId; + int currentThreadId = Environment.CurrentNativeThreadId; // // Make one quick attempt to acquire an uncontended lock @@ -231,13 +230,16 @@ namespace System.Threading get { // + // The comment below is for platforms where CurrentNativeThreadId redirects to + // ManagedThreadId.Current instead of being a compiler intrinsic. + // // Compare the current owning thread ID with the current thread ID. We need // to read the current thread's ID before we read m_owningThreadId. Otherwise, // the following might happen: // // 1) We read m_owningThreadId, and get, say 42, which belongs to another thread. // 2) Thread 42 releases the lock, and exits. - // 3) We call CurrentManagedThreadId. If this is the first time it's been called + // 3) We call ManagedThreadId.Current. If this is the first time it's been called // on this thread, we'll go get a new ID. We may reuse thread 42's ID, since // that thread is dead. // 4) Now we're thread 42, and it looks like we own the lock, even though we don't. @@ -246,8 +248,8 @@ namespace System.Threading // because while we're doing this check the current thread is definitely still // alive. // - int currentManagedThreadId = Environment.CurrentManagedThreadId; - bool acquired = (currentManagedThreadId == _owningThreadId); + int currentThreadId = Environment.CurrentNativeThreadId; + bool acquired = (currentThreadId == _owningThreadId); if (acquired) Debug.Assert((_state & Locked) != 0); return acquired; |