/// <summary> /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/> /// structure with the option to track thread IDs to improve debugging. /// </summary> /// <remarks> /// The default constructor for <see cref="SpinLock"/> tracks thread ownership. /// </remarks> /// <summary> /// Acquires the lock in a reliable manner, such that even if an exception occurs within the method /// call, <paramref name="lockTaken"/> can be examined reliably to determine whether the lock was /// acquired. /// </summary> /// <remarks> /// <see cref="SpinLock"/> is a non-reentrant lock, meaning that if a thread holds the lock, it is /// not allowed to enter the lock again. If thread ownership tracking is enabled (whether it's /// enabled is available through <see cref="IsThreadOwnerTrackingEnabled"/>), an exception will be /// thrown when a thread tries to re-enter a lock it already holds. However, if thread ownership /// tracking is disabled, attempting to enter a lock already held will result in deadlock. /// </remarks> /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref /// name="lockTaken"/> must be initialized to false prior to calling this method.</param> /// <exception cref="T:System.Threading.LockRecursionException"> /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// </exception> /// <exception cref="T:System.ArgumentException"> /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling Enter. /// </exception> public void Enter(ref bool lockTaken) { if (lockTaken) { lockTaken = false; throw new System.ArgumentException(Environment2.GetResourceString("SpinLock_TryReliableEnter_ArgumentException")); } // Fast path to acquire the lock if the lock is released // If the thread tracking enabled set the new owner to the current thread id // Id not, set the anonymous bit lock int observedOwner = m_owner; int newOwner = 0; bool threadTrackingEnabled = (m_owner & LOCK_ID_DISABLE_MASK) == 0; if (threadTrackingEnabled) { if (observedOwner == LOCK_UNOWNED) { newOwner = Thread.CurrentThread.ManagedThreadId; } } else if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { newOwner = observedOwner | LOCK_ANONYMOUS_OWNED; // set the lock bit } if (newOwner != 0) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif #if PFX_LEGACY_3_5 if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner) == observedOwner) { lockTaken = true; return; } #else if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { // Fast path succeeded return; } #endif #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } //Fast path failed, try slow path ContinueTryEnter(Timeout.Infinite, ref lockTaken); }
/// <summary> /// Initializes a new instance of the <see cref="T:System.Threading.SpinLock"/> /// structure with the option to track thread IDs to improve debugging. /// </summary> /// <remarks> /// The default constructor for <see cref="SpinLock"/> tracks thread ownership. /// </remarks> /// <summary> /// Acquires the lock in a reliable manner, such that even if an exception occurs within the method /// call, <paramref name="lockTaken"/> can be examined reliably to determine whether the lock was /// acquired. /// </summary> /// <remarks> /// <see cref="SpinLock"/> is a non-reentrant lock, meaning that if a thread holds the lock, it is /// not allowed to enter the lock again. If thread ownership tracking is enabled (whether it's /// enabled is available through <see cref="IsThreadOwnerTrackingEnabled"/>), an exception will be /// thrown when a thread tries to re-enter a lock it already holds. However, if thread ownership /// tracking is disabled, attempting to enter a lock already held will result in deadlock. /// </remarks> /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref /// name="lockTaken"/> must be initialized to false prior to calling this method.</param> /// <exception cref="T:System.Threading.LockRecursionException"> /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// </exception> /// <exception cref="T:System.ArgumentException"> /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling Enter. /// </exception> public void Enter(ref bool lockTaken) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif //Try to keep the code and branching in this method as small as possible in order to inline the method 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 { ContinueTryEnter(Timeout.Infinite, ref lockTaken); // Then try the slow path if any of the above conditions is met } }
/// <summary> /// ContinueTryEnter for the thread tracking mode enabled /// </summary> private void ContinueTryEnterWithThreadTracking(int millisecondsTimeout, uint startTime, ref bool lockTaken) { Contract.Assert(IsThreadOwnerTrackingEnabled); 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; if (m_owner == m_newOwner) { // We don't allow lock recursion. throw new LockRecursionException(Environment.GetResourceString("SpinLock_TryEnter_LockRecursionException")); } SpinWait spinner = new SpinWait(); // 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(); // Test before trying to CAS, to avoid acquiring the line exclusively unnecessarily. if (m_owner == lockUnowned) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif if (Interlocked.CompareExchange(ref m_owner, m_newOwner, lockUnowned, ref lockTaken) == lockUnowned) { return; } #if !FEATURE_CORECLR // The thread failed to get the lock, so we don't need to remain in a critical region. Thread.EndCriticalRegion(); #endif } // Check the timeout. We only RDTSC if the next spin will yield, to amortize the cost. if (millisecondsTimeout == 0 || (millisecondsTimeout != Timeout.Infinite && spinner.NextSpinWillYield && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)) { return; } } while (true); }
/// <summary> /// Attempts to acquire the lock in a reliable manner, such that even if an exception occurs within /// the method call, <paramref name="lockTaken"/> can be examined reliably to determine whether the /// lock was acquired. /// </summary> /// <remarks> /// Unlike <see cref="Enter"/>, TryEnter will not block indefinitely waiting for the lock to be /// available. It will block until either the lock is available or until the <paramref /// name="millisecondsTimeout"/> has expired. /// </remarks> /// <param name="millisecondsTimeout">The number of milliseconds to wait, or <see /// cref="System.Threading.Timeout.Infinite"/> (-1) to wait indefinitely.</param> /// <param name="lockTaken">True if the lock is acquired; otherwise, false. <paramref /// name="lockTaken"/> must be initialized to false prior to calling this method.</param> /// <exception cref="T:System.Threading.LockRecursionException"> /// Thread ownership tracking is enabled, and the current thread has already acquired this lock. /// </exception> /// <exception cref="T:System.ArgumentException"> /// The <paramref name="lockTaken"/> argument must be initialized to false prior to calling TryEnter. /// </exception> /// <exception cref="T:System.ArgumentOutOfRangeException"><paramref name="millisecondsTimeout"/> is /// a negative number other than -1, which represents an infinite time-out.</exception> public void TryEnter(int millisecondsTimeout, ref bool lockTaken) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif int observedOwner = m_owner; 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 { ContinueTryEnter(millisecondsTimeout, ref lockTaken); // The call the slow pth } }
internal void MutexTryCode(object userData) { SafeWaitHandle mutexHandle = null; // try block RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (m_initiallyOwned) { m_cleanupInfo.inCriticalRegion = true; #if !FEATURE_CORECLR Thread.BeginThreadAffinity(); Thread.BeginCriticalRegion(); #endif //!FEATURE_CORECLR } } int errorCode = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { errorCode = CreateMutexHandle(m_initiallyOwned, m_name, m_secAttrs, out mutexHandle); } if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); if (null != m_name && 0 != m_name.Length && Win32Native.ERROR_INVALID_HANDLE == errorCode) { throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", m_name)); } __Error.WinIOError(errorCode, m_name); } m_newMutex = errorCode != Win32Native.ERROR_ALREADY_EXISTS; m_mutex.SetHandleInternal(mutexHandle); mutexHandle.SetAsMutex(); m_mutex.hasThreadAffinity = true; }
public bool TryEnterWriteLock(int millisecondsTimeout) { Thread.BeginCriticalRegion(); bool flag = false; try { flag = this.TryEnterWriteLockCore(millisecondsTimeout); } finally { if (!flag) { Thread.EndCriticalRegion(); } } return(flag); }
public bool TryEnterUpgradeableReadLock(int millisecondsTimeout) { Thread.BeginCriticalRegion(); bool result = false; try { result = TryEnterUpgradeableReadLockCore(millisecondsTimeout); } finally { if (!result) { Thread.EndCriticalRegion(); } } return(result); }
internal void MutexTryCode(object userData) { SafeWaitHandle safeWaitHandle = null; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (this.m_initiallyOwned) { this.m_cleanupInfo.inCriticalRegion = true; Thread.BeginThreadAffinity(); Thread.BeginCriticalRegion(); } } int num = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { num = Mutex.CreateMutexHandle(this.m_initiallyOwned, this.m_name, this.m_secAttrs, out safeWaitHandle); } if (safeWaitHandle.IsInvalid) { safeWaitHandle.SetHandleAsInvalid(); if (this.m_name != null && this.m_name.Length != 0 && 6 == num) { throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", new object[] { this.m_name })); } __Error.WinIOError(num, this.m_name); } this.m_newMutex = (num != 183); this.m_mutex.SetHandleInternal(safeWaitHandle); this.m_mutex.hasThreadAffinity = true; }
private bool TryEnterUpgradeableReadLock(TimeoutTracker timeout) { #if !FEATURE_NETCORE Thread.BeginCriticalRegion(); #endif // !FEATURE_NETCORE bool result = false; try { result = TryEnterUpgradeableReadLockCore(timeout); } finally { #if !FEATURE_NETCORE if (!result) { Thread.EndCriticalRegion(); } #endif // !FEATURE_NETCORE } return(result); }
public void TryEnter(int millisecondsTimeout, ref bool lockTaken) { if (lockTaken) { lockTaken = false; throw new ArgumentException(Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException")); } if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); } int owner = this.m_owner; int managedThreadId = 0; if (this.IsThreadOwnerTrackingEnabled) { if (owner == 0) { managedThreadId = Thread.CurrentThread.ManagedThreadId; } } else if ((owner & 1) == 0) { managedThreadId = owner | 1; } if (managedThreadId != 0) { Thread.BeginCriticalRegion(); if (Interlocked.CompareExchange(ref this.m_owner, managedThreadId, owner, ref lockTaken) == owner) { return; } Thread.EndCriticalRegion(); } this.ContinueTryEnter(millisecondsTimeout, ref lockTaken); }
/// <summary> /// Try acquire the lock with long path, this is usually called after the first path in Enter and /// TryEnter failed The reason for short path is to make it inline in the run time which improves the /// performance. This method assumed that the parameter are validated in Enter ir TryENter method /// </summary> /// <param name="millisecondsTimeout">The timeout milliseconds</param> /// <param name="lockTaken">The lockTaken param</param> private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken) { long startTicks = 0; if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout != 0) { startTicks = DateTime.UtcNow.Ticks; } #if !FEATURE_PAL && !FEATURE_CORECLR // PAL doesn't support eventing, and we don't compile CDS providers for Coreclr if (CdsSyncEtwBCLProvider.Log.IsEnabled()) { CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(m_owner); } #endif if (IsThreadOwnerTrackingEnabled) { // Slow path for enabled thread tracking mode ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTicks, ref lockTaken); return; } // then thread tracking is disabled // In this case there are three ways to acquire the lock // 1- the first way the thread either tries to get the lock if it's free or updates the waiters, if the turn >= the processors count then go to 3 else go to 2 // 2- In this step the waiter threads spins and tries to acquire the lock, the number of spin iterations and spin count is dependent on the thread turn // the late the thread arrives the more it spins and less frequent it check the lock avilability // Also the spins count is increaes each iteration // If the spins iterations finished and failed to acquire the lock, go to step 3 // 3- This is the yielding step, there are two ways of yielding Thread.Yield and Sleep(1) // If the timeout is expired in after step 1, we need to decrement the waiters count before returning int observedOwner; //***Step 1, take the lock or update the waiters // try to acquire the lock directly if possoble or update the waiters count SpinWait spinner = new SpinWait(); while (true) { observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif #if PFX_LEGACY_3_5 if (Interlocked.CompareExchange(ref m_owner, observedOwner | 1, observedOwner) == observedOwner) { lockTaken = true; return; } #else if (Interlocked.CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner) { return; } #endif #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } 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 || Interlocked.CompareExchange(ref m_owner, observedOwner + 2, observedOwner) == observedOwner) { break; } spinner.SpinOnce(); } // Check the timeout. if (millisecondsTimeout == 0 || (millisecondsTimeout != Timeout.Infinite && TimeoutExpired(startTicks, millisecondsTimeout))) { DecrementWaiters(); return; } //***Step 2. Spinning //lock acquired failed and waiters updated int turn = ((observedOwner + 2) & WAITERS_MASK) / 2; int processorCount = PlatformHelper.ProcessorCount; if (turn < processorCount) { int processFactor = 1; for (int i = 1; i <= turn * SPINNING_FACTOR; i++) { Thread.SpinWait((turn + i) * SPINNING_FACTOR * processFactor); if (processFactor < processorCount) { processFactor++; } observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit Contract.Assert((newOwner & WAITERS_MASK) >= 0); #if PFX_LEGACY_3_5 if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner) == observedOwner) { lockTaken = true; return; } #else if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { return; } #endif #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } } } // Check the timeout. if (millisecondsTimeout != Timeout.Infinite && TimeoutExpired(startTicks, millisecondsTimeout)) { DecrementWaiters(); return; } //*** Step 3, Yielding //Sleep(1) every 50 yields int yieldsoFar = 0; while (true) { observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit Contract.Assert((newOwner & WAITERS_MASK) >= 0); #if PFX_LEGACY_3_5 if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner) == observedOwner) { lockTaken = true; return; } #else if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { return; } #endif #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } if (yieldsoFar % SLEEP_ONE_FREQUENCY == 0) { Thread.Sleep(1); } else if (yieldsoFar % SLEEP_ZERO_FREQUENCY == 0) { Thread.Sleep(0); } else { #if PFX_LEGACY_3_5 Platform.Yield(); #else Thread.Yield(); #endif } if (yieldsoFar % TIMEOUT_CHECK_FREQUENCY == 0) { //Check the timeout. if (millisecondsTimeout != Timeout.Infinite && TimeoutExpired(startTicks, millisecondsTimeout)) { DecrementWaiters(); return; } } yieldsoFar++; } }
/// <summary> /// Try acquire the lock with long path, this is usually called after the first path in Enter and /// TryEnter failed The reason for short path is to make it inline in the run time which improves the /// performance. This method assumed that the parameter are validated in Enter ir TryENter method /// </summary> /// <param name="millisecondsTimeout">The timeout milliseconds</param> /// <param name="lockTaken">The lockTaken param</param> private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken) { //Leave the critical region which is entered by the fast path #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif // The fast path doesn't throw any exception, so we have to validate the parameters here if (lockTaken) { lockTaken = false; throw new System.ArgumentException(Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException")); } if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException( "millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); } uint startTime = 0; if (millisecondsTimeout != Timeout.Infinite && millisecondsTimeout != 0) { startTime = TimeoutHelper.GetTime(); } #if !FEATURE_CORECLR if (CdsSyncEtwBCLProvider.Log.IsEnabled()) { CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(m_owner); } #endif if (IsThreadOwnerTrackingEnabled) { // Slow path for enabled thread tracking mode ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTime, ref lockTaken); return; } // then thread tracking is disabled // In this case there are three ways to acquire the lock // 1- the first way the thread either tries to get the lock if it's free or updates the waiters, if the turn >= the processors count then go to 3 else go to 2 // 2- In this step the waiter threads spins and tries to acquire the lock, the number of spin iterations and spin count is dependent on the thread turn // the late the thread arrives the more it spins and less frequent it check the lock avilability // Also the spins count is increases each iteration // If the spins iterations finished and failed to acquire the lock, go to step 3 // 3- This is the yielding step, there are two ways of yielding Thread.Yield and Sleep(1) // If the timeout is expired in after step 1, we need to decrement the waiters count before returning int observedOwner; int turn = int.MaxValue; //***Step 1, take the lock or update the waiters // try to acquire the lock directly if possible or update the waiters count observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif if (Interlocked.CompareExchange(ref m_owner, observedOwner | 1, observedOwner, ref lockTaken) == observedOwner) { return; } #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } 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; } } // Check the timeout. if (millisecondsTimeout == 0 || (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)) { DecrementWaiters(); return; } //***Step 2. Spinning //lock acquired failed and waiters updated int processorCount = PlatformHelper.ProcessorCount; if (turn < processorCount) { int processFactor = 1; for (int i = 1; i <= turn * SPINNING_FACTOR; i++) { Thread.SpinWait((turn + i) * SPINNING_FACTOR * processFactor); if (processFactor < processorCount) { processFactor++; } observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit Contract.Assert((newOwner & WAITERS_MASK) >= 0); if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { return; } #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } } } // Check the timeout. if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) { DecrementWaiters(); return; } //*** Step 3, Yielding //Sleep(1) every 50 yields int yieldsoFar = 0; while (true) { observedOwner = m_owner; if ((observedOwner & LOCK_ANONYMOUS_OWNED) == LOCK_UNOWNED) { #if !FEATURE_CORECLR Thread.BeginCriticalRegion(); #endif int newOwner = (observedOwner & WAITERS_MASK) == 0 ? // Gets the number of waiters, if zero observedOwner | 1 // don't decrement it. just set the lock bit, it is zzero because a previous call of Exit(false) ehich corrupted the waiters : (observedOwner - 2) | 1; // otherwise decrement the waiters and set the lock bit Contract.Assert((newOwner & WAITERS_MASK) >= 0); if (Interlocked.CompareExchange(ref m_owner, newOwner, observedOwner, ref lockTaken) == observedOwner) { return; } #if !FEATURE_CORECLR Thread.EndCriticalRegion(); #endif } if (yieldsoFar % SLEEP_ONE_FREQUENCY == 0) { Thread.Sleep(1); } else if (yieldsoFar % SLEEP_ZERO_FREQUENCY == 0) { Thread.Sleep(0); } else { Thread.Yield(); } if (yieldsoFar % TIMEOUT_CHECK_FREQUENCY == 0) { //Check the timeout. if (millisecondsTimeout != Timeout.Infinite && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) { DecrementWaiters(); return; } } yieldsoFar++; } }
private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken) { Thread.EndCriticalRegion(); if (lockTaken) { lockTaken = false; throw new ArgumentException(Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException")); } if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout", (object)millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); } uint startTime = 0; if (millisecondsTimeout != -1 && millisecondsTimeout != 0) { startTime = TimeoutHelper.GetTime(); } if (CdsSyncEtwBCLProvider.Log.IsEnabled()) { CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(this.m_owner); } if (this.IsThreadOwnerTrackingEnabled) { this.ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTime, ref lockTaken); } else { int num1 = int.MaxValue; int comparand1 = this.m_owner; if ((comparand1 & 1) == 0) { Thread.BeginCriticalRegion(); if (Interlocked.CompareExchange(ref this.m_owner, comparand1 | 1, comparand1, ref lockTaken) == comparand1) { return; } Thread.EndCriticalRegion(); } else if ((comparand1 & 2147483646) != SpinLock.MAXIMUM_WAITERS) { num1 = (Interlocked.Add(ref this.m_owner, 2) & 2147483646) >> 1; } if (millisecondsTimeout == 0 || millisecondsTimeout != -1 && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) { this.DecrementWaiters(); } else { int processorCount = PlatformHelper.ProcessorCount; if (num1 < processorCount) { int num2 = 1; for (int index = 1; index <= num1 * 100; ++index) { Thread.SpinWait((num1 + index) * 100 * num2); if (num2 < processorCount) { ++num2; } int comparand2 = this.m_owner; if ((comparand2 & 1) == 0) { Thread.BeginCriticalRegion(); if (Interlocked.CompareExchange(ref this.m_owner, (comparand2 & 2147483646) == 0 ? comparand2 | 1 : comparand2 - 2 | 1, comparand2, ref lockTaken) == comparand2) { return; } Thread.EndCriticalRegion(); } } } if (millisecondsTimeout != -1 && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) { this.DecrementWaiters(); } else { int num2 = 0; while (true) { int comparand2 = this.m_owner; if ((comparand2 & 1) == 0) { Thread.BeginCriticalRegion(); if (Interlocked.CompareExchange(ref this.m_owner, (comparand2 & 2147483646) == 0 ? comparand2 | 1 : comparand2 - 2 | 1, comparand2, ref lockTaken) != comparand2) { Thread.EndCriticalRegion(); } else { break; } } if (num2 % 40 == 0) { Thread.Sleep(1); } else if (num2 % 10 == 0) { Thread.Sleep(0); } else { Thread.Yield(); } if (num2 % 10 != 0 || millisecondsTimeout == -1 || TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) > 0) { ++num2; } else { goto label_40; } } return; label_40: this.DecrementWaiters(); } } } }
private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken) { int owner; long startTicks = 0L; if ((millisecondsTimeout != -1) && (millisecondsTimeout != 0)) { startTicks = DateTime.UtcNow.Ticks; } if (CdsSyncEtwBCLProvider.Log.IsEnabled()) { CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(this.m_owner); } if (this.IsThreadOwnerTrackingEnabled) { this.ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTicks, ref lockTaken); return; } SpinWait wait = new SpinWait(); while (true) { owner = this.m_owner; if ((owner & 1) == 0) { Thread.BeginCriticalRegion(); if (Interlocked.CompareExchange(ref this.m_owner, owner | 1, owner, ref lockTaken) == owner) { return; } Thread.EndCriticalRegion(); } else if (((owner & 0x7ffffffe) == MAXIMUM_WAITERS) || (Interlocked.CompareExchange(ref this.m_owner, owner + 2, owner) == owner)) { break; } wait.SpinOnce(); } if ((millisecondsTimeout == 0) || ((millisecondsTimeout != -1) && TimeoutExpired(startTicks, millisecondsTimeout))) { this.DecrementWaiters(); return; } int num3 = ((owner + 2) & 0x7ffffffe) / 2; int processorCount = PlatformHelper.ProcessorCount; if (num3 < processorCount) { int num5 = 1; for (int i = 1; i <= (num3 * 100); i++) { Thread.SpinWait(((num3 + i) * 100) * num5); if (num5 < processorCount) { num5++; } owner = this.m_owner; if ((owner & 1) == 0) { Thread.BeginCriticalRegion(); int num7 = ((owner & 0x7ffffffe) == 0) ? (owner | 1) : ((owner - 2) | 1); if (Interlocked.CompareExchange(ref this.m_owner, num7, owner, ref lockTaken) == owner) { return; } Thread.EndCriticalRegion(); } } } if ((millisecondsTimeout != -1) && TimeoutExpired(startTicks, millisecondsTimeout)) { this.DecrementWaiters(); return; } int num8 = 0; Label_015F: owner = this.m_owner; if ((owner & 1) == 0) { Thread.BeginCriticalRegion(); int num9 = ((owner & 0x7ffffffe) == 0) ? (owner | 1) : ((owner - 2) | 1); if (Interlocked.CompareExchange(ref this.m_owner, num9, owner, ref lockTaken) == owner) { return; } Thread.EndCriticalRegion(); } if ((num8 % 40) == 0) { Thread.Sleep(1); } else if ((num8 % 10) == 0) { Thread.Sleep(0); } else { Thread.Yield(); } if ((((num8 % 10) == 0) && (millisecondsTimeout != -1)) && TimeoutExpired(startTicks, millisecondsTimeout)) { this.DecrementWaiters(); } else { num8++; goto Label_015F; } }
public unsafe Mutex(bool initiallyOwned, string name, out bool createdNew, MutexSecurity mutexSecurity) { if ((name != null) && (260 < name.Length)) { throw new ArgumentException(Environment.GetResourceString("Argument_WaitHandleNameTooLong", new object[] { name })); } Win32Native.SECURITY_ATTRIBUTES secAttrs = null; if (mutexSecurity != null) { secAttrs = new Win32Native.SECURITY_ATTRIBUTES { nLength = Marshal.SizeOf(secAttrs) }; byte[] securityDescriptorBinaryForm = mutexSecurity.GetSecurityDescriptorBinaryForm(); byte * pDest = stackalloc byte[1 * securityDescriptorBinaryForm.Length]; Buffer.memcpy(securityDescriptorBinaryForm, 0, pDest, 0, securityDescriptorBinaryForm.Length); secAttrs.pSecurityDescriptor = pDest; } SafeWaitHandle mutexHandle = null; bool newMutex = false; RuntimeHelpers.CleanupCode backoutCode = new RuntimeHelpers.CleanupCode(this.MutexCleanupCode); MutexCleanupInfo cleanupInfo = new MutexCleanupInfo(mutexHandle, false); RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(delegate(object userData) { RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { if (initiallyOwned) { cleanupInfo.inCriticalRegion = true; Thread.BeginThreadAffinity(); Thread.BeginCriticalRegion(); } } int errorCode = 0; RuntimeHelpers.PrepareConstrainedRegions(); try { } finally { errorCode = CreateMutexHandle(initiallyOwned, name, secAttrs, out mutexHandle); } if (mutexHandle.IsInvalid) { mutexHandle.SetHandleAsInvalid(); if (((name != null) && (name.Length != 0)) && (6 == errorCode)) { throw new WaitHandleCannotBeOpenedException(Environment.GetResourceString("Threading.WaitHandleCannotBeOpenedException_InvalidHandle", new object[] { name })); } __Error.WinIOError(errorCode, name); } newMutex = errorCode != 0xb7; this.SetHandleInternal(mutexHandle); this.hasThreadAffinity = true; }, backoutCode, cleanupInfo); createdNew = newMutex; }
// Token: 0x06003D91 RID: 15761 RVA: 0x000E49DC File Offset: 0x000E2BDC private void ContinueTryEnter(int millisecondsTimeout, ref bool lockTaken) { Thread.EndCriticalRegion(); if (lockTaken) { lockTaken = false; throw new ArgumentException(Environment.GetResourceString("SpinLock_TryReliableEnter_ArgumentException")); } if (millisecondsTimeout < -1) { throw new ArgumentOutOfRangeException("millisecondsTimeout", millisecondsTimeout, Environment.GetResourceString("SpinLock_TryEnter_ArgumentOutOfRange")); } uint startTime = 0U; if (millisecondsTimeout != -1 && millisecondsTimeout != 0) { startTime = TimeoutHelper.GetTime(); } if (CdsSyncEtwBCLProvider.Log.IsEnabled()) { CdsSyncEtwBCLProvider.Log.SpinLock_FastPathFailed(this.m_owner); } if (this.IsThreadOwnerTrackingEnabled) { this.ContinueTryEnterWithThreadTracking(millisecondsTimeout, startTime, ref lockTaken); return; } int num = int.MaxValue; int owner = this.m_owner; if ((owner & 1) == 0) { Thread.BeginCriticalRegion(); if (Interlocked.CompareExchange(ref this.m_owner, owner | 1, owner, ref lockTaken) == owner) { return; } Thread.EndCriticalRegion(); } else if ((owner & 2147483646) != SpinLock.MAXIMUM_WAITERS) { num = (Interlocked.Add(ref this.m_owner, 2) & 2147483646) >> 1; } if (millisecondsTimeout == 0 || (millisecondsTimeout != -1 && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0)) { this.DecrementWaiters(); return; } int processorCount = PlatformHelper.ProcessorCount; if (num < processorCount) { int num2 = 1; for (int i = 1; i <= num * 100; i++) { Thread.SpinWait((num + i) * 100 * num2); if (num2 < processorCount) { num2++; } owner = this.m_owner; if ((owner & 1) == 0) { Thread.BeginCriticalRegion(); int value = ((owner & 2147483646) == 0) ? (owner | 1) : (owner - 2 | 1); if (Interlocked.CompareExchange(ref this.m_owner, value, owner, ref lockTaken) == owner) { return; } Thread.EndCriticalRegion(); } } } if (millisecondsTimeout != -1 && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) { this.DecrementWaiters(); return; } int num3 = 0; for (;;) { owner = this.m_owner; if ((owner & 1) == 0) { Thread.BeginCriticalRegion(); int value2 = ((owner & 2147483646) == 0) ? (owner | 1) : (owner - 2 | 1); if (Interlocked.CompareExchange(ref this.m_owner, value2, owner, ref lockTaken) == owner) { break; } Thread.EndCriticalRegion(); } if (num3 % 40 == 0) { Thread.Sleep(1); } else if (num3 % 10 == 0) { Thread.Sleep(0); } else { Thread.Yield(); } if (num3 % 10 == 0 && millisecondsTimeout != -1 && TimeoutHelper.UpdateTimeOut(startTime, millisecondsTimeout) <= 0) { goto Block_26; } num3++; } return; Block_26: this.DecrementWaiters(); }