//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // Note: // User spinlock functionality // using System; using Microsoft.Singularity; using System.Runtime.CompilerServices; using System.Threading; namespace System.Threading { [NoCCtor] [CLSCompliant(false)] [AccessedByRuntime("referenced from halidt.asm")] public struct SpinLock { /// /// /// Acquire spinlock /// /// [NoHeapAllocation] [Inline] public void Acquire() { Thread thread = Thread.CurrentThread; AcquireInternal(thread, thread.GetThreadId()); } /// /// /// Acquire spinlock /// /// /// Thread's Id acquiring spinlock /// [NoHeapAllocation] [Inline] public void Acquire(int threadId) { AcquireInternal(Thread.GetThreadFromThreadId(threadId), threadId); } /// /// /// Acquire spinlock /// /// /// Thread acquiring spinlock /// [NoHeapAllocation] public void Acquire(Thread thread) { AcquireInternal(thread, thread.GetThreadId()); } /// /// /// Release spinlock /// /// [NoHeapAllocation] public void Release() { Thread thread = Thread.CurrentThread; // Release spinlock ReleaseInternal(thread, thread.GetThreadId()); } /// /// /// Release spinlock /// /// /// Thread's Id releasing spinlock /// [NoHeapAllocation] public void Release(int threadId) { // Release spinlock ReleaseInternal(Thread.GetThreadFromThreadId(threadId), threadId); } /// /// /// Release spinlock /// /// /// Thread releasing spinlock /// [NoHeapAllocation] public void Release(Thread thread) { // Release spinlock ReleaseInternal(thread, thread.GetThreadId()); } /// /// /// Try to acquire the spin lock. Always return immediately. /// /// /// true if the spin lock is acquired. [NoHeapAllocation] public bool TryAcquire() { Thread thread = Thread.CurrentThread; return TryAcquireInternal(thread, thread.GetThreadId()); } /// /// /// Try to acquire the spin lock. Always return immediately. /// /// /// true if the spin lock is acquired. /// /// Thread acquiring spinlock /// [NoHeapAllocation] public bool TryAcquire(Thread thread) { int threadId = thread.GetThreadId(); return TryAcquireInternal(thread, thread.GetThreadId()); } /// /// /// Method to find out if spinlock is held by specified thread /// /// true if the spin lock is acquired. /// /// Thread to verify possible spinlock's ownership /// [NoHeapAllocation] public bool IsHeldBy(Thread thread) { return baseLock.IsHeldBy(thread.GetThreadId()+1); } /// /// /// Method to find out if spinlock is held by specified thread /// /// true if the spin lock is acquired. /// /// Thread's Id to verify possible spinlock's ownership /// [NoHeapAllocation] public bool IsHeldBy(int threadId) { return baseLock.IsHeldBy(threadId+1); } /// /// /// Assert thatf spinlock is held by specified thread /// /// /// Thread to verify possible spinlock's ownership /// [System.Diagnostics.Conditional("DEBUG")] [NoHeapAllocation] public void AssertHeldBy(Thread thread) { VTable.Assert(IsHeldBy(thread)); } /// /// /// Assert thatf spinlock is held by specified thread /// /// /// Thread's Id to verify possible spinlock's ownership /// [System.Diagnostics.Conditional("DEBUG")] [NoHeapAllocation] public void AssertHeldBy(int threadId) { VTable.Assert(IsHeldBy(threadId)); } /// /// /// Try to acquire the spin lock. Always return immediately. /// /// true if the spin lock is acquired. /// /// Thread acquiring spinlock /// Thread's Id acquiring spinlock /// [NoHeapAllocation] private bool TryAcquireInternal(Thread thread, int threadId) { bool result; VTable.Assert(thread != null); // Notify thread that we are about to acquire spinlock thread.NotifySpinLockAboutToAcquire(this.baseLock.Type); result = baseLock.TryAcquire(threadId+1); // If we didn't acquire spinlock -we should notify thread about it: Just use release // notification if (!result) { thread.NotifySpinLockReleased(this.baseLock.Type); } return result; } /// /// /// Acquire the spin lock. /// /// /// Thread acquiring spinlock /// Thread's Id acquiring spinlock /// [NoHeapAllocation] private void AcquireInternal(Thread thread, int threadId) { VTable.Assert(thread != null); // Thread has to be notified if we are about to acquire spinlock thread.NotifySpinLockAboutToAcquire(this.baseLock.Type); // Get lock baseLock.Acquire(threadId+1); } /// /// /// Release the spin lock. /// /// /// Thread releasing spinlock /// Thread's Id releasing spinlock /// [NoHeapAllocation] private void ReleaseInternal(Thread thread, int threadId) { // Assert preconditions: Thread can't be null VTable.Assert(thread != null); // Release spinlock baseLock.Release(threadId+1); // Don't forget to notify thread that it just released spinlock thread.NotifySpinLockReleased(this.baseLock.Type); } /// Actual mechanism implementing spinlock private SpinLockBase baseLock; } }