Beispiel #1
0
        public LowLevelLock()
        {
#if DEBUG
            _ownerThread = null;
#endif

            _spinWaiter = new LowLevelSpinWaiter();
            _spinWaitTryAcquireCallback = SpinWaitTryAcquireCallback;
            _monitor = new LowLevelMonitor();
        }
        public bool Wait(int timeoutMs)
        {
            Debug.Assert(timeoutMs >= -1);

            // Try to acquire the semaphore or
            // a) register as a spinner if spinCount > 0 and timeoutMs > 0
            // b) register as a waiter if there's already too many spinners or spinCount == 0 and timeoutMs > 0
            // c) bail out if timeoutMs == 0 and return false
            Counts counts = _separated._counts;

            while (true)
            {
                Debug.Assert(counts._signalCount <= _maximumSignalCount);
                Counts newCounts = counts;

                if (counts._signalCount != 0)
                {
                    newCounts._signalCount--;
                }
                else if (timeoutMs != 0)
                {
                    if (_spinCount > 0 && newCounts._spinnerCount < byte.MaxValue)
                    {
                        newCounts._spinnerCount++;
                    }
                    else
                    {
                        // Maximum number of spinners reached, register as a waiter instead
                        newCounts._waiterCount++;
                        Debug.Assert(newCounts._waiterCount != 0); // overflow check, this many waiters is currently not supported
                    }
                }

                Counts countsBeforeUpdate = _separated._counts.CompareExchange(newCounts, counts);
                if (countsBeforeUpdate == counts)
                {
                    if (counts._signalCount != 0)
                    {
                        return(true);
                    }
                    if (newCounts._waiterCount != counts._waiterCount)
                    {
                        return(WaitForSignal(timeoutMs));
                    }
                    if (timeoutMs == 0)
                    {
                        return(false);
                    }
                    break;
                }

                counts = countsBeforeUpdate;
            }

            int processorCount = Environment.ProcessorCount;
            int spinIndex      = processorCount > 1 ? 0 : SpinSleep0Threshold;

            while (spinIndex < _spinCount)
            {
                LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, processorCount);
                spinIndex++;

                // Try to acquire the semaphore and unregister as a spinner
                counts = _separated._counts;
                while (counts._signalCount > 0)
                {
                    Counts newCounts = counts;
                    newCounts._signalCount--;
                    newCounts._spinnerCount--;

                    Counts countsBeforeUpdate = _separated._counts.CompareExchange(newCounts, counts);
                    if (countsBeforeUpdate == counts)
                    {
                        return(true);
                    }

                    counts = countsBeforeUpdate;
                }
            }

            // Unregister as spinner and acquire the semaphore or register as a waiter
            counts = _separated._counts;
            while (true)
            {
                Counts newCounts = counts;
                newCounts._spinnerCount--;
                if (counts._signalCount != 0)
                {
                    newCounts._signalCount--;
                }
                else
                {
                    newCounts._waiterCount++;
                    Debug.Assert(newCounts._waiterCount != 0); // overflow check, this many waiters is currently not supported
                }

                Counts countsBeforeUpdate = _separated._counts.CompareExchange(newCounts, counts);
                if (countsBeforeUpdate == counts)
                {
                    return(counts._signalCount != 0 || WaitForSignal(timeoutMs));
                }

                counts = countsBeforeUpdate;
            }
        }
Beispiel #3
0
 public LowLevelLock()
 {
     _spinWaiter = default(LowLevelSpinWaiter);
     _monitor.Initialize();
 }
        public bool Wait(int timeoutMs, bool spinWait)
        {
            Debug.Assert(timeoutMs >= -1);

            int spinCount = spinWait ? _spinCount : 0;

            // Try to acquire the semaphore or
            // a) register as a spinner if spinCount > 0 and timeoutMs > 0
            // b) register as a waiter if there's already too many spinners or spinCount == 0 and timeoutMs > 0
            // c) bail out if timeoutMs == 0 and return false
            Counts counts = _separated._counts;

            while (true)
            {
                Debug.Assert(counts.SignalCount <= _maximumSignalCount);
                Counts newCounts = counts;
                if (counts.SignalCount != 0)
                {
                    newCounts.DecrementSignalCount();
                }
                else if (timeoutMs != 0)
                {
                    if (spinCount > 0 && newCounts.SpinnerCount < byte.MaxValue)
                    {
                        newCounts.IncrementSpinnerCount();
                    }
                    else
                    {
                        // Maximum number of spinners reached, register as a waiter instead
                        newCounts.IncrementWaiterCount();
                    }
                }

                Counts countsBeforeUpdate = _separated._counts.InterlockedCompareExchange(newCounts, counts);
                if (countsBeforeUpdate == counts)
                {
                    if (counts.SignalCount != 0)
                    {
                        return(true);
                    }
                    if (newCounts.WaiterCount != counts.WaiterCount)
                    {
                        return(WaitForSignal(timeoutMs));
                    }
                    if (timeoutMs == 0)
                    {
                        return(false);
                    }
                    break;
                }

                counts = countsBeforeUpdate;
            }

#if CORECLR && TARGET_UNIX
            // The PAL's wait subsystem is slower, spin more to compensate for the more expensive wait
            spinCount *= 2;
#endif
            int processorCount = Environment.ProcessorCount;
            int spinIndex      = processorCount > 1 ? 0 : SpinSleep0Threshold;
            while (spinIndex < spinCount)
            {
                LowLevelSpinWaiter.Wait(spinIndex, SpinSleep0Threshold, processorCount);
                spinIndex++;

                // Try to acquire the semaphore and unregister as a spinner
                counts = _separated._counts;
                while (counts.SignalCount > 0)
                {
                    Counts newCounts = counts;
                    newCounts.DecrementSignalCount();
                    newCounts.DecrementSpinnerCount();

                    Counts countsBeforeUpdate = _separated._counts.InterlockedCompareExchange(newCounts, counts);
                    if (countsBeforeUpdate == counts)
                    {
                        return(true);
                    }

                    counts = countsBeforeUpdate;
                }
            }

            // Unregister as spinner, and acquire the semaphore or register as a waiter
            counts = _separated._counts;
            while (true)
            {
                Counts newCounts = counts;
                newCounts.DecrementSpinnerCount();
                if (counts.SignalCount != 0)
                {
                    newCounts.DecrementSignalCount();
                }
                else
                {
                    newCounts.IncrementWaiterCount();
                }

                Counts countsBeforeUpdate = _separated._counts.InterlockedCompareExchange(newCounts, counts);
                if (countsBeforeUpdate == counts)
                {
                    return(counts.SignalCount != 0 || WaitForSignal(timeoutMs));
                }

                counts = countsBeforeUpdate;
            }
        }
Beispiel #5
0
 public LowLevelLock()
 {
     _spinWaiter = default(LowLevelSpinWaiter);
     _spinWaitTryAcquireCallback = SpinWaitTryAcquireCallback;
     _monitor.Initialize();
 }