[ofw] [RFC] [PATCH 1/2] work_queue: new abstraction for queuing work

Fab Tillier ftillier at windows.microsoft.com
Thu May 21 09:15:55 PDT 2009


> The work queue maintains a small pool of IO_WORKITEMs that it uses
> to process a list of queued work entries.  This allows
> objects to be created with embedded work entry objects.  (IO_WORKITEMs
> cannot be embedded in structures pre-Vista.)

While IO_WORKITEMs can't be embedded in structures pre-Vista, you can allocate a work item and store the pointer to it pre-Vista.

> The work queue also alleviates the queuing of a large number of
> associated work requests from consuming all available system threads.
> A future enhancement would be to limit how long the work callback
> handler
> can run before the work item is requeued.  Work entries are protected
> against being queued multiple times.
> 
> Signed-off-by: Sean Hefty <sean.hefty at intel.com>
> ---
> I'm sure that I read in the WDK documentation that it recommended
> that drivers use a pool of reusable IO_WORKITEMs to process a list
> of pending requests if it created more than one every minute, but
> I can't find that reference now.  That's what sent me down this path
> to begin with.

Just store the work items (by reference) in the objects that need them.

> static VOID WorkQueueHandler(PDEVICE_OBJECT pDevice, void *Context)
> {
> 	WORK_QUEUE *wq;
> 	WORK_QUEUE_TASK *task = (WORK_QUEUE_TASK *) Context;
> 	WORK_ENTRY *work;
> 	LIST_ENTRY *entry;
> 	KLOCK_QUEUE_HANDLE lockqueue;
> 	UNREFERENCED_PARAMETER(pDevice);
> 
> 	wq = task->pWorkQueue;
> 	KeAcquireInStackQueuedSpinLock(&wq->Lock, &lockqueue);
> 	while (!IsListEmpty(&wq->List)) {
> 		entry = RemoveHeadList(&wq->List);
> 		KeReleaseInStackQueuedSpinLock(&lockqueue);
> 
> 		work = CONTAINING_RECORD(entry, WORK_ENTRY, Entry);
> 		InterlockedExchange(&work->Queued, 0);
> 		work->WorkHandler(work);
> 		KeAcquireInStackQueuedSpinLock(&wq->Lock, &lockqueue);
> 	}

The IO_WORKITEM documentation warns against infinite loops in a work item handler.  See the section "System Worker Threads" in the WDK docs, the last paragraph: "If one of these routines runs for too long (if it contains an indefinite loop, for example), the system can deadlock."

Just allocate work items, and queue those.  So all you're doing is providing potential serialization of callbacks, and potentially deadlocking the system.



More information about the ofw mailing list