[ofw] [RFC] [PATCH 1/2 v3] work_queue: abstraction to manage small pool of work items
Smith, Stan
stan.smith at intel.com
Tue May 26 17:19:37 PDT 2009
> Abstraction was re-added. The WORK_ENTRY was redefined to allow
> overlaying it on top of the IRP.Tail.Overlay.DriverContext. This
> makes it trivial to queue an IRP for asynchronous processing.
Isn't this a wee bit dangerous w.r.t. to a future time bomb to use IRP.Tail.Overlay.DriverContext?
Did you not state that MS has claimed the field IRP.Tail.Overlay.DriverContext for future use; although it's not used today?
What did I miss?
>
> Code is inserted inline, since it is all new.
>
>
> /*
> * Copyright (c) 2009 Intel Corporation. All rights reserved.
> *
> * This software is available to you under the OpenIB.org BSD license
> * below:
> *
> * Redistribution and use in source and binary forms, with or
> * without modification, are permitted provided that the following
> * conditions are met:
> *
> * - Redistributions of source code must retain the above
> * copyright notice, this list of conditions and the following
> * disclaimer.
> *
> * - Redistributions in binary form must reproduce the above
> * copyright notice, this list of conditions and the following
> * disclaimer in the documentation and/or other materials
> * provided with the distribution.
> *
> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
> * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> * SOFTWARE.
> */
>
> #pragma once
>
> #ifndef _WORK_QUEUE_H_
> #define _WORK_QUEUE_H_
>
> #include <ntddk.h>
>
> // Allow overlaying across IRP.Tail.Overlay.DriverContext
> typedef struct _WORK_ENTRY
> {
> LIST_ENTRY Entry;
> void (*WorkHandler)(struct _WORK_ENTRY *Work);
> void *Context;
>
> } WORK_ENTRY;
>
> static void WorkEntryInit(WORK_ENTRY *pWork,
> void (*WorkHandler)(struct _WORK_ENTRY *Work), void *Context)
> {
> pWork->WorkHandler = WorkHandler;
> pWork->Context = Context;
> }
>
> #define WorkEntryFromIrp(pIrp) ((WORK_ENTRY *)
> (pIrp)->Tail.Overlay.DriverContext)
>
> struct _WORK_QUEUE_TASK;
>
> typedef struct _WORK_QUEUE
> {
> LIST_ENTRY List;
> KSPIN_LOCK Lock;
> int TaskCount;
> struct _WORK_QUEUE_TASK *TaskArray; // TaskArray[0] is for internal
> use
>
> } WORK_QUEUE;
>
> NTSTATUS WorkQueueInit(WORK_QUEUE *pWorkQueue, PDEVICE_OBJECT Device,
> int TaskCount);
> void WorkQueueDestroy(WORK_QUEUE *pWorkQueue);
> void WorkQueueInsert(WORK_QUEUE *pWorkQueue, WORK_ENTRY *pWork);
>
> #endif // _WORK_QUEUE_H_
>
>
> /*
> * Copyright (c) 2009 Intel Corporation. All rights reserved.
> *
> * This software is available to you under the OpenIB.org BSD license
> * below:
> *
> * Redistribution and use in source and binary forms, with or
> * without modification, are permitted provided that the following
> * conditions are met:
> *
> * - Redistributions of source code must retain the above
> * copyright notice, this list of conditions and the following
> * disclaimer.
> *
> * - Redistributions in binary form must reproduce the above
> * copyright notice, this list of conditions and the following
> * disclaimer in the documentation and/or other materials
> * provided with the distribution.
> *
> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AWV
> * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
> * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
> * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
> * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
> * SOFTWARE.
> */
>
> #include <ntddk.h>
> #include "work_queue.h"
>
>
> typedef struct _WORK_QUEUE_TASK
> {
> WORK_QUEUE *pWorkQueue;
> PIO_WORKITEM pWorkItem;
> int Next;
> int Index;
>
> } WORK_QUEUE_TASK;
>
>
> #if (WINVER < _WIN32_WINNT_WIN6)
> #define KeQueryActiveProcessorCount(x) KeNumberProcessors
> #endif
>
>
> NTSTATUS WorkQueueInit(WORK_QUEUE *pWorkQueue, PDEVICE_OBJECT Device,
> int TaskCount) {
> WORK_QUEUE_TASK *task;
> KAFFINITY procs;
> int i;
>
> if (TaskCount == 0) {
> TaskCount = KeQueryActiveProcessorCount(&procs);
> }
>
> KeInitializeSpinLock(&pWorkQueue->Lock);
> InitializeListHead(&pWorkQueue->List);
> pWorkQueue->TaskCount = TaskCount;
> pWorkQueue->TaskArray = ExAllocatePoolWithTag(NonPagedPool,
> sizeof(WORK_QUEUE_TASK) * (TaskCount + 1),
> 'ktqw');
> if (pWorkQueue->TaskArray == NULL) {
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> for (i = 0; i <= TaskCount; i++) {
> task = &pWorkQueue->TaskArray[i];
> task->pWorkQueue = pWorkQueue;
> task->Index = i;
> task->Next = i + 1;
> if (i > 0) {
> task->pWorkItem = IoAllocateWorkItem(Device);
> if (task->pWorkItem == NULL) {
> goto err;
> }
> }
> }
> task->Next = 0;
> return STATUS_SUCCESS;
>
> err:
> while (--i > 0) {
> IoFreeWorkItem(pWorkQueue->TaskArray[i].pWorkItem);
> }
> ExFreePool(pWorkQueue->TaskArray);
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> void WorkQueueDestroy(WORK_QUEUE *pWorkQueue)
> {
> while (pWorkQueue->TaskCount > 0) {
> IoFreeWorkItem(pWorkQueue->TaskArray[pWorkQueue->TaskCount--].pWorkItem);
> }
> ExFreePool(pWorkQueue->TaskArray);
> }
>
> 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);
>
> if (!IsListEmpty(&wq->List)) {
> entry = RemoveHeadList(&wq->List);
> KeReleaseInStackQueuedSpinLock(&lockqueue);
>
> work = CONTAINING_RECORD(entry, WORK_ENTRY, Entry);
> work->WorkHandler(work);
>
> KeAcquireInStackQueuedSpinLock(&wq->Lock, &lockqueue);
> if (!IsListEmpty(&wq->List)) {
> KeReleaseInStackQueuedSpinLock(&lockqueue);
> IoQueueWorkItem(task->pWorkItem, WorkQueueHandler,
> DelayedWorkQueue, task); return;
> }
> }
>
> task->Next = wq->TaskArray[0].Next;
> wq->TaskArray[0].Next = task->Index;
> KeReleaseInStackQueuedSpinLock(&lockqueue);
> }
>
> void WorkQueueInsert(WORK_QUEUE *pWorkQueue, WORK_ENTRY *pWork)
> {
> WORK_QUEUE_TASK *task;
> KLOCK_QUEUE_HANDLE lockqueue;
>
> KeAcquireInStackQueuedSpinLock(&pWorkQueue->Lock, &lockqueue);
> InsertHeadList(&pWorkQueue->List, &pWork->Entry);
> task = &pWorkQueue->TaskArray[pWorkQueue->TaskArray[0].Next];
> pWorkQueue->TaskArray[0].Next = task->Next;
> KeReleaseInStackQueuedSpinLock(&lockqueue);
>
> if (task->Index != 0) {
> IoQueueWorkItem(task->pWorkItem, WorkQueueHandler,
> DelayedWorkQueue, task); }
> }
>
> _______________________________________________
> ofw mailing list
> ofw at lists.openfabrics.org
> http://lists.openfabrics.org/cgi-bin/mailman/listinfo/ofw
More information about the ofw
mailing list