Synchronize SpinLock with CoreRT (#9244)
authorJan Kotas <jkotas@microsoft.com>
Wed, 1 Feb 2017 07:34:28 +0000 (23:34 -0800)
committerGitHub <noreply@github.com>
Wed, 1 Feb 2017 07:34:28 +0000 (23:34 -0800)
src/mscorlib/corefx/SR.cs
src/mscorlib/src/System/Threading/SpinLock.cs

index 23890e0..5f96a40 100644 (file)
@@ -595,4 +595,29 @@ internal static class SR
     {
         get { return Environment.GetResourceString("ArgumentException_ValueTupleLastArgumentNotATuple"); }
     }
+
+    internal static string SpinLock_TryEnter_ArgumentOutOfRange
+    {
+        get { return Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange"); }
+    }
+
+    internal static string SpinLock_TryReliableEnter_ArgumentException
+    {
+        get { return Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException"); }
+    }
+
+    internal static string SpinLock_TryEnter_LockRecursionException
+    {
+        get { return Environment.GetResourceString("SpinLock_TryEnter_LockRecursionException"); }
+    }
+
+    internal static string SpinLock_Exit_SynchronizationLockException
+    {
+        get { return Environment.GetResourceString("SpinLock_Exit_SynchronizationLockException"); }
+    }
+
+    internal static string SpinLock_IsHeldByCurrentThread
+    {
+        get { return Environment.GetResourceString("SpinLock_IsHeldByCurrentThread"); }
+    }
 }
index aad274d..eee73ce 100644 (file)
@@ -9,19 +9,14 @@
 // repeatedly checking until the lock becomes available. As the thread remains active performing a non-useful task,
 // the use of such a lock is a kind of busy waiting and consumes CPU resources without performing real work. 
 //
-//
 // =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
-using System;
-using System.Security.Permissions;
+
+using System.Diagnostics;
 using System.Runtime.InteropServices;
 using System.Runtime.CompilerServices;
-using System.Runtime.ConstrainedExecution;
-using System.Diagnostics;
-using System.Diagnostics.Contracts;
 
 namespace System.Threading
 {
-
     /// <summary>
     /// Provides a mutual exclusion lock primitive where a thread trying to acquire the lock waits in a loop
     /// repeatedly checking until the lock becomes available.
@@ -54,7 +49,6 @@ namespace System.Threading
     /// concurrently.
     /// </para>
     /// </remarks>
-    [ComVisible(false)]
     [DebuggerTypeProxy(typeof(SystemThreading_SpinLockDebugView))]
     [DebuggerDisplay("IsHeld = {IsHeld}")]
     public struct SpinLock
@@ -106,6 +100,14 @@ namespace System.Threading
         // The waiters count is calculated by m_owner & WAITERS_MASK 01111....110
         private static int MAXIMUM_WAITERS = WAITERS_MASK;
 
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        private int CompareExchange(ref int location, int value, int comparand, ref bool success)
+        {
+            int result = Interlocked.CompareExchange(ref location, value, comparand);
+            success = (result == comparand);
+            return result;
+        }
+
         /// <summary>
         /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/>
         /// structure with the option to track thread IDs to improve debugging.
@@ -158,9 +160,8 @@ namespace System.Threading
             int observedOwner = m_owner;
             if (lockTaken || //invalid parameter
                 (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK || //thread tracking is enabled or the lock is already acquired
-                Interlocked.CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) //acquiring the lock failed
+                CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) //acquiring the lock failed
                 ContinueTryEnter(Timeout.Infinite, ref lockTaken); // Then try the slow path if any of the above conditions is met
-
         }
 
         /// <summary>
@@ -197,7 +198,7 @@ namespace System.Threading
             else
             {
                 // Lock wasn't held; try to acquire it.
-                Interlocked.CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken);
+                CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken);
             }
         }
 
@@ -234,7 +235,7 @@ namespace System.Threading
             if (totalMilliseconds < -1 || totalMilliseconds > int.MaxValue)
             {
                 throw new System.ArgumentOutOfRangeException(
-                    nameof(timeout), timeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange"));
+                    nameof(timeout), timeout, SR.SpinLock_TryEnter_ArgumentOutOfRange);
             }
 
             // Call reliable enter with the int-based timeout milliseconds
@@ -269,7 +270,7 @@ namespace System.Threading
             if (millisecondsTimeout < -1 || //invalid parameter
                 lockTaken || //invalid parameter
                 (observedOwner & ID_DISABLED_AND_ANONYMOUS_OWNED) != LOCK_ID_DISABLE_MASK ||  //thread tracking is enabled or the lock is already acquired
-                Interlocked.CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) // acquiring the lock failed
+                CompareExchange(ref m_owner, observedOwner | LOCK_ANONYMOUS_OWNED, observedOwner, ref lockTaken) != observedOwner) // acquiring the lock failed
                 ContinueTryEnter(millisecondsTimeout, ref lockTaken); // The call the slow pth
         }
 
@@ -286,13 +287,13 @@ namespace System.Threading
             if (lockTaken)
             {
                 lockTaken = false;
-                throw new System.ArgumentException(Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException"));
+                throw new System.ArgumentException(SR.SpinLock_TryReliableEnter_ArgumentException);
             }
 
             if (millisecondsTimeout < -1)
             {
                 throw new ArgumentOutOfRangeException(
-                    nameof(millisecondsTimeout), millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange"));
+                    nameof(millisecondsTimeout), millisecondsTimeout, SR.SpinLock_TryEnter_ArgumentOutOfRange);
             }
 
             uint startTime = 0;
@@ -326,7 +327,7 @@ namespace System.Threading
             observedOwner = m_owner;
             if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED)
             {
-                if (Interlocked.CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner)
+                if (CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner)
                 {
                     // Aquired lock
                     return;
@@ -346,7 +347,7 @@ namespace System.Threading
             else //failed to acquire the lock,then try to update the waiters. If the waiters count reached the maximum, jsut break the loop to avoid overflow
             {
                 if ((observedOwner & WAITERS_MASK) != MAXIMUM_WAITERS)
-                    turn = (Interlocked.Add(ref m_owner, 2) & WAITERS_MASK) >> 1 ;
+                    turn = (Interlocked.Add(ref m_owner, 2) & WAITERS_MASK) >> 1;
             }
 
             //***Step 2. Spinning
@@ -368,7 +369,7 @@ namespace System.Threading
                             : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
                         Debug.Assert((newOwner & WAITERS_MASK) >= 0);
 
-                        if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
+                        if (CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
                         {
                             return;
                         }
@@ -396,7 +397,7 @@ namespace System.Threading
                            : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit
                     Debug.Assert((newOwner & WAITERS_MASK) >= 0);
 
-                    if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
+                    if (CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner)
                     {
                         return;
                     }
@@ -446,7 +447,6 @@ namespace System.Threading
                 }
                 spinner.SpinOnce();
             }
-
         }
 
         /// <summary>
@@ -459,11 +459,11 @@ namespace System.Threading
             int lockUnowned = 0;
             // We are using thread IDs to mark ownership. Snap the thread ID and check for recursion.
             // We also must or the ID enablement bit, to ensure we propagate when we CAS it in.
-            int m_newOwner = Thread.CurrentThread.ManagedThreadId;
+            int m_newOwner = Environment.CurrentManagedThreadId;
             if (m_owner == m_newOwner)
             {
                 // We don't allow lock recursion.
-                throw new LockRecursionException(Environment.GetResourceString("SpinLock_TryEnter_LockRecursionException"));
+                throw new LockRecursionException(SR.SpinLock_TryEnter_LockRecursionException);
             }
 
 
@@ -472,7 +472,6 @@ namespace System.Threading
             // Loop until the lock has been successfully acquired or, if specified, the timeout expires.
             do
             {
-
                 // We failed to get the lock, either from the fast route or the last iteration
                 // and the timeout hasn't expired; spin once and try again.
                 spinner.SpinOnce();
@@ -481,7 +480,7 @@ namespace System.Threading
 
                 if (m_owner == lockUnowned)
                 {
-                    if (Interlocked.CompareExchange(ref m_owner, m_newOwner, lockUnowned, ref lockTaken) == lockUnowned)
+                    if (CompareExchange(ref m_owner, m_newOwner, lockUnowned, ref lockTaken) == lockUnowned)
                     {
                         return;
                     }
@@ -506,7 +505,6 @@ namespace System.Threading
         /// <exception cref="SynchronizationLockException">
         /// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
         /// </exception>
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
         public void Exit()
         {
             //This is the fast path for the thread tracking is disabled, otherwise go to the slow path
@@ -532,7 +530,6 @@ namespace System.Threading
         /// <exception cref="SynchronizationLockException">
         /// Thread ownership tracking is enabled, and the current thread is not the owner of this lock.
         /// </exception>
-        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
         public void Exit(bool useMemoryBarrier)
         {
             // This is the fast path for the thread tracking is diabled and not to use memory barrier, otherwise go to the slow path
@@ -560,7 +557,7 @@ namespace System.Threading
             if (threadTrackingEnabled && !IsHeldByCurrentThread)
             {
                 throw new System.Threading.SynchronizationLockException(
-                    Environment.GetResourceString("SpinLock_Exit_SynchronizationLockException"));
+                    SR.SpinLock_Exit_SynchronizationLockException);
             }
 
             if (useMemoryBarrier)
@@ -569,7 +566,6 @@ namespace System.Threading
                     Interlocked.Exchange(ref m_owner, LOCK_UNOWNED);
                 else
                     Interlocked.Decrement(ref m_owner);
-
             }
             else
             {
@@ -580,9 +576,7 @@ namespace System.Threading
                     int tmpOwner = m_owner;
                     m_owner = tmpOwner & (~LOCK_ANONYMOUS_OWNED);
                 }
-
             }
-
         }
 
         /// <summary>
@@ -590,7 +584,6 @@ namespace System.Threading
         /// </summary>
         public bool IsHeld
         {
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
             get
             {
                 if (IsThreadOwnerTrackingEnabled)
@@ -616,21 +609,19 @@ namespace System.Threading
         /// </exception>
         public bool IsHeldByCurrentThread
         {
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
             get
             {
                 if (!IsThreadOwnerTrackingEnabled)
                 {
-                    throw new InvalidOperationException(Environment.GetResourceString("SpinLock_IsHeldByCurrentThread"));
+                    throw new InvalidOperationException(SR.SpinLock_IsHeldByCurrentThread);
                 }
-                return ((m_owner & (~LOCK_ID_DISABLE_MASK)) == Thread.CurrentThread.ManagedThreadId);
+                return ((m_owner & (~LOCK_ID_DISABLE_MASK)) == Environment.CurrentManagedThreadId);
             }
         }
 
         /// <summary>Gets whether thread ownership tracking is enabled for this instance.</summary>
         public bool IsThreadOwnerTrackingEnabled
         {
-            [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
             get { return (m_owner & LOCK_ID_DISABLE_MASK) == 0; }
         }