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; } }
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; } }
public LowLevelLock() { _spinWaiter = default(LowLevelSpinWaiter); _spinWaitTryAcquireCallback = SpinWaitTryAcquireCallback; _monitor.Initialize(); }