This commit is contained in:
Bill Zissimopoulos
2015-12-28 11:17:37 -08:00
parent 3d381145e3
commit 72fdea5e78
6 changed files with 81 additions and 116 deletions

View File

@ -55,10 +55,14 @@
* queue is not empty.
*/
#define InterruptTimeToSecFactor 10000000
#define ConvertInterruptTimeToSec(Time) ((ULONG)((Time) / InterruptTimeToSecFactor))
#define QueryInterruptTimeInSec() ConvertInterruptTimeToSec(KeQueryInterruptTime())
typedef struct
{
PVOID IrpHint;
ULONGLONG ExpirationTime;
ULONG ExpirationTime;
} FSP_IOQ_PEEK_CONTEXT;
static NTSTATUS FspIoqPendingInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertContext)
@ -99,8 +103,8 @@ static PIRP FspIoqPendingPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext)
PVOID IrpHint = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->IrpHint;
if (0 == IrpHint)
{
ULONGLONG ExpirationTime = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->ExpirationTime;
return FspIrpContext(Irp)->ExpirationTime <= ExpirationTime ? Irp : 0;
ULONG ExpirationTime = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->ExpirationTime;
return FspIrpTimestamp(Irp) <= ExpirationTime ? Irp : 0;
}
else
return Irp;
@ -132,19 +136,29 @@ static NTSTATUS FspIoqProcessInsertIrpEx(PIO_CSQ IoCsq, PIRP Irp, PVOID InsertCo
if (Ioq->Stopped)
return STATUS_CANCELLED;
InsertTailList(&Ioq->ProcessIrpList, &Irp->Tail.Overlay.ListEntry);
ASSERT(0 == FspDictGetEntry(&Ioq->ProcessIrpDict, Irp));
FSP_DICT_ENTRY DictEntry = { 0 };
DictEntry.Key = Irp;
FspDictSetEntry(&Ioq->ProcessIrpDict, &DictEntry);
ULONG Index = FspHashMixPointer(Irp) % Ioq->ProcessIrpBucketCount;
#if DBG
for (PIRP IrpX = Ioq->ProcessIrpBuckets[Index]; IrpX; IrpX = FspIrpDictNext(IrpX))
ASSERT(IrpX != Irp);
#endif
FspIrpDictNext(Irp) = Ioq->ProcessIrpBuckets[Index];
Ioq->ProcessIrpBuckets[Index] = Irp;
return STATUS_SUCCESS;
}
static VOID FspIoqProcessRemoveIrp(PIO_CSQ IoCsq, PIRP Irp)
{
FSP_IOQ *Ioq = CONTAINING_RECORD(IoCsq, FSP_IOQ, ProcessIoCsq);
FSP_DICT_ENTRY *DictEntry; (VOID)DictEntry;
DictEntry = FspDictRemoveEntry(&Ioq->ProcessIrpDict, Irp);
ASSERT(0 == DictEntry);
ULONG Index = FspHashMixPointer(Irp) % Ioq->ProcessIrpBucketCount;
for (PIRP *PIrp = (PIRP *)&Ioq->ProcessIrpBuckets[Index];; PIrp = &FspIrpDictNext(*PIrp))
{
ASSERT(0 != *PIrp);
if (*PIrp == Irp)
{
*PIrp = FspIrpDictNext(*PIrp);
break;
}
}
RemoveEntryList(&Irp->Tail.Overlay.ListEntry);
}
@ -163,13 +177,16 @@ static PIRP FspIoqProcessPeekNextIrp(PIO_CSQ IoCsq, PIRP Irp, PVOID PeekContext)
PVOID IrpHint = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->IrpHint;
if (0 == IrpHint)
{
ULONGLONG ExpirationTime = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->ExpirationTime;
return FspIrpContext(Irp)->ExpirationTime <= ExpirationTime ? Irp : 0;
ULONG ExpirationTime = ((FSP_IOQ_PEEK_CONTEXT *)PeekContext)->ExpirationTime;
return FspIrpTimestamp(Irp) <= ExpirationTime ? Irp : 0;
}
else
{
FSP_DICT_ENTRY *DictEntry = FspDictGetEntry(&Ioq->ProcessIrpDict, IrpHint);
return 0 != DictEntry ? (PIRP)IrpHint : 0;
ULONG Index = FspHashMixPointer(IrpHint) % Ioq->ProcessIrpBucketCount;
for (Irp = Ioq->ProcessIrpBuckets[Index]; Irp; Irp = FspIrpDictNext(Irp))
if (Irp == IrpHint)
return Irp;
return 0;
}
}
@ -193,16 +210,6 @@ static VOID FspIoqProcessCompleteCanceledIrp(PIO_CSQ IoCsq, PIRP Irp)
Ioq->CompleteCanceledIrp(Irp);
}
BOOLEAN FspIoqIrpEquals(PVOID Irp1, PVOID Irp2)
{
return Irp1 == Irp2;
}
ULONG FspIoqIrpHash(PVOID Irp)
{
return (ULONG)(UINT_PTR)Irp;
}
NTSTATUS FspIoqCreate(
ULONG IrpCapacity, PLARGE_INTEGER IrpTimeout, VOID (*CompleteCanceledIrp)(PIRP Irp),
FSP_IOQ **PIoq)
@ -212,12 +219,12 @@ NTSTATUS FspIoqCreate(
*PIoq = 0;
FSP_IOQ *Ioq;
ULONG BucketCount = (PAGE_SIZE - sizeof *Ioq) / sizeof Ioq->ProcessIrpDictBuckets[0];
ULONG BucketCount = (PAGE_SIZE - sizeof *Ioq) / sizeof Ioq->ProcessIrpBuckets[0];
Ioq = FspAllocNonPaged(PAGE_SIZE);
if (0 == Ioq)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(Ioq, PAGE_SIZE);
RtlZeroMemory(Ioq, sizeof *Ioq);
KeInitializeSpinLock(&Ioq->SpinLock);
KeInitializeEvent(&Ioq->PendingIrpEvent, NotificationEvent, FALSE);
InitializeListHead(&Ioq->PendingIrpList);
@ -236,11 +243,11 @@ NTSTATUS FspIoqCreate(
FspIoqProcessAcquireLock,
FspIoqProcessReleaseLock,
FspIoqProcessCompleteCanceledIrp);
FspDictInitialize(&Ioq->ProcessIrpDict,
FspIoqIrpEquals, FspIoqIrpHash, Ioq->ProcessIrpDictBuckets, BucketCount);
Ioq->IrpTimeout = *IrpTimeout;
Ioq->IrpTimeout = ConvertInterruptTimeToSec(IrpTimeout->QuadPart + InterruptTimeToSecFactor - 1);
/* convert to seconds (and round up) */
Ioq->PendingIrpCapacity = IrpCapacity;
Ioq->CompleteCanceledIrp = CompleteCanceledIrp;
Ioq->ProcessIrpBucketCount = BucketCount;
*PIoq = Ioq;
@ -282,7 +289,7 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq)
{
FSP_IOQ_PEEK_CONTEXT PeekContext;
PeekContext.IrpHint = 0;
PeekContext.ExpirationTime = KeQueryInterruptTime();
PeekContext.ExpirationTime = QueryInterruptTimeInSec();
PIRP Irp;
while (0 != (Irp = IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, &PeekContext)))
Ioq->CompleteCanceledIrp(Irp);
@ -293,7 +300,7 @@ VOID FspIoqRemoveExpired(FSP_IOQ *Ioq)
BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp, NTSTATUS *PResult)
{
NTSTATUS Result;
FspIrpContext(Irp)->ExpirationTime = KeQueryInterruptTime() + Ioq->IrpTimeout.QuadPart;
FspIrpTimestamp(Irp) = QueryInterruptTimeInSec() + Ioq->IrpTimeout;
Result = IoCsqInsertIrpEx(&Ioq->PendingIoCsq, Irp, 0, (PVOID)1);
if (NT_SUCCESS(Result))
return TRUE;
@ -323,6 +330,7 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, PLARGE_INTEGER Timeout)
BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp)
{
NTSTATUS Result;
FspIrpTimestamp(Irp) = QueryInterruptTimeInSec() + Ioq->IrpTimeout;
Result = IoCsqInsertIrpEx(&Ioq->ProcessIoCsq, Irp, 0, 0);
return NT_SUCCESS(Result);
}