diff --git a/reactos/include/ddk/iofuncs.h b/reactos/include/ddk/iofuncs.h index d3dd51e5731..9ebf817ed7d 100644 --- a/reactos/include/ddk/iofuncs.h +++ b/reactos/include/ddk/iofuncs.h @@ -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( diff --git a/reactos/include/ddk/iotypes.h b/reactos/include/ddk/iotypes.h index 0449fa3c18a..5cff95c9796 100644 --- a/reactos/include/ddk/iotypes.h +++ b/reactos/include/ddk/iotypes.h @@ -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 { diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index e4d62d1bd3b..f1d773d18db 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -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, diff --git a/reactos/ntoskrnl/io/iomgr.c b/reactos/ntoskrnl/io/iomgr.c index c6f8638cdad..2b8c90a2875 100644 --- a/reactos/ntoskrnl/io/iomgr.c +++ b/reactos/ntoskrnl/io/iomgr.c @@ -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(); } diff --git a/reactos/ntoskrnl/io/iowork.c b/reactos/ntoskrnl/io/iowork.c index 7eb34596374..035e1b91f1a 100644 --- a/reactos/ntoskrnl/io/iowork.c +++ b/reactos/ntoskrnl/io/iowork.c @@ -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 +/* 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 */