mirror of
https://github.com/reactos/reactos.git
synced 2024-08-27 13:48:42 +00:00
Implemented IO work queue functions using the system work queues.
svn path=/trunk/; revision=3625
This commit is contained in:
parent
34f0970179
commit
a686f1e6f4
|
@ -1,6 +1,6 @@
|
|||
#ifndef _INCLUDE_DDK_IOFUNCS_H
|
||||
#define _INCLUDE_DDK_IOFUNCS_H
|
||||
/* $Id: iofuncs.h,v 1.34 2002/10/03 19:26:46 robd Exp $ */
|
||||
/* $Id: iofuncs.h,v 1.35 2002/10/05 10:53:36 dwelch Exp $ */
|
||||
|
||||
/* --- EXPORTED BY NTOSKRNL --- */
|
||||
|
||||
|
@ -825,9 +825,6 @@ IoQueueThreadIrp (
|
|||
IN PIRP Irp
|
||||
);
|
||||
|
||||
typedef struct _IO_WORKITEM *PIO_WORKITEM;
|
||||
typedef VOID (*PIO_WORKITEM_ROUTINE)(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
||||
|
||||
VOID
|
||||
STDCALL
|
||||
IoQueueWorkItem(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: iotypes.h,v 1.42 2002/10/03 19:26:47 robd Exp $
|
||||
/* $Id: iotypes.h,v 1.43 2002/10/05 10:53:36 dwelch Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -815,6 +815,9 @@ typedef VOID STDCALL
|
|||
(*PIO_TIMER_ROUTINE)(PDEVICE_OBJECT DeviceObject,
|
||||
PVOID Context);
|
||||
|
||||
typedef struct _IO_WORKITEM *PIO_WORKITEM;
|
||||
typedef VOID (*PIO_WORKITEM_ROUTINE)(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
||||
|
||||
#if WINDOWS_STRUCTS_DOESNT_ALREADY_DEFINE_THIS
|
||||
typedef struct _PARTITION_INFORMATION
|
||||
{
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
/* $Id: io.h,v 1.26 2002/10/03 19:24:24 robd Exp $
|
||||
/* $Id: io.h,v 1.27 2002/10/05 10:53:37 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -268,8 +268,6 @@ VOID
|
|||
IoInitFileSystemImplementation(VOID);
|
||||
VOID
|
||||
IoInitVpbImplementation(VOID);
|
||||
VOID
|
||||
IoInitializeWorkerThreads(VOID);
|
||||
|
||||
NTSTATUS
|
||||
IoMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $Id: iomgr.c,v 1.28 2002/10/03 19:34:50 robd Exp $
|
||||
/* $Id: iomgr.c,v 1.29 2002/10/05 10:53:37 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
|
@ -267,11 +267,6 @@ VOID IoInit (VOID)
|
|||
* Initialize PnP manager
|
||||
*/
|
||||
PnpInit();
|
||||
|
||||
/*
|
||||
* Start the Io worker threads
|
||||
*/
|
||||
IoInitializeWorkerThreads();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
/* $Id: iowork.c,v 1.1 2002/10/03 19:17:26 robd Exp $
|
||||
/* $Id: iowork.c,v 1.2 2002/10/05 10:53:37 dwelch Exp $
|
||||
*
|
||||
* COPYRIGHT: See COPYING in the top level directory
|
||||
* PROJECT: ReactOS kernel
|
||||
* FILE: reactos/ntoskrnk/io/iowork.c
|
||||
* FILE: reactos/ntoskrnl/io/iowork.c
|
||||
* PURPOSE: Manage IO system work queues
|
||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||
* Robert Dickenson (odin@pnc.com.au)
|
||||
|
@ -18,246 +18,74 @@
|
|||
#define NDEBUG
|
||||
#include <internal/debug.h>
|
||||
|
||||
/* TYPES ********************************************************************/
|
||||
|
||||
/* DEFINES *******************************************************************/
|
||||
typedef struct _IO_WORKITEM
|
||||
{
|
||||
WORK_QUEUE_ITEM Item;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PIO_WORKITEM_ROUTINE WorkerRoutine;
|
||||
PVOID Context;
|
||||
} IO_WORKITEM;
|
||||
|
||||
#define NUMBER_OF_WORKER_THREADS (5)
|
||||
|
||||
|
||||
/* TYPES *********************************************************************/
|
||||
|
||||
typedef struct _WORK_QUEUE {
|
||||
LIST_ENTRY Head; // Head of the list of waiting work items
|
||||
KSPIN_LOCK Lock; // Sychronize access to the work queue
|
||||
KSEMAPHORE Sem; // Worker threads with nothing to do wait on this event
|
||||
HANDLE Thread[NUMBER_OF_WORKER_THREADS]; // Thread associated with work queue
|
||||
} WORK_QUEUE, *PWORK_QUEUE;
|
||||
|
||||
|
||||
struct _IO_WORKITEM {
|
||||
LIST_ENTRY IoWorkItemsList;
|
||||
PDEVICE_OBJECT DeviceObject;
|
||||
PDRIVER_OBJECT DriverObject;
|
||||
int size;
|
||||
PIO_WORKITEM_ROUTINE WorkerRoutine;
|
||||
WORK_QUEUE_TYPE QueueType;
|
||||
PVOID Context;
|
||||
int reserved[50];
|
||||
};
|
||||
|
||||
//typedef VOID (*PIO_WORKITEM_ROUTINE)(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
||||
|
||||
|
||||
/* GLOBALS *******************************************************************/
|
||||
|
||||
#define TAG_IOWI TAG('I', 'O', 'W', 'I')
|
||||
|
||||
// Queue of items waiting to be processed at normal priority
|
||||
WORK_QUEUE IoNormalWorkQueue;
|
||||
WORK_QUEUE IoCriticalWorkQueue;
|
||||
WORK_QUEUE IoHyperCriticalWorkQueue;
|
||||
|
||||
|
||||
/* LOCALS *******************************************************************/
|
||||
|
||||
static BOOL IoWorkQueueItemsListInitialised = FALSE;
|
||||
static LIST_ENTRY IoWorkQueueItemsListHead;
|
||||
static KSPIN_LOCK IoWorkQueueItemsListLock;
|
||||
/* GLOBALS ******************************************************************/
|
||||
|
||||
#define TAG_IOWI TAG('I', 'O', 'W', 'I')
|
||||
|
||||
/* FUNCTIONS ****************************************************************/
|
||||
|
||||
static
|
||||
NTSTATUS
|
||||
STDCALL
|
||||
IoWorkerThreadEntryPoint(PVOID context)
|
||||
/*
|
||||
* FUNCTION: Entry point for a worker thread
|
||||
* ARGUMENTS:
|
||||
* context = Parameters
|
||||
* RETURNS: Status
|
||||
* NOTE: To kill a worker thread you must queue an item whose callback
|
||||
* calls PsTerminateSystemThread
|
||||
*/
|
||||
VOID STDCALL STATIC
|
||||
IoWorkItemCallback(PVOID Parameter)
|
||||
{
|
||||
PWORK_QUEUE queue = (PWORK_QUEUE)context;
|
||||
PIO_WORKITEM pWorkItem;
|
||||
PLIST_ENTRY pListEntry;
|
||||
|
||||
for (;;) {
|
||||
pListEntry = ExInterlockedRemoveHeadList(&queue->Head, &queue->Lock);
|
||||
if (pListEntry != NULL) {
|
||||
pWorkItem = CONTAINING_RECORD(pListEntry, struct _IO_WORKITEM, IoWorkItemsList);
|
||||
(pWorkItem->WorkerRoutine)(pWorkItem->DeviceObject, pWorkItem->Context);
|
||||
} else {
|
||||
KeWaitForSingleObject((PVOID)&queue->Sem,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL);
|
||||
DPRINT("Woke from wait\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
|
||||
VOID
|
||||
Scan_IoQueueWorkItems(PDEVICE_OBJECT DeviceObject, WORK_QUEUE_TYPE QueueType)
|
||||
{
|
||||
PIO_WORKITEM pWorkItem;
|
||||
PLIST_ENTRY pListEntry;
|
||||
KIRQL oldlvl;
|
||||
|
||||
pListEntry = IoWorkQueueItemsListHead.Flink;
|
||||
while (pListEntry != &IoWorkQueueItemsListHead) {
|
||||
pWorkItem = CONTAINING_RECORD(pListEntry, struct _IO_WORKITEM, IoWorkItemsList);
|
||||
if (pWorkItem->QueueType == QueueType) {
|
||||
KeAcquireSpinLock(&IoWorkQueueItemsListLock,&oldlvl);
|
||||
RemoveEntryList(pListEntry);
|
||||
KeReleaseSpinLock(&IoWorkQueueItemsListLock,oldlvl);
|
||||
pListEntry = pListEntry->Flink;
|
||||
(pWorkItem->WorkerRoutine)(pWorkItem->DeviceObject, pWorkItem->Context);
|
||||
} else {
|
||||
pListEntry = pListEntry->Flink;
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
static
|
||||
VOID
|
||||
IoInitializeWorkQueue(PWORK_QUEUE WorkQueue, KPRIORITY Priority)
|
||||
{
|
||||
ULONG i;
|
||||
PETHREAD Thread;
|
||||
|
||||
InitializeListHead(&WorkQueue->Head);
|
||||
KeInitializeSpinLock(&WorkQueue->Lock);
|
||||
KeInitializeSemaphore(&WorkQueue->Sem, 0, 256);
|
||||
|
||||
for (i = 0; i < NUMBER_OF_WORKER_THREADS; i++) {
|
||||
PsCreateSystemThread(&WorkQueue->Thread[i],
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
IoWorkerThreadEntryPoint,
|
||||
WorkQueue);
|
||||
ObReferenceObjectByHandle(WorkQueue->Thread[i],
|
||||
THREAD_ALL_ACCESS,
|
||||
PsThreadType,
|
||||
KernelMode,
|
||||
(PVOID*)&Thread,
|
||||
NULL);
|
||||
KeSetPriorityThread(&Thread->Tcb, Priority);
|
||||
ObDereferenceObject(Thread);
|
||||
}
|
||||
PIO_WORKITEM IoWorkItem = (PIO_WORKITEM)Parameter;
|
||||
IoWorkItem->WorkerRoutine(IoWorkItem->DeviceObject, IoWorkItem->Context);
|
||||
ObDereferenceObject(IoWorkItem->DeviceObject);
|
||||
}
|
||||
|
||||
VOID
|
||||
IoInitializeWorkerThreads(VOID)
|
||||
{
|
||||
IoInitializeWorkQueue(&IoNormalWorkQueue, LOW_PRIORITY);
|
||||
IoInitializeWorkQueue(&IoCriticalWorkQueue, LOW_REALTIME_PRIORITY);
|
||||
IoInitializeWorkQueue(&IoHyperCriticalWorkQueue, HIGH_PRIORITY);
|
||||
}
|
||||
|
||||
/* NOTES:
|
||||
IoQueueWorkItem inserts the specified work item into a queue from which a
|
||||
system worker thread removes the item and gives control to the specified
|
||||
callback routine.
|
||||
Highest-level drivers can call IoQueueWorkItem.
|
||||
Callers of IoQueueWorkItem must be running at IRQL <= DISPATCH_LEVEL.
|
||||
The callback is run within a system thread context at IRQL PASSIVE_LEVEL.
|
||||
This caller-supplied routine is responsible for calling IoFreeWorkItem to
|
||||
reclaim the storage allocated for the work item.
|
||||
IoQueueWorkItem should be used instead of ExQueueWorkItem because
|
||||
IoQueueWorkItem will ensure that the device object associated with the
|
||||
specified work item is available for the processing of the work item.
|
||||
*/
|
||||
VOID
|
||||
STDCALL
|
||||
IoQueueWorkItem(IN PIO_WORKITEM pIoWorkItem, IN PIO_WORKITEM_ROUTINE pWorkerRoutine,
|
||||
IN WORK_QUEUE_TYPE QueueType, IN PVOID pContext)
|
||||
VOID STDCALL
|
||||
IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem,
|
||||
IN PIO_WORKITEM_ROUTINE WorkerRoutine,
|
||||
IN WORK_QUEUE_TYPE QueueType,
|
||||
IN PVOID Context)
|
||||
/*
|
||||
* FUNCTION: Inserts a work item in a queue for one of the system worker
|
||||
* threads to process
|
||||
* ARGUMENTS:
|
||||
* pIoWorkItem = Item to insert
|
||||
* IoWorkItem = Item to insert
|
||||
* QueueType = Queue to insert it in
|
||||
*/
|
||||
{
|
||||
DPRINT("IoQueueWorkItem(%p, %p, %p, %p)\n", pIoWorkItem, pWorkerRoutine, QueueType, pContext);
|
||||
|
||||
assert(pIoWorkItem!=NULL);
|
||||
|
||||
if (!IoWorkQueueItemsListInitialised) {
|
||||
IoWorkQueueItemsListInitialised = TRUE;
|
||||
InitializeListHead(&IoWorkQueueItemsListHead);
|
||||
KeInitializeSpinLock(&IoWorkQueueItemsListLock);
|
||||
}
|
||||
pIoWorkItem->WorkerRoutine = pWorkerRoutine;
|
||||
pIoWorkItem->QueueType = QueueType;
|
||||
pIoWorkItem->Context = pContext;
|
||||
//ExInterlockedInsertHeadList(&IoWorkQueueItemsListHead, &pIoWorkItem->IoWorkItemsList, &IoWorkQueueItemsListLock);
|
||||
|
||||
switch(QueueType) {
|
||||
case DelayedWorkQueue:
|
||||
ExInterlockedInsertTailList(&IoNormalWorkQueue.Head,
|
||||
&pIoWorkItem->IoWorkItemsList,
|
||||
&IoNormalWorkQueue.Lock);
|
||||
KeReleaseSemaphore(&IoNormalWorkQueue.Sem,
|
||||
IO_NO_INCREMENT, 1, FALSE);
|
||||
break;
|
||||
case CriticalWorkQueue:
|
||||
ExInterlockedInsertTailList(&IoCriticalWorkQueue.Head,
|
||||
&pIoWorkItem->IoWorkItemsList,
|
||||
&IoCriticalWorkQueue.Lock);
|
||||
KeReleaseSemaphore(&IoCriticalWorkQueue.Sem,
|
||||
IO_NO_INCREMENT, 1, FALSE);
|
||||
break;
|
||||
case HyperCriticalWorkQueue:
|
||||
ExInterlockedInsertTailList(&IoHyperCriticalWorkQueue.Head,
|
||||
&pIoWorkItem->IoWorkItemsList,
|
||||
&IoHyperCriticalWorkQueue.Lock);
|
||||
KeReleaseSemaphore(&IoHyperCriticalWorkQueue.Sem,
|
||||
IO_NO_INCREMENT, 1, FALSE);
|
||||
break;
|
||||
}
|
||||
ExInitializeWorkItem(&IoWorkItem->Item, IoWorkItemCallback,
|
||||
(PVOID)IoWorkItem);
|
||||
IoWorkItem->WorkerRoutine = WorkerRoutine;
|
||||
IoWorkItem->Context = Context;
|
||||
ObReferenceObjectByPointer(IoWorkItem->DeviceObject,
|
||||
FILE_ALL_ACCESS,
|
||||
NULL,
|
||||
KernelMode);
|
||||
ExQueueWorkItem(&IoWorkItem->Item, QueueType);
|
||||
}
|
||||
|
||||
/*
|
||||
*/
|
||||
VOID STDCALL
|
||||
IoFreeWorkItem(PIO_WORKITEM pIoWorkItem)
|
||||
IoFreeWorkItem(PIO_WORKITEM IoWorkItem)
|
||||
{
|
||||
if (pIoWorkItem != NULL) {
|
||||
ExFreePool(pIoWorkItem);
|
||||
} else {
|
||||
DPRINT("IoFreeWorkItem() passed NULL pointer ???\n");
|
||||
}
|
||||
ExFreePool(IoWorkItem);
|
||||
}
|
||||
|
||||
/* NOTES:
|
||||
Callers of IoAllocateWorkItem must be running at IRQL <= DISPATCH_LEVEL
|
||||
*/
|
||||
PIO_WORKITEM STDCALL
|
||||
IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
|
||||
{
|
||||
PIO_WORKITEM pIoWorkItem = NULL;
|
||||
|
||||
assert(DeviceObject!=NULL);
|
||||
//ASSERT_IRQL(DISPATCH_LEVEL);
|
||||
|
||||
pIoWorkItem = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _IO_WORKITEM), TAG_IOWI);
|
||||
if (pIoWorkItem != NULL) {
|
||||
RtlZeroMemory(pIoWorkItem, sizeof(struct _IO_WORKITEM));
|
||||
pIoWorkItem->size = sizeof(struct _IO_WORKITEM);
|
||||
pIoWorkItem->DeviceObject = DeviceObject;
|
||||
} else {
|
||||
DPRINT("IoAllocateWorkItem() FAILED to allocated %d bytes memory\n", sizeof(struct _IO_WORKITEM));
|
||||
PIO_WORKITEM IoWorkItem = NULL;
|
||||
|
||||
IoWorkItem =
|
||||
ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_WORKITEM), TAG_IOWI);
|
||||
if (IoWorkItem == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
return pIoWorkItem;
|
||||
RtlZeroMemory(IoWorkItem, sizeof(IO_WORKITEM));
|
||||
IoWorkItem->DeviceObject = DeviceObject;
|
||||
return(IoWorkItem);
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
Loading…
Reference in a new issue