Implement Lookaside List allocation and release for IRPs on Per-CPU Lists, or global system lists if the per-cpu has been exhausted. This should tremendously reduce memory fragmentation and speed up I/o noticeably. Also, don't allocate IRPs with quota charge when they shouldn't. Modified: trunk/reactos/include/ddk/iodef.h Modified: trunk/reactos/ntoskrnl/io/file.c Modified: trunk/reactos/ntoskrnl/io/irp.c _____
Modified: trunk/reactos/include/ddk/iodef.h --- trunk/reactos/include/ddk/iodef.h 2005-05-13 03:34:13 UTC (rev 15254) +++ trunk/reactos/include/ddk/iodef.h 2005-05-13 04:49:54 UTC (rev 15255) @@ -134,6 +134,11 @@
IRP_RETRY_IO_COMPLETION = 0x4000 };
+#define IRP_QUOTA_CHARGED 0x01 +#define IRP_ALLOCATED_MUST_SUCCEED 0x02 +#define IRP_ALLOCATED_FIXED_SIZE 0x04 +#define IRP_LOOKASIDE_ALLOCATION 0x08 + #define SL_FORCE_ACCESS_CHECK (0x1) #define SL_OPEN_PAGING_FILE (0x2) #define SL_OPEN_TARGET_DIRECTORY (0x4) _____
Modified: trunk/reactos/ntoskrnl/io/file.c --- trunk/reactos/ntoskrnl/io/file.c 2005-05-13 03:34:13 UTC (rev 15254) +++ trunk/reactos/ntoskrnl/io/file.c 2005-05-13 04:49:54 UTC (rev 15255) @@ -210,7 +210,7 @@
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
/* Allocate an IRP */ - Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
/* Set it up */ Irp->UserEvent = &Event; @@ -329,7 +329,7 @@ }
/* Allocate the IRP */ - Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
/* Set the IRP */ Irp->Tail.Overlay.OriginalFileObject = FileObject; @@ -498,7 +498,7 @@ KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
/* Allocate an IRP */ - Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
/* Set it up */ Irp->UserEvent = &Event; @@ -1149,7 +1149,7 @@ }
/* Allocate the IRP */ - Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
/* Set the IRP */ Irp->Tail.Overlay.OriginalFileObject = FileObject; @@ -1586,7 +1586,7 @@ }
/* Allocate the IRP */ - if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE))) + if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) { ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; @@ -1699,7 +1699,7 @@ DeviceObject = FileObject->DeviceObject;
- Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE); + Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE); if (Irp==NULL) { ObDereferenceObject(FileObject); @@ -1795,7 +1795,7 @@ DeviceObject = IoGetRelatedDeviceObject(FileObject);
Irp = IoAllocateIrp(DeviceObject->StackSize, - TRUE); + FALSE); if (Irp == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; @@ -2123,7 +2123,7 @@ }
/* Allocate the IRP */ - if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE))) + if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) { ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; @@ -2321,7 +2321,7 @@ }
/* Allocate the IRP */ - if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE))) + if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) { ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; @@ -2775,7 +2775,7 @@ }
/* Allocate the IRP */ - if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE))) + if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) { ObDereferenceObject(FileObject); return STATUS_INSUFFICIENT_RESOURCES; @@ -2900,7 +2900,7 @@ DeviceObject = IoGetRelatedDeviceObject(FileObject);
Irp = IoAllocateIrp(DeviceObject->StackSize, - TRUE); + FALSE); if (Irp == NULL) { Status = STATUS_INSUFFICIENT_RESOURCES; _____
Modified: trunk/reactos/ntoskrnl/io/irp.c --- trunk/reactos/ntoskrnl/io/irp.c 2005-05-13 03:34:13 UTC (rev 15254) +++ trunk/reactos/ntoskrnl/io/irp.c 2005-05-13 04:49:54 UTC (rev 15255) @@ -366,31 +366,93 @@
IoAllocateIrp(CCHAR StackSize, BOOLEAN ChargeQuota) { - PIRP Irp; + PIRP Irp = NULL; USHORT Size = IoSizeOfIrp(StackSize); - - /* Check if we shoudl charge quota */ - if (ChargeQuota) + PKPRCB Prcb; + ULONG Flags = 0; + PNPAGED_LOOKASIDE_LIST List; + PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList; + + /* Figure out which Lookaside List to use */ + if ((StackSize <= 8) && (ChargeQuota == FALSE)) { - /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool,IoSizeOfIrp(StackSize), TAG_IRP); */ - /* FIXME */ - Irp = ExAllocatePoolWithTag(NonPagedPool, - Size, - TAG_IRP); + DPRINT("Using lookaside, %d\n", StackSize); + /* Set Fixed Size Flag */ + Flags = IRP_ALLOCATED_FIXED_SIZE; + + /* See if we should use big list */ + if (StackSize != 1) + { + DPRINT("Using large lookaside\n"); + Size = IoSizeOfIrp(8); + ListType = LookasideLargeIrpList; + } + + /* Get the PRCB */ + Prcb = KeGetCurrentPrcb(); + + /* Get the P List First */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P; + + /* Attempt allocation */ + List->L.TotalAllocates++; + DPRINT("Total allocates: %d\n", List->L.TotalAllocates); + Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead); + DPRINT("Alloc attempt on CPU list: %p\n", Irp); + + /* Check if the P List failed */ + if (!Irp) + { + /* Let the balancer know */ + List->L.AllocateMisses++; + DPRINT("Total misses: %d\n", List->L.AllocateMisses); + + /* Try the L List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L; + List->L.TotalAllocates++; + Irp = (PIRP)InterlockedPopEntrySList(&List->L.ListHead); + DPRINT("Alloc attempt on SYS list: %p\n", Irp); + } } + + /* Check if we have to use the pool */ + if (!Irp) + { + DPRINT("Using pool\n"); + /* Did we try lookaside and fail? */ + if (Flags & IRP_ALLOCATED_FIXED_SIZE) List->L.AllocateMisses++; + + /* Check if we shoudl charge quota */ + if (ChargeQuota) + { + /* Irp = ExAllocatePoolWithQuotaTag(NonPagedPool, Size, TAG_IRP); */ + /* FIXME */ + Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP); + } + else + { + /* Allocate the IRP With no Quota charge */ + Irp = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_IRP); + } + + /* Make sure it was sucessful */ + if (!Irp) return(NULL); + } else { - /* Allocate the IRP With no Quota charge */ - Irp = ExAllocatePoolWithTag(NonPagedPool, - Size, - TAG_IRP); + /* We have an IRP from Lookaside */ + Flags |= IRP_LOOKASIDE_ALLOCATION; } - - /* Make sure it was sucessful */ - if (Irp==NULL) return(NULL); - + + /* Set Flag */ + if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED; + /* Now Initialize it */ + DPRINT("irp allocated\n"); IoInitializeIrp(Irp, Size, StackSize); + + /* Set the Allocation Flags */ + Irp->AllocationFlags = Flags;
/* Return it */ return Irp; @@ -430,7 +492,7 @@ StartingOffset,IoStatusBlock);
/* Allocate IRP */ - if (!(Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE))) return Irp; + if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) return Irp;
/* Get the Stack */ StackPtr = IoGetNextIrpStackLocation(Irp); @@ -580,7 +642,7 @@ InternalDeviceIoControl,Event,IoStatusBlock);
/* Allocate IRP */ - if (!(Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE))) return Irp; + if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) return Irp;
/* Get the Stack */ StackPtr = IoGetNextIrpStackLocation(Irp); @@ -1177,8 +1239,59 @@ STDCALL IoFreeIrp(PIRP Irp) { - /* Free the pool memory associated with it */ - ExFreePoolWithTag(Irp, TAG_IRP); + PNPAGED_LOOKASIDE_LIST List; + PP_NPAGED_LOOKASIDE_NUMBER ListType = LookasideSmallIrpList; + PKPRCB Prcb; + + /* If this was a pool alloc, free it with the pool */ + if (!(Irp->AllocationFlags & IRP_ALLOCATED_FIXED_SIZE)) + { + /* Free it */ + DPRINT("Freeing pool IRP\n"); + ExFreePool(Irp); + } + else + { + DPRINT("Freeing Lookaside IRP\n"); + + /* Check if this was a Big IRP */ + if (Irp->StackCount != 1) + { + DPRINT("Large IRP\n"); + ListType = LookasideLargeIrpList; + } + + /* Get the PRCB */ + Prcb = KeGetCurrentPrcb(); + + /* Use the P List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].P; + List->L.TotalFrees++; + + /* Check if the Free was within the Depth or not */ + if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) + { + /* Let the balancer know */ + List->L.FreeMisses++; + + /* Use the L List */ + List = (PNPAGED_LOOKASIDE_LIST)Prcb->PPLookasideList[ListType].L; + List->L.TotalFrees++; + + /* Check if the Free was within the Depth or not */ + if (ExQueryDepthSList(&List->L.ListHead) >= List->L.Depth) + { + /* All lists failed, use the pool */ + List->L.FreeMisses++; + ExFreePool(Irp); + } + } + + /* The free was within dhe Depth */ + InterlockedPushEntrySList(&List->L.ListHead, (PSINGLE_LIST_ENTRY)Irp); + } + + DPRINT("Free done\n"); }
/* @@ -1324,7 +1437,7 @@ PIRP AssocIrp;
/* Allocate the IRP */ - AssocIrp = IoAllocateIrp(StackSize,FALSE); + AssocIrp = IoAllocateIrp(StackSize, FALSE); if (AssocIrp == NULL) return NULL;
/* Set the Flags */