mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 09:03:25 +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
5 changed files with 51 additions and 230 deletions
|
@ -1,6 +1,6 @@
|
||||||
#ifndef _INCLUDE_DDK_IOFUNCS_H
|
#ifndef _INCLUDE_DDK_IOFUNCS_H
|
||||||
#define _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 --- */
|
/* --- EXPORTED BY NTOSKRNL --- */
|
||||||
|
|
||||||
|
@ -825,9 +825,6 @@ IoQueueThreadIrp (
|
||||||
IN PIRP Irp
|
IN PIRP Irp
|
||||||
);
|
);
|
||||||
|
|
||||||
typedef struct _IO_WORKITEM *PIO_WORKITEM;
|
|
||||||
typedef VOID (*PIO_WORKITEM_ROUTINE)(IN PDEVICE_OBJECT DeviceObject, IN PVOID Context);
|
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
IoQueueWorkItem(
|
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,
|
(*PIO_TIMER_ROUTINE)(PDEVICE_OBJECT DeviceObject,
|
||||||
PVOID Context);
|
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
|
#if WINDOWS_STRUCTS_DOESNT_ALREADY_DEFINE_THIS
|
||||||
typedef struct _PARTITION_INFORMATION
|
typedef struct _PARTITION_INFORMATION
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
* 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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -268,8 +268,6 @@ VOID
|
||||||
IoInitFileSystemImplementation(VOID);
|
IoInitFileSystemImplementation(VOID);
|
||||||
VOID
|
VOID
|
||||||
IoInitVpbImplementation(VOID);
|
IoInitVpbImplementation(VOID);
|
||||||
VOID
|
|
||||||
IoInitializeWorkerThreads(VOID);
|
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
IoMountVolume(IN PDEVICE_OBJECT DeviceObject,
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
|
@ -267,11 +267,6 @@ VOID IoInit (VOID)
|
||||||
* Initialize PnP manager
|
* Initialize PnP manager
|
||||||
*/
|
*/
|
||||||
PnpInit();
|
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
|
* COPYRIGHT: See COPYING in the top level directory
|
||||||
* PROJECT: ReactOS kernel
|
* PROJECT: ReactOS kernel
|
||||||
* FILE: reactos/ntoskrnk/io/iowork.c
|
* FILE: reactos/ntoskrnl/io/iowork.c
|
||||||
* PURPOSE: Manage IO system work queues
|
* PURPOSE: Manage IO system work queues
|
||||||
* PROGRAMMER: David Welch (welch@mcmail.com)
|
* PROGRAMMER: David Welch (welch@mcmail.com)
|
||||||
* Robert Dickenson (odin@pnc.com.au)
|
* Robert Dickenson (odin@pnc.com.au)
|
||||||
|
@ -18,246 +18,74 @@
|
||||||
#define NDEBUG
|
#define NDEBUG
|
||||||
#include <internal/debug.h>
|
#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)
|
/* GLOBALS ******************************************************************/
|
||||||
|
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
|
#define TAG_IOWI TAG('I', 'O', 'W', 'I')
|
||||||
|
|
||||||
/* FUNCTIONS ****************************************************************/
|
/* FUNCTIONS ****************************************************************/
|
||||||
|
|
||||||
static
|
VOID STDCALL STATIC
|
||||||
NTSTATUS
|
IoWorkItemCallback(PVOID Parameter)
|
||||||
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
|
|
||||||
*/
|
|
||||||
{
|
{
|
||||||
PWORK_QUEUE queue = (PWORK_QUEUE)context;
|
PIO_WORKITEM IoWorkItem = (PIO_WORKITEM)Parameter;
|
||||||
PIO_WORKITEM pWorkItem;
|
IoWorkItem->WorkerRoutine(IoWorkItem->DeviceObject, IoWorkItem->Context);
|
||||||
PLIST_ENTRY pListEntry;
|
ObDereferenceObject(IoWorkItem->DeviceObject);
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID STDCALL
|
||||||
IoInitializeWorkerThreads(VOID)
|
IoQueueWorkItem(IN PIO_WORKITEM IoWorkItem,
|
||||||
{
|
IN PIO_WORKITEM_ROUTINE WorkerRoutine,
|
||||||
IoInitializeWorkQueue(&IoNormalWorkQueue, LOW_PRIORITY);
|
IN WORK_QUEUE_TYPE QueueType,
|
||||||
IoInitializeWorkQueue(&IoCriticalWorkQueue, LOW_REALTIME_PRIORITY);
|
IN PVOID Context)
|
||||||
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)
|
|
||||||
/*
|
/*
|
||||||
* FUNCTION: Inserts a work item in a queue for one of the system worker
|
* FUNCTION: Inserts a work item in a queue for one of the system worker
|
||||||
* threads to process
|
* threads to process
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* pIoWorkItem = Item to insert
|
* IoWorkItem = Item to insert
|
||||||
* QueueType = Queue to insert it in
|
* QueueType = Queue to insert it in
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
DPRINT("IoQueueWorkItem(%p, %p, %p, %p)\n", pIoWorkItem, pWorkerRoutine, QueueType, pContext);
|
ExInitializeWorkItem(&IoWorkItem->Item, IoWorkItemCallback,
|
||||||
|
(PVOID)IoWorkItem);
|
||||||
assert(pIoWorkItem!=NULL);
|
IoWorkItem->WorkerRoutine = WorkerRoutine;
|
||||||
|
IoWorkItem->Context = Context;
|
||||||
if (!IoWorkQueueItemsListInitialised) {
|
ObReferenceObjectByPointer(IoWorkItem->DeviceObject,
|
||||||
IoWorkQueueItemsListInitialised = TRUE;
|
FILE_ALL_ACCESS,
|
||||||
InitializeListHead(&IoWorkQueueItemsListHead);
|
NULL,
|
||||||
KeInitializeSpinLock(&IoWorkQueueItemsListLock);
|
KernelMode);
|
||||||
}
|
ExQueueWorkItem(&IoWorkItem->Item, QueueType);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
VOID STDCALL
|
VOID STDCALL
|
||||||
IoFreeWorkItem(PIO_WORKITEM pIoWorkItem)
|
IoFreeWorkItem(PIO_WORKITEM IoWorkItem)
|
||||||
{
|
{
|
||||||
if (pIoWorkItem != NULL) {
|
ExFreePool(IoWorkItem);
|
||||||
ExFreePool(pIoWorkItem);
|
|
||||||
} else {
|
|
||||||
DPRINT("IoFreeWorkItem() passed NULL pointer ???\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTES:
|
|
||||||
Callers of IoAllocateWorkItem must be running at IRQL <= DISPATCH_LEVEL
|
|
||||||
*/
|
|
||||||
PIO_WORKITEM STDCALL
|
PIO_WORKITEM STDCALL
|
||||||
IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
|
IoAllocateWorkItem(PDEVICE_OBJECT DeviceObject)
|
||||||
{
|
{
|
||||||
PIO_WORKITEM pIoWorkItem = NULL;
|
PIO_WORKITEM IoWorkItem = NULL;
|
||||||
|
|
||||||
assert(DeviceObject!=NULL);
|
IoWorkItem =
|
||||||
//ASSERT_IRQL(DISPATCH_LEVEL);
|
ExAllocatePoolWithTag(NonPagedPool, sizeof(IO_WORKITEM), TAG_IOWI);
|
||||||
|
if (IoWorkItem == NULL)
|
||||||
pIoWorkItem = ExAllocatePoolWithTag(NonPagedPool, sizeof(struct _IO_WORKITEM), TAG_IOWI);
|
{
|
||||||
if (pIoWorkItem != NULL) {
|
return(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));
|
|
||||||
}
|
}
|
||||||
return pIoWorkItem;
|
RtlZeroMemory(IoWorkItem, sizeof(IO_WORKITEM));
|
||||||
|
IoWorkItem->DeviceObject = DeviceObject;
|
||||||
|
return(IoWorkItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue