PVOID Context;
} DEVICETREE_TRAVERSE_CONTEXT, *PDEVICETREE_TRAVERSE_CONTEXT;
+//
+// Reserve IRP allocator
+// Used for read paging IOs in low-memory situations
+//
+typedef struct _RESERVE_IRP_ALLOCATOR
+{
+ PIRP ReserveIrp;
+ volatile LONG ReserveIrpInUse;
+ KEVENT WaitEvent;
+ CCHAR StackSize;
+} RESERVE_IRP_ALLOCATOR, *PRESERVE_IRP_ALLOCATOR;
+
//
// Resource code
//
IN CCHAR StackSize
);
+BOOLEAN
+NTAPI
+IopInitializeReserveIrp(
+ IN PRESERVE_IRP_ALLOCATOR ReserveIrpAllocator
+);
+
+PIRP
+NTAPI
+IopAllocateReserveIrp(
+ IN CCHAR StackSize
+);
+
//
// Shutdown routines
//
extern PDRIVER_OBJECT IopRootDriverObject;
extern KSPIN_LOCK IopDeviceRelationsSpinLock;
extern LIST_ENTRY IopDeviceRelationsRequestList;
+extern RESERVE_IRP_ALLOCATOR IopReserveIrpAllocator;
//
// Inlined Functions
#include <debug.h>
#include "internal/io_i.h"
+volatile LONG IoPageReadIrpAllocationFailure = 0;
+volatile LONG IoPageReadNonPagefileIrpAllocationFailure = 0;
+
/* PRIVATE FUNCTIONS *********************************************************/
VOID
/* Allocate IRP */
Irp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
- if (!Irp) return STATUS_INSUFFICIENT_RESOURCES;
+ /* If allocation failed, try to see whether we can use
+ * the reserve IRP
+ */
+ if (Irp == NULL)
+ {
+ /* We will use it only for paging file */
+ if (MmIsFileObjectAPagingFile(FileObject))
+ {
+ InterlockedExchangeAdd(&IoPageReadIrpAllocationFailure, 1);
+ Irp = IopAllocateReserveIrp(DeviceObject->StackSize);
+ }
+ else
+ {
+ InterlockedExchangeAdd(&IoPageReadNonPagefileIrpAllocationFailure, 1);
+ }
+
+ /* If allocation failed (not a paging file or too big stack size)
+ * Fail for real
+ */
+ if (Irp == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
/* Get the Stack */
StackPtr = IoGetNextIrpStackLocation(Irp);
* PROGRAMMERS: Alex Ionescu (alex.ionescu@reactos.org)
* Gunnar Dalsnes
* Filip Navara (navaraf@reactos.org)
+ * Pierre Schweitzer (pierre@reactos.org)
*/
/* INCLUDES ****************************************************************/
#include <debug.h>
PIRP IopDeadIrp;
+RESERVE_IRP_ALLOCATOR IopReserveIrpAllocator;
/* PRIVATE FUNCTIONS ********************************************************/
}
}
+BOOLEAN
+NTAPI
+IopInitializeReserveIrp(IN PRESERVE_IRP_ALLOCATOR ReserveIrpAllocator)
+{
+ /* Our allocated stack size */
+ ReserveIrpAllocator->StackSize = 20;
+
+ /* Allocate the IRP now */
+ ReserveIrpAllocator->ReserveIrp = IoAllocateIrp(ReserveIrpAllocator->StackSize, FALSE);
+ /* If we cannot, abort system boot */
+ if (ReserveIrpAllocator->ReserveIrp == NULL)
+ {
+ return FALSE;
+ }
+
+ /* It's not in use */
+ ReserveIrpAllocator->ReserveIrpInUse = 0;
+ /* And init the event */
+ KeInitializeEvent(&ReserveIrpAllocator->WaitEvent, SynchronizationEvent, FALSE);
+
+ /* All good, keep booting */
+ return TRUE;
+}
+
+PIRP
+NTAPI
+IopAllocateReserveIrp(IN CCHAR StackSize)
+{
+ /* If we need a stack size higher than what was allocated, then fail */
+ if (StackSize > IopReserveIrpAllocator.StackSize)
+ {
+ return NULL;
+ }
+
+ /* Now, wait until the IRP becomes available and reserve it immediately */
+ while (InterlockedExchange(&IopReserveIrpAllocator.ReserveIrpInUse, 1) == 1)
+ {
+ KeWaitForSingleObject(&IopReserveIrpAllocator.WaitEvent,
+ Executive,
+ KernelMode,
+ FALSE,
+ NULL);
+ }
+
+ /* It's ours! Initialize it */
+ IoInitializeIrp(IopReserveIrpAllocator.ReserveIrp, IoSizeOfIrp(StackSize), StackSize);
+
+ /* And return it to the caller */
+ return IopReserveIrpAllocator.ReserveIrp;
+}
+
+VOID
+IopFreeReserveIrp(IN CCHAR PriorityBoost)
+{
+ /* Mark we don't use the IRP anymore */
+ InterlockedExchange(&IopReserveIrpAllocator.ReserveIrpInUse, 0);
+
+ /* And set the event if someone is waiting on the IRP */
+ KeSetEvent(&IopReserveIrpAllocator.WaitEvent, PriorityBoost, FALSE);
+}
+
/* FUNCTIONS *****************************************************************/
/*
KeSetEvent(Irp->UserEvent, PriorityBoost, FALSE);
/* Free the IRP for a Paging I/O Only, Close is handled by us */
- if (Flags) IoFreeIrp(Irp);
+ if (Flags)
+ {
+ /* If we were using the reserve IRP, then call the appropriate
+ * free function (to make the IRP available again)
+ */
+ if (Irp == IopReserveIrpAllocator.ReserveIrp)
+ {
+ IopFreeReserveIrp(PriorityBoost);
+ }
+ /* Otherwise, free for real! */
+ else
+ {
+ IoFreeIrp(Irp);
+ }
+ }
}
else
{