BeginCriticalRegion() public static method

public static BeginCriticalRegion ( ) : void
return void
Esempio n. 1
0
        /// <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);
        }
Esempio n. 2
0
        /// <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
            }
        }
Esempio n. 3
0
        /// <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);
        }
Esempio n. 4
0
        /// <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
            }
        }
Esempio n. 5
0
            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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 10
0
        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);
        }
Esempio n. 11
0
        /// <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++;
            }
        }
Esempio n. 12
0
        /// <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++;
            }
        }
Esempio n. 13
0
        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();
                    }
                }
            }
        }
Esempio n. 14
0
        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;
            }
        }
Esempio n. 15
0
        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();
        }