diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index b6901db8452..778bf6d8073 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -1277,6 +1277,8 @@ extern ULONG IopNumTriageDumpDataBlocks; extern PVOID IopTriageDumpDataBlocks[64]; extern PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList; extern PDRIVER_OBJECT IopRootDriverObject; +extern KSPIN_LOCK IopDeviceRelationsSpinLock; +extern LIST_ENTRY IopDeviceRelationsRequestList; // // Inlined Functions diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpinit.c b/reactos/ntoskrnl/io/pnpmgr/pnpinit.c index c51e326229a..504565f978a 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpinit.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpinit.c @@ -385,6 +385,8 @@ IopInitializePlugPlayServices(VOID) /* Initialize locks and such */ KeInitializeSpinLock(&IopDeviceTreeLock); + KeInitializeSpinLock(&IopDeviceRelationsSpinLock); + InitializeListHead(&IopDeviceRelationsRequestList); /* Get the default interface */ PnpDefaultInterfaceType = IopDetermineDefaultInterfaceType(); diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index 1cdfc5d46d3..3fe5e6e2957 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -30,12 +30,16 @@ extern BOOLEAN PnpSystemInit; PDRIVER_OBJECT IopRootDriverObject; PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList = NULL; +LIST_ENTRY IopDeviceRelationsRequestList; +WORK_QUEUE_ITEM IopDeviceRelationsWorkItem; +BOOLEAN IopDeviceRelationsRequestInProgress; +KSPIN_LOCK IopDeviceRelationsSpinLock; typedef struct _INVALIDATE_DEVICE_RELATION_DATA { + LIST_ENTRY RequestListEntry; PDEVICE_OBJECT DeviceObject; DEVICE_RELATION_TYPE Type; - PIO_WORKITEM WorkItem; } INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA; /* FUNCTIONS *****************************************************************/ @@ -890,20 +894,34 @@ IopQueryDeviceCapabilities(PDEVICE_NODE DeviceNode, return Status; } -static VOID NTAPI -IopAsynchronousInvalidateDeviceRelations( - IN PDEVICE_OBJECT DeviceObject, - IN PVOID InvalidateContext) +static +VOID +NTAPI +IopDeviceRelationsWorker( + _In_ PVOID Context) { - PINVALIDATE_DEVICE_RELATION_DATA Data = InvalidateContext; + PLIST_ENTRY ListEntry; + PINVALIDATE_DEVICE_RELATION_DATA Data; + KIRQL OldIrql; - IoSynchronousInvalidateDeviceRelations( - Data->DeviceObject, - Data->Type); + KeAcquireSpinLock(&IopDeviceRelationsSpinLock, &OldIrql); + while (!IsListEmpty(&IopDeviceRelationsRequestList)) + { + ListEntry = RemoveHeadList(&IopDeviceRelationsRequestList); + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); + Data = CONTAINING_RECORD(ListEntry, + INVALIDATE_DEVICE_RELATION_DATA, + RequestListEntry); - ObDereferenceObject(Data->DeviceObject); - IoFreeWorkItem(Data->WorkItem); - ExFreePool(Data); + IoSynchronousInvalidateDeviceRelations(Data->DeviceObject, + Data->Type); + + ObDereferenceObject(Data->DeviceObject); + ExFreePool(Data); + KeAcquireSpinLock(&IopDeviceRelationsSpinLock, &OldIrql); + } + IopDeviceRelationsRequestInProgress = FALSE; + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); } NTSTATUS @@ -4670,29 +4688,32 @@ IoInvalidateDeviceRelations( IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type) { - PIO_WORKITEM WorkItem; PINVALIDATE_DEVICE_RELATION_DATA Data; + KIRQL OldIrql; Data = ExAllocatePool(NonPagedPool, sizeof(INVALIDATE_DEVICE_RELATION_DATA)); if (!Data) return; - WorkItem = IoAllocateWorkItem(DeviceObject); - if (!WorkItem) - { - ExFreePool(Data); - return; - } ObReferenceObject(DeviceObject); Data->DeviceObject = DeviceObject; Data->Type = Type; - Data->WorkItem = WorkItem; - IoQueueWorkItem( - WorkItem, - IopAsynchronousInvalidateDeviceRelations, - DelayedWorkQueue, - Data); + KeAcquireSpinLock(&IopDeviceRelationsSpinLock, &OldIrql); + InsertTailList(&IopDeviceRelationsRequestList, &Data->RequestListEntry); + if (IopDeviceRelationsRequestInProgress) + { + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); + return; + } + IopDeviceRelationsRequestInProgress = TRUE; + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); + + ExInitializeWorkItem(&IopDeviceRelationsWorkItem, + IopDeviceRelationsWorker, + NULL); + ExQueueWorkItem(&IopDeviceRelationsWorkItem, + DelayedWorkQueue); } /*