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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|