From 25f6bd52a7f25f63ef0b2ccc6c98c15a85a3ed13 Mon Sep 17 00:00:00 2001 From: Bill Zissimopoulos Date: Tue, 24 Nov 2015 15:59:43 -0800 Subject: [PATCH] sys: FspTransactThread --- build/VStudio/winfsp.vcxproj | 1 + build/VStudio/winfsp.vcxproj.filters | 3 + src/sys/driver.h | 12 ++++ src/sys/ioq.c | 7 ++- src/sys/transact.c | 82 ++++++++++++++++++++++++++++ 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/sys/transact.c diff --git a/build/VStudio/winfsp.vcxproj b/build/VStudio/winfsp.vcxproj index f7d94004..4b118dde 100644 --- a/build/VStudio/winfsp.vcxproj +++ b/build/VStudio/winfsp.vcxproj @@ -149,6 +149,7 @@ + diff --git a/build/VStudio/winfsp.vcxproj.filters b/build/VStudio/winfsp.vcxproj.filters index eb72665c..fba2a105 100644 --- a/build/VStudio/winfsp.vcxproj.filters +++ b/build/VStudio/winfsp.vcxproj.filters @@ -77,6 +77,9 @@ Source + + Source + diff --git a/src/sys/driver.h b/src/sys/driver.h index a897b3c5..8783c066 100644 --- a/src/sys/driver.h +++ b/src/sys/driver.h @@ -155,12 +155,24 @@ typedef struct } FSP_IOQ; VOID FspIoqInitialize(FSP_IOQ *Ioq); VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta); +PKEVENT FspIoqPendingIrpEvent(FSP_IOQ *Ioq); BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp); PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis); BOOLEAN FspIoqStartProcessingIrp(FSP_IOQ *Ioq, PIRP Irp); PIRP FspIoqEndProcessingIrp(FSP_IOQ *Ioq, UINT_PTR IrpHint); VOID FspIoqCancelAll(FSP_IOQ *Ioq); +/* transact thread */ +typedef struct +{ + PKTHREAD Thread; + KEVENT Event; + FSP_IOQ *TransactIoq, *Ioq; +} FSP_TRANSACT_THREAD; +NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread, + FSP_IOQ *TransactIoq, FSP_IOQ *Ioq); +VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread); + /* device extensions */ enum { diff --git a/src/sys/ioq.c b/src/sys/ioq.c index 384d9ec4..8a7f9e10 100644 --- a/src/sys/ioq.c +++ b/src/sys/ioq.c @@ -174,6 +174,11 @@ VOID FspIoqEnable(FSP_IOQ *Ioq, int Delta) KeReleaseSpinLock(&Ioq->SpinLock, Irql); } +PKEVENT FspIoqPendingIrpEvent(FSP_IOQ *Ioq) +{ + return &Ioq->PendingIrpEvent; +} + BOOLEAN FspIoqPostIrp(FSP_IOQ *Ioq, PIRP Irp) { NTSTATUS Result; @@ -190,7 +195,7 @@ PIRP FspIoqNextPendingIrp(FSP_IOQ *Ioq, ULONG millis) Timeout.QuadPart = (LONGLONG)millis * 10000; Result = KeWaitForSingleObject(&Ioq->PendingIrpEvent, Executive, KernelMode, FALSE, -1 == millis ? 0 : &Timeout); - if (!NT_SUCCESS(Result)) + if (STATUS_SUCCESS != Result) return 0; } return IoCsqRemoveNextIrp(&Ioq->PendingIoCsq, (PVOID)1); diff --git a/src/sys/transact.c b/src/sys/transact.c new file mode 100644 index 00000000..e9dcff6f --- /dev/null +++ b/src/sys/transact.c @@ -0,0 +1,82 @@ +/** + * @file sys/transact.c + * + * @copyright 2015 Bill Zissimopoulos + */ + +#include + +static KSTART_ROUTINE FspTransactThread; +NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread, + FSP_IOQ *TransactIoq, FSP_IOQ *Ioq); +VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread); + +#ifdef ALLOC_PRAGMA +#pragma alloc_text(PAGE, FspTransactThread) +#pragma alloc_text(PAGE, FspTransactThreadStart) +#pragma alloc_text(PAGE, FspTransactThreadStop) +#endif + +static VOID FspTransactThread(PVOID StartContext) +{ + PAGED_CODE(); + + FSP_TRANSACT_THREAD *TransactThread = StartContext; + PVOID WaitObjects[2]; + WaitObjects[0] = &TransactThread->Event; + WaitObjects[1] = FspIoqPendingIrpEvent(TransactThread->TransactIoq); + for (;;) + { + NTSTATUS Result; + PIRP Irp; + + Result = KeWaitForMultipleObjects(2, WaitObjects, WaitAny, Executive, KernelMode, FALSE, 0, 0); + if (STATUS_WAIT_0 == Result) + break; /* stop thread */ + else if (STATUS_WAIT_1 != Result) + continue; /* retry */ + + Irp = FspIoqNextPendingIrp(&TransactThread->TransactIoq, 0); + if (0 == Irp) + continue; /* retry */ + } + + PsTerminateSystemThread(STATUS_SUCCESS); +} + +NTSTATUS FspTransactThreadStart(FSP_TRANSACT_THREAD *TransactThread, + FSP_IOQ *TransactIoq, FSP_IOQ *Ioq) +{ + PAGED_CODE(); + + NTSTATUS Result; + OBJECT_ATTRIBUTES ObjectAttributes; + HANDLE ThreadHandle; + + RtlZeroMemory(TransactThread, sizeof *TransactThread); + KeInitializeEvent(&TransactThread->Event, NotificationEvent, FALSE); + TransactThread->TransactIoq = TransactIoq; + TransactThread->Ioq = Ioq; + + InitializeObjectAttributes(&ObjectAttributes, 0, OBJ_KERNEL_HANDLE, 0, 0); + Result = PsCreateSystemThread(&ThreadHandle, THREAD_ALL_ACCESS, &ObjectAttributes, 0, 0, + FspTransactThread, TransactThread); + if (!NT_SUCCESS(Result)) + return Result; + + Result = ObReferenceObjectByHandle(ThreadHandle, THREAD_ALL_ACCESS, *PsThreadType, KernelMode, + &TransactThread->Thread, 0); + ASSERT(NT_SUCCESS(Result)); + + ZwClose(ThreadHandle); + + return STATUS_SUCCESS; +} + +VOID FspTransactThreadStop(FSP_TRANSACT_THREAD *TransactThread) +{ + PAGED_CODE(); + + KeSetEvent(&TransactThread->Event, 1, TRUE); + KeWaitForSingleObject(&TransactThread->Thread, Executive, KernelMode, FALSE, 0); +}