I use the following code to create a system thread to process items that I
have queued myself. The problem is that the system grinds to a halt when
this thread is running (Windows XP). The mouse cursor does not even move
across the screen! The thread itself seems to be running just fine. I
never get any debug messages about the exception (of course if might not be
able to flush that data out!) This is my first attempt at system threads
and I can’t seem to figure out just what I am doing wrong.
I don’t use the built in work items because this driver must run on NT4
through XP. The implementation changed completely between NT4 and Windows
2000, so I decided to roll my own work item queuing.
Thanks in advance,
Jon
typedef struct _WORKER_THREAD_CONTEXT
{
PKQUEUE WorkQueue; // The queue from which the
// worker thread pulls items.
PKEVENT ShutdownEvent; // Event that when signaled indicates
// that the thread should terminate.
} WORKER_THREAD_CONTEXT, *PWORKER_THREAD_CONTEXT;
typedef struct _MY_DEVICE_EXTENSION
{
// … other members…
PETHREAD WorkerThreadObject;
KQUEUE WorkerQueue;
KEVENT ShutdownEvent;
// … other members…
} MY_DEVICE_EXTENSION, *PMY_DEVICE_EXTENSION;
{
// code from DriverEntry…
//
// This event is used to tell any threads that
// we create that it is time to shutdown.
//
KeInitializeEvent(&devExt->ShutdownEvent,
NotificationEvent,
FALSE);
workerContext = ExAllocatePoolWithTag(NonPagedPool,
sizeof(WORKER_THREAD_CONTEXT),
MY_TAG);
if (NULL != workerContext)
{
workerContext->ShutdownEvent = &devExt->ShutdownEvent;
workerContext->WorkQueue = &devExt->WorkQueue;
status = PsCreateSystemThread(&hThread,
(ACCESS_MASK)0L,
NULL,
0,
NULL,
WorkerThread,
workerContext);
ObReferenceObjectByHandle(hThread,
THREAD_ALL_ACCESS,
NULL,
KernelMode,
&devExt->WorkerThreadObject,
NULL);
ZwClose(hThread);
}
} // code from DriverEntry…
VOID WorkerThread(IN PVOID Context)
{
NTSTATUS status;
WORKER_THREAD_CONTEXT context;
LARGE_INTEGER waitPeriod;
PLIST_ENTRY NodePtr = NULL;
ASSERT(NULL != Context);
context.ShutdownEvent = ((PWORKER_THREAD_CONTEXT)Context)->ShutdownEvent;
context.WorkQueue = ((PWORKER_THREAD_CONTEXT)Context)->WorkQueue;
ExFreePool(Context);
KeSetPriorityThread(KeGetCurrentThread(),
LOW_REALTIME_PRIORITY);
while (TRUE)
{
//
// Test the shutdown event.
//
waitPeriod.QuadPart = 0;
status = KeWaitForSingleObject(context.ShutdownEvent,
Executive,
KernelMode,
FALSE,
&waitPeriod);
if (STATUS_SUCCESS == status)
{
//
// The shutdown event has bee signaled.
//
break;
}
__try
{
waitPeriod.QuadPart = 50000; // =~ 5 milliSeconds
//
// Dequeue an item and process it.
//
NodePtr = KeRemoveQueue(context.WorkQueue,
KernelMode,
&waitPeriod);
if (STATUS_TIMEOUT != (NTSTATUS)NodePtr &&
STATUS_USER_APC != (NTSTATUS)NodePtr)
{
//
// Process the request.
//
_QueueFunc funcPtr = FUNC_PTR_FROM_NODE(NodePtr);
funcPtr(NodePtr);
}
else
{
KeDelayExecutionThread(KernelMode,
FALSE,
&waitPeriod);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint((“\n\t!!! Exception in worker thread, 0x%08X\n”,
GetExceptionCode()));
}
}
PsTerminateSystemThread(status);
} // WorkerThread()