Protect TryEnter and Exit methods of SpinLock against asynchronous exceptions.
[mono.git] / mcs / class / corlib / System.Threading / SpinWait.cs
index 8687bc21c4e0b6cb4573bcd1cb55083e4fdd5bff..d46376bc0439bde0dbde55c160a338c87010d14a 100644 (file)
@@ -1,4 +1,3 @@
-#if NET_4_0 || BOOTSTRAP_NET_4_0
 // SpinWait.cs
 //
 // Copyright (c) 2008 Jérémie "Garuma" Laval
 //
 //
 
+#if NET_4_0 || BOOTSTRAP_NET_4_0
 using System;
 
 namespace System.Threading
 {
-
        public struct SpinWait
        {
                // The number of step until SpinOnce yield on multicore machine
                const           int  step = 5;
+               const           int  maxTime = 50;
                static readonly bool isSingleCpu = (Environment.ProcessorCount == 1);
 
                int ntime;
 
                public void SpinOnce ()
                {
-                       // On a single-CPU system, spinning does no good
                        if (isSingleCpu) {
-                               Yield ();
+                               // On a single-CPU system, spinning does no good
+                               Thread.Yield ();
                        } else {
-                               if (Interlocked.Increment (ref ntime) % step == 0) {
-                                       Yield ();
-                               } else {
+                               if ((ntime = ntime == maxTime ? maxTime : ntime + 1) % step == 0)
+                                       Thread.Yield ();
+                               else
                                        // Multi-CPU system might be hyper-threaded, let other thread run
-                                       Thread.SpinWait (2 * (ntime + 1));
-                               }
+                                       Thread.SpinWait (ntime << 1);
                        }
                }
 
@@ -77,13 +76,6 @@ namespace System.Threading
                        return true;
                }
 
-               void Yield ()
-               {
-                       // Replace sched_yield by Thread.Sleep(0) which does almost the same thing
-                       // (going back in kernel mode and yielding) but avoid the branching and unmanaged bridge
-                       Thread.Sleep (0);
-               }
-
                public void Reset ()
                {
                        ntime = 0;