singrdk/base/Kernel/Singularity/ServiceRequestQueue.cs

101 lines
2.8 KiB
C#
Raw Permalink Normal View History

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