//////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // File: ServiceRequestQueue.cs // // Note: // using System.Threading; using System.Runtime.CompilerServices; namespace Microsoft.Singularity { public class ServiceRequestQueue { // Invariant: head == null <==> tail == null // tail.next is undefined. private ServiceRequest head = null; private ServiceRequest tail = null; private SpinLock spinLock; private InterruptAwareAutoResetEvent enqueueEvent = new InterruptAwareAutoResetEvent(false); /// /// /// Constructor /// /// public ServiceRequestQueue() { spinLock = new SpinLock(SpinLock.Types.ServiceQueue); } // Insert an element at the tail of the queue. [NoHeapAllocation] public void Enqueue(ServiceRequest req) { // For now disable interrupts: bool iflag = Processor.DisableInterrupts(); spinLock.Acquire(); try { if (head == null) { head = req; tail = req; } else { tail.next = req; tail = req; } } finally { spinLock.Release(); } // Signal an event : for now it is possible that it can be spirous one... enqueueEvent.InterruptAwareSet(); // Reenable interrupts Processor.RestoreInterrupts(iflag); } // Block while the queue is empty, then return the head of the queue. public ServiceRequest Dequeue() { while (true) { // For now disable interrupts: bool iflag = Processor.DisableInterrupts(); spinLock.Acquire(); try { if (tail != null) { ServiceRequest req = head; if (req != tail) { head = req.next; } else { head = null; tail = null; } return req; } } finally { spinLock.Release(); // Reenable interrupts Processor.RestoreInterrupts(iflag); } // Wait on event enqueueEvent.InterruptAwareWaitOne(); } } } }