I posted the same question a week ago but used a “wrong” sample (DiskFile). Here is my second attempt using the RamDisk Sample. The worker thread code is based on the code in the “input\vserial” sample.
In EvtDeviceAdd:
- Create a manual Queue.
- Init a semaphore.
- Create worker thread.
In EvtIoWrite:
- Forward the Request to the manual Queue.
- Release the semaphore.
In the Thread Routine:
- Wait on the semaphore.
- Retrieve a Request from the manual Queue, process, and complete.
The code seems to work fine. But if EvtDeviceAdd fails to complete for some reasons (for example, couldn’t alloc memory for the RamDisk), the system crashes.
Below is some trace data:
*********************************************
* Windows Ramdisk Driver - Driver Framework Edition.
*********************************************
Built Nov 19 2008 11:59:29
***TEST*** RamDisk Enter DeviceAdd
DiskSize = 0x12800000 (to force a failed alloc)
RootDirEntries = 0x200
SectorsPerCluster = 0x2
DriveLetter = R:
***TEST*** RamDisk Exit DeviceAdd. Failed NonPagePool alloc: 0x00000000
***TEST*** RamDisk Enter ContextCleanup
(Released semaphore here. Thread Routine should wake up and terminate itself. But it didn’t)
***TEST*** RamDisk Dereference thread obj
***TEST*** RamDisk Exit ContextCleanup
*** Fatal System Error: 0x000000ce
(0xF44BD0D0,0x00000000,0xF44BD0D0,0x00000000)
…
kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_UNLOADED_WITHOUT_CANCELLING_PENDING_OPERATIONS (ce)
…
My questions are:
- Is this an acceptable way to do worker thread in DMDF?
- Why ContextCleanup called if the driver has not been loaded?
- Why the Context Cleanup code doesn’t terminate the thread? Below is the subroutine:
VOID RamDiskEvtDeviceContextCleanup(IN WDFDEVICE Device)
{
PDEVICE_EXTENSION pDeviceExtension = DeviceGetExtension(Device);
PAGED_CODE();
KdPrint((__DRIVER_NAME " Enter ContextCleanup\n"));
// Set flag to terminate thread
pDeviceExtension->bTerminateThread = TRUE;
// Make sure the thread wakes up
KeReleaseSemaphore(&pDeviceExtension->IrpQueueSem,
0, // No priority boost
1, // Increment semaphore by 1
TRUE); // WaitForXxx after this call
// Wait for the thread to terminate
KeWaitForSingleObject(&pDeviceExtension->pThreadObj,
Executive,
KernelMode,
FALSE,
NULL);
KdPrint((__DRIVER_NAME " Dereference thread obj\n"));
ObDereferenceObject(&pDeviceExtension->pThreadObj);
if(pDeviceExtension->DiskImage)
{
ExFreePool(pDeviceExtension->DiskImage);
}
KdPrint((__DRIVER_NAME " Exit ContextCleanup\n"));
}
And thread subroutine:
VOID WorkerThreadRoutine(IN PVOID pContext)
{
// Vars declarations.
…
KdPrint((__DRIVER_NAME " Thread in\n"));
// Sets thread priority
KeSetPriorityThread(KeGetCurrentThread(), LOW_REALTIME_PRIORITY);
while(TRUE)
{
// Wake up when there are Requests in the Queue or when thread should be terminated
KeWaitForSingleObject(&pDevExt->IrpQueueSem, Executive, KernelMode, FALSE, NULL);
// Check termination flag
if(pDevExt->bTerminateThread)
{
PsTerminateSystemThread(STATUS_SUCCESS);
KdPrint((__DRIVER_NAME " Thread terminated\n"));
return;
}
// Retrieve a Request from the manual queue and process
…
}
KdPrint((__DRIVER_NAME " Thread out (never get here)\n"));
return;
}
Thank you for your help.
Chu Bun