mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 10:04:49 +00:00
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.
svn path=/trunk/; revision=15255
This commit is contained in:
parent
9ca493afb5
commit
6d1d9cbac8
3 changed files with 151 additions and 33 deletions
|
@ -134,6 +134,11 @@ enum
|
||||||
IRP_RETRY_IO_COMPLETION = 0x4000
|
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_FORCE_ACCESS_CHECK (0x1)
|
||||||
#define SL_OPEN_PAGING_FILE (0x2)
|
#define SL_OPEN_PAGING_FILE (0x2)
|
||||||
#define SL_OPEN_TARGET_DIRECTORY (0x4)
|
#define SL_OPEN_TARGET_DIRECTORY (0x4)
|
||||||
|
|
|
@ -210,7 +210,7 @@ IopDeleteFile(PVOID ObjectBody)
|
||||||
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
||||||
|
|
||||||
/* Allocate an IRP */
|
/* Allocate an IRP */
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
|
||||||
/* Set it up */
|
/* Set it up */
|
||||||
Irp->UserEvent = &Event;
|
Irp->UserEvent = &Event;
|
||||||
|
@ -329,7 +329,7 @@ IopSecurityFile(PVOID ObjectBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
|
||||||
/* Set the IRP */
|
/* Set the IRP */
|
||||||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||||
|
@ -498,7 +498,7 @@ IopCloseFile(PVOID ObjectBody,
|
||||||
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
KeInitializeEvent(&Event, SynchronizationEvent, FALSE);
|
||||||
|
|
||||||
/* Allocate an IRP */
|
/* Allocate an IRP */
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
|
||||||
/* Set it up */
|
/* Set it up */
|
||||||
Irp->UserEvent = &Event;
|
Irp->UserEvent = &Event;
|
||||||
|
@ -1149,7 +1149,7 @@ IoQueryFileInformation(IN PFILE_OBJECT FileObject,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
|
|
||||||
/* Set the IRP */
|
/* Set the IRP */
|
||||||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||||
|
@ -1586,7 +1586,7 @@ NtFlushBuffersFile(IN HANDLE FileHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
|
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
|
||||||
{
|
{
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -1699,7 +1699,7 @@ NtNotifyChangeDirectoryFile(IN HANDLE FileHandle,
|
||||||
DeviceObject = FileObject->DeviceObject;
|
DeviceObject = FileObject->DeviceObject;
|
||||||
|
|
||||||
|
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE);
|
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
|
||||||
if (Irp==NULL)
|
if (Irp==NULL)
|
||||||
{
|
{
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
|
@ -1795,7 +1795,7 @@ NtLockFile(IN HANDLE FileHandle,
|
||||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
|
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
||||||
TRUE);
|
FALSE);
|
||||||
if (Irp == NULL)
|
if (Irp == NULL)
|
||||||
{
|
{
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -2123,7 +2123,7 @@ NtQueryDirectoryFile(IN HANDLE FileHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
|
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
|
||||||
{
|
{
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -2321,7 +2321,7 @@ NtQueryInformationFile(HANDLE FileHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
|
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
|
||||||
{
|
{
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -2775,7 +2775,7 @@ NtSetInformationFile(HANDLE FileHandle,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, TRUE)))
|
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE)))
|
||||||
{
|
{
|
||||||
ObDereferenceObject(FileObject);
|
ObDereferenceObject(FileObject);
|
||||||
return STATUS_INSUFFICIENT_RESOURCES;
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
@ -2900,7 +2900,7 @@ NtUnlockFile(IN HANDLE FileHandle,
|
||||||
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
DeviceObject = IoGetRelatedDeviceObject(FileObject);
|
||||||
|
|
||||||
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
Irp = IoAllocateIrp(DeviceObject->StackSize,
|
||||||
TRUE);
|
FALSE);
|
||||||
if (Irp == NULL)
|
if (Irp == NULL)
|
||||||
{
|
{
|
||||||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
|
|
@ -366,31 +366,93 @@ STDCALL
|
||||||
IoAllocateIrp(CCHAR StackSize,
|
IoAllocateIrp(CCHAR StackSize,
|
||||||
BOOLEAN ChargeQuota)
|
BOOLEAN ChargeQuota)
|
||||||
{
|
{
|
||||||
PIRP Irp;
|
PIRP Irp = NULL;
|
||||||
USHORT Size = IoSizeOfIrp(StackSize);
|
USHORT Size = IoSizeOfIrp(StackSize);
|
||||||
|
PKPRCB Prcb;
|
||||||
/* Check if we shoudl charge quota */
|
ULONG Flags = 0;
|
||||||
if (ChargeQuota)
|
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); */
|
DPRINT("Using lookaside, %d\n", StackSize);
|
||||||
/* FIXME */
|
/* Set Fixed Size Flag */
|
||||||
Irp = ExAllocatePoolWithTag(NonPagedPool,
|
Flags = IRP_ALLOCATED_FIXED_SIZE;
|
||||||
Size,
|
|
||||||
TAG_IRP);
|
/* 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
|
else
|
||||||
{
|
{
|
||||||
/* Allocate the IRP With no Quota charge */
|
/* We have an IRP from Lookaside */
|
||||||
Irp = ExAllocatePoolWithTag(NonPagedPool,
|
Flags |= IRP_LOOKASIDE_ALLOCATION;
|
||||||
Size,
|
|
||||||
TAG_IRP);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure it was sucessful */
|
/* Set Flag */
|
||||||
if (Irp==NULL) return(NULL);
|
if (ChargeQuota) Flags |= IRP_QUOTA_CHARGED;
|
||||||
|
|
||||||
/* Now Initialize it */
|
/* Now Initialize it */
|
||||||
|
DPRINT("irp allocated\n");
|
||||||
IoInitializeIrp(Irp, Size, StackSize);
|
IoInitializeIrp(Irp, Size, StackSize);
|
||||||
|
|
||||||
|
/* Set the Allocation Flags */
|
||||||
|
Irp->AllocationFlags = Flags;
|
||||||
|
|
||||||
/* Return it */
|
/* Return it */
|
||||||
return Irp;
|
return Irp;
|
||||||
|
@ -430,7 +492,7 @@ IoBuildAsynchronousFsdRequest(ULONG MajorFunction,
|
||||||
StartingOffset,IoStatusBlock);
|
StartingOffset,IoStatusBlock);
|
||||||
|
|
||||||
/* Allocate IRP */
|
/* Allocate IRP */
|
||||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE))) return Irp;
|
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) return Irp;
|
||||||
|
|
||||||
/* Get the Stack */
|
/* Get the Stack */
|
||||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||||
|
@ -580,7 +642,7 @@ IoBuildDeviceIoControlRequest (ULONG IoControlCode,
|
||||||
InternalDeviceIoControl,Event,IoStatusBlock);
|
InternalDeviceIoControl,Event,IoStatusBlock);
|
||||||
|
|
||||||
/* Allocate IRP */
|
/* Allocate IRP */
|
||||||
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize,TRUE))) return Irp;
|
if (!(Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE))) return Irp;
|
||||||
|
|
||||||
/* Get the Stack */
|
/* Get the Stack */
|
||||||
StackPtr = IoGetNextIrpStackLocation(Irp);
|
StackPtr = IoGetNextIrpStackLocation(Irp);
|
||||||
|
@ -1177,8 +1239,59 @@ VOID
|
||||||
STDCALL
|
STDCALL
|
||||||
IoFreeIrp(PIRP Irp)
|
IoFreeIrp(PIRP Irp)
|
||||||
{
|
{
|
||||||
/* Free the pool memory associated with it */
|
PNPAGED_LOOKASIDE_LIST List;
|
||||||
ExFreePoolWithTag(Irp, TAG_IRP);
|
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 @@ IoMakeAssociatedIrp(PIRP Irp,
|
||||||
PIRP AssocIrp;
|
PIRP AssocIrp;
|
||||||
|
|
||||||
/* Allocate the IRP */
|
/* Allocate the IRP */
|
||||||
AssocIrp = IoAllocateIrp(StackSize,FALSE);
|
AssocIrp = IoAllocateIrp(StackSize, FALSE);
|
||||||
if (AssocIrp == NULL) return NULL;
|
if (AssocIrp == NULL) return NULL;
|
||||||
|
|
||||||
/* Set the Flags */
|
/* Set the Flags */
|
||||||
|
|
Loading…
Reference in a new issue