mirror of
https://github.com/reactos/reactos.git
synced 2025-01-04 21:38:43 +00:00
[FORMATTING]
* Improve indentation, remove trailing spaces, apply a consistent style, adjust to 80 col... No code changes. svn path=/trunk/; revision=56262
This commit is contained in:
parent
a13075fb0e
commit
5491e8fbde
7 changed files with 2260 additions and 2040 deletions
1182
reactos/ntoskrnl/cache/section/data.c
vendored
1182
reactos/ntoskrnl/cache/section/data.c
vendored
File diff suppressed because it is too large
Load diff
1308
reactos/ntoskrnl/cache/section/fault.c
vendored
1308
reactos/ntoskrnl/cache/section/fault.c
vendored
File diff suppressed because it is too large
Load diff
231
reactos/ntoskrnl/cache/section/io.c
vendored
231
reactos/ntoskrnl/cache/section/io.c
vendored
|
@ -64,19 +64,18 @@ MmGetDeviceObjectForFile(IN PFILE_OBJECT FileObject)
|
|||
return IoGetRelatedDeviceObject(FileObject);
|
||||
}
|
||||
|
||||
// Note:
|
||||
// This completion function is really required. Paging io completion does almost
|
||||
// nothing, including freeing the mdls.
|
||||
/* Note:
|
||||
This completion function is really required. Paging io completion does almost
|
||||
nothing, including freeing the mdls. */
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSimpleReadComplete
|
||||
(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context)
|
||||
MiSimpleReadComplete(PDEVICE_OBJECT DeviceObject,
|
||||
PIRP Irp,
|
||||
PVOID Context)
|
||||
{
|
||||
PMDL Mdl = Irp->MdlAddress;
|
||||
|
||||
/* Unlock MDL Pages, page 167. */
|
||||
/* Unlock MDL Pages, page 167. */
|
||||
DPRINT("MiSimpleReadComplete %p\n", Irp);
|
||||
while (Mdl)
|
||||
{
|
||||
|
@ -98,13 +97,12 @@ MiSimpleReadComplete
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSimpleRead
|
||||
(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
BOOLEAN Paging,
|
||||
PIO_STATUS_BLOCK ReadStatus)
|
||||
MiSimpleRead(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
BOOLEAN Paging,
|
||||
PIO_STATUS_BLOCK ReadStatus)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PIRP Irp = NULL;
|
||||
|
@ -118,32 +116,30 @@ MiSimpleRead
|
|||
ASSERT(ReadStatus);
|
||||
|
||||
DeviceObject = MmGetDeviceObjectForFile(FileObject);
|
||||
ReadStatus->Status = STATUS_INTERNAL_ERROR;
|
||||
ReadStatus->Information = 0;
|
||||
ReadStatus->Status = STATUS_INTERNAL_ERROR;
|
||||
ReadStatus->Information = 0;
|
||||
|
||||
ASSERT(DeviceObject);
|
||||
|
||||
DPRINT
|
||||
("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %d\n",
|
||||
FileObject,
|
||||
&FileObject->FileName,
|
||||
FileOffset->HighPart,
|
||||
FileOffset->LowPart,
|
||||
Length);
|
||||
DPRINT("PAGING READ: FileObject %p <%wZ> Offset %08x%08x Length %d\n",
|
||||
FileObject,
|
||||
&FileObject->FileName,
|
||||
FileOffset->HighPart,
|
||||
FileOffset->LowPart,
|
||||
Length);
|
||||
|
||||
KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
|
||||
|
||||
Irp = IoBuildAsynchronousFsdRequest
|
||||
(IRP_MJ_READ,
|
||||
DeviceObject,
|
||||
Buffer,
|
||||
Length,
|
||||
FileOffset,
|
||||
ReadStatus);
|
||||
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
|
||||
DeviceObject,
|
||||
Buffer,
|
||||
Length,
|
||||
FileOffset,
|
||||
ReadStatus);
|
||||
|
||||
if (!Irp)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Irp->Flags |= (Paging ? IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE : 0) | IRP_SYNCHRONOUS_API;
|
||||
|
@ -152,49 +148,44 @@ MiSimpleRead
|
|||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
|
||||
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
|
||||
IrpSp->FileObject = FileObject;
|
||||
IrpSp->CompletionRoutine = MiSimpleReadComplete;
|
||||
|
||||
// Non paging case, the FileObject will be dereferenced at completion
|
||||
/* Non paging case, the FileObject will be dereferenced at completion */
|
||||
if (!Paging)
|
||||
ObReferenceObject(FileObject);
|
||||
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
|
||||
if (!NT_SUCCESS
|
||||
(KeWaitForSingleObject
|
||||
(&ReadWait,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL)))
|
||||
{
|
||||
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
|
||||
ASSERT(FALSE);
|
||||
return Status;
|
||||
}
|
||||
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
|
||||
if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL)))
|
||||
{
|
||||
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
|
||||
ASSERT(FALSE);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
|
||||
Status =
|
||||
ReadStatus->Status == STATUS_END_OF_FILE ?
|
||||
STATUS_SUCCESS : ReadStatus->Status;
|
||||
Status = ReadStatus->Status == STATUS_END_OF_FILE ? STATUS_SUCCESS : ReadStatus->Status;
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiSimpleWrite
|
||||
(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PIO_STATUS_BLOCK ReadStatus,
|
||||
const char *File,
|
||||
int Line)
|
||||
_MiSimpleWrite(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PIO_STATUS_BLOCK ReadStatus,
|
||||
const char *File,
|
||||
int Line)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PIRP Irp = NULL;
|
||||
|
@ -207,31 +198,29 @@ _MiSimpleWrite
|
|||
ASSERT(Buffer);
|
||||
ASSERT(ReadStatus);
|
||||
|
||||
DeviceObject = MmGetDeviceObjectForFile(FileObject);
|
||||
DeviceObject = MmGetDeviceObjectForFile(FileObject);
|
||||
ASSERT(DeviceObject);
|
||||
|
||||
DPRINT
|
||||
("PAGING WRITE: FileObject %x <%wZ> Offset %x Length %d (%s:%d)\n",
|
||||
FileObject,
|
||||
&FileObject->FileName,
|
||||
FileOffset->LowPart,
|
||||
Length,
|
||||
File,
|
||||
Line);
|
||||
DPRINT("PAGING WRITE: FileObject %x <%wZ> Offset %x Length %d (%s:%d)\n",
|
||||
FileObject,
|
||||
&FileObject->FileName,
|
||||
FileOffset->LowPart,
|
||||
Length,
|
||||
File,
|
||||
Line);
|
||||
|
||||
KeInitializeEvent(&ReadWait, NotificationEvent, FALSE);
|
||||
|
||||
Irp = IoBuildAsynchronousFsdRequest
|
||||
(IRP_MJ_WRITE,
|
||||
DeviceObject,
|
||||
Buffer,
|
||||
Length,
|
||||
FileOffset,
|
||||
ReadStatus);
|
||||
Irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
|
||||
DeviceObject,
|
||||
Buffer,
|
||||
Length,
|
||||
FileOffset,
|
||||
ReadStatus);
|
||||
|
||||
if (!Irp)
|
||||
{
|
||||
return STATUS_NO_MEMORY;
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
|
||||
Irp->Flags = IRP_PAGING_IO | IRP_SYNCHRONOUS_PAGING_IO | IRP_NOCACHE | IRP_SYNCHRONOUS_API;
|
||||
|
@ -240,29 +229,27 @@ _MiSimpleWrite
|
|||
Irp->Tail.Overlay.OriginalFileObject = FileObject;
|
||||
Irp->Tail.Overlay.Thread = PsGetCurrentThread();
|
||||
IrpSp = IoGetNextIrpStackLocation(Irp);
|
||||
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
|
||||
IrpSp->Control |= SL_INVOKE_ON_SUCCESS | SL_INVOKE_ON_ERROR;
|
||||
IrpSp->FileObject = FileObject;
|
||||
IrpSp->CompletionRoutine = MiSimpleReadComplete;
|
||||
|
||||
DPRINT("Call Driver\n");
|
||||
DPRINT("Call Driver\n");
|
||||
Status = IoCallDriver(DeviceObject, Irp);
|
||||
DPRINT("Status %x\n", Status);
|
||||
DPRINT("Status %x\n", Status);
|
||||
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
|
||||
if (!NT_SUCCESS
|
||||
(KeWaitForSingleObject
|
||||
(&ReadWait,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL)))
|
||||
{
|
||||
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
|
||||
ASSERT(FALSE);
|
||||
return Status;
|
||||
}
|
||||
DPRINT("KeWaitForSingleObject(&ReadWait)\n");
|
||||
if (!NT_SUCCESS(KeWaitForSingleObject(&ReadWait,
|
||||
Suspended,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL)))
|
||||
{
|
||||
DPRINT1("Warning: Failed to wait for synchronous IRP\n");
|
||||
ASSERT(FALSE);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
DPRINT("Paging IO Done: %08x\n", ReadStatus->Status);
|
||||
|
@ -274,45 +261,49 @@ FAST_MUTEX MiWriteMutex;
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiWriteBackPage
|
||||
(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
ULONG Length,
|
||||
PFN_NUMBER Page,
|
||||
const char *File,
|
||||
int Line)
|
||||
_MiWriteBackPage(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
ULONG Length,
|
||||
PFN_NUMBER Page,
|
||||
const char *File,
|
||||
int Line)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
PVOID Hyperspace;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
KIRQL OldIrql;
|
||||
PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
|
||||
NTSTATUS Status;
|
||||
PVOID Hyperspace;
|
||||
IO_STATUS_BLOCK Iosb;
|
||||
KIRQL OldIrql;
|
||||
PVOID PageBuffer = ExAllocatePool(NonPagedPool, PAGE_SIZE);
|
||||
|
||||
if (!PageBuffer) return STATUS_NO_MEMORY;
|
||||
if (!PageBuffer) return STATUS_NO_MEMORY;
|
||||
|
||||
Hyperspace = MiMapPageInHyperSpace(PsGetCurrentProcess(), Page, &OldIrql);
|
||||
Hyperspace = MiMapPageInHyperSpace(PsGetCurrentProcess(), Page, &OldIrql);
|
||||
if (!Hyperspace)
|
||||
{
|
||||
ExFreePool(PageBuffer);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE);
|
||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Hyperspace, OldIrql);
|
||||
RtlCopyMemory(PageBuffer, Hyperspace, PAGE_SIZE);
|
||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), Hyperspace, OldIrql);
|
||||
|
||||
DPRINT("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n", &FileObject->FileName, FileOffset->u.HighPart, FileOffset->u.LowPart, File, Line);
|
||||
Status = MiSimpleWrite
|
||||
(FileObject,
|
||||
FileOffset,
|
||||
PageBuffer,
|
||||
Length,
|
||||
&Iosb);
|
||||
DPRINT("MiWriteBackPage(%wZ,%08x%08x,%s:%d)\n",
|
||||
&FileObject->FileName,
|
||||
FileOffset->u.HighPart,
|
||||
FileOffset->u.LowPart,
|
||||
File,
|
||||
Line);
|
||||
|
||||
ExFreePool(PageBuffer);
|
||||
Status = MiSimpleWrite(FileObject,
|
||||
FileOffset,
|
||||
PageBuffer,
|
||||
Length,
|
||||
&Iosb);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("MiSimpleWrite failed (%x)\n", Status);
|
||||
}
|
||||
ExFreePool(PageBuffer);
|
||||
|
||||
return Status;
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("MiSimpleWrite failed (%x)\n", Status);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
378
reactos/ntoskrnl/cache/section/newmm.h
vendored
378
reactos/ntoskrnl/cache/section/newmm.h
vendored
|
@ -8,7 +8,7 @@
|
|||
#define PFN_FROM_SSE(E) ((E) >> PAGE_SHIFT)
|
||||
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
|
||||
#define MM_IS_WAIT_PTE(E) \
|
||||
(IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY)
|
||||
(IS_SWAP_FROM_SSE(E) && SWAPENTRY_FROM_SSE(E) == MM_WAIT_ENTRY)
|
||||
#define MAKE_PFN_SSE(P) ((P) << PAGE_SHIFT)
|
||||
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
|
||||
#define MAKE_SWAP_SSE(S) (((ULONG)(S) << 1) | 0x1)
|
||||
|
@ -27,19 +27,19 @@
|
|||
/* Determine what's needed to make paged pool fit in this category.
|
||||
* it seems that something more is required to satisfy arm3. */
|
||||
#define BALANCER_CAN_EVICT(Consumer) \
|
||||
(((Consumer) == MC_USER) || \
|
||||
((Consumer) == MC_CACHE))
|
||||
(((Consumer) == MC_USER) || \
|
||||
((Consumer) == MC_CACHE))
|
||||
|
||||
#define SEC_CACHE (0x20000000)
|
||||
|
||||
#define MiWaitForPageEvent(Process,Address) do { \
|
||||
DPRINT("MiWaitForPageEvent %x:%x #\n", Process, Address); \
|
||||
#define MiWaitForPageEvent(Process,Address) do { \
|
||||
DPRINT("MiWaitForPageEvent %x:%x #\n", Process, Address); \
|
||||
KeWaitForSingleObject(&MmWaitPageEvent, 0, KernelMode, FALSE, NULL); \
|
||||
} while(0)
|
||||
|
||||
#define MiSetPageEvent(Process,Address) do { \
|
||||
DPRINT("MiSetPageEvent %x:%x #\n",Process, Address); \
|
||||
KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE); \
|
||||
#define MiSetPageEvent(Process,Address) do { \
|
||||
DPRINT("MiSetPageEvent %x:%x #\n",Process, Address); \
|
||||
KeSetEvent(&MmWaitPageEvent, IO_NO_INCREMENT, FALSE); \
|
||||
} while(0)
|
||||
|
||||
/* We store 8 bits of location with a page association */
|
||||
|
@ -47,69 +47,72 @@
|
|||
|
||||
extern KEVENT MmWaitPageEvent;
|
||||
|
||||
typedef struct _CACHE_SECTION_PAGE_TABLE
|
||||
typedef struct _CACHE_SECTION_PAGE_TABLE
|
||||
{
|
||||
LARGE_INTEGER FileOffset;
|
||||
PMM_SECTION_SEGMENT Segment;
|
||||
PMM_SECTION_SEGMENT Segment;
|
||||
ULONG Refcount;
|
||||
ULONG PageEntries[ENTRIES_PER_ELEMENT];
|
||||
} CACHE_SECTION_PAGE_TABLE, *PCACHE_SECTION_PAGE_TABLE;
|
||||
|
||||
struct _MM_REQUIRED_RESOURCES;
|
||||
|
||||
typedef NTSTATUS (NTAPI * AcquireResource)
|
||||
(PMMSUPPORT AddressSpace,
|
||||
struct _MEMORY_AREA *MemoryArea,
|
||||
struct _MM_REQUIRED_RESOURCES *Required);
|
||||
typedef NTSTATUS (NTAPI * NotPresentFaultHandler)
|
||||
(PMMSUPPORT AddressSpace,
|
||||
struct _MEMORY_AREA *MemoryArea,
|
||||
PVOID Address,
|
||||
BOOLEAN Locked,
|
||||
struct _MM_REQUIRED_RESOURCES *Required);
|
||||
typedef NTSTATUS (NTAPI * FaultHandler)
|
||||
(PMMSUPPORT AddressSpace,
|
||||
struct _MEMORY_AREA *MemoryArea,
|
||||
PVOID Address,
|
||||
struct _MM_REQUIRED_RESOURCES *Required);
|
||||
typedef NTSTATUS (NTAPI * AcquireResource)(
|
||||
PMMSUPPORT AddressSpace,
|
||||
struct _MEMORY_AREA *MemoryArea,
|
||||
struct _MM_REQUIRED_RESOURCES *Required);
|
||||
|
||||
typedef NTSTATUS (NTAPI * NotPresentFaultHandler)(
|
||||
PMMSUPPORT AddressSpace,
|
||||
struct _MEMORY_AREA *MemoryArea,
|
||||
PVOID Address,
|
||||
BOOLEAN Locked,
|
||||
struct _MM_REQUIRED_RESOURCES *Required);
|
||||
|
||||
typedef NTSTATUS (NTAPI * FaultHandler)(
|
||||
PMMSUPPORT AddressSpace,
|
||||
struct _MEMORY_AREA *MemoryArea,
|
||||
PVOID Address,
|
||||
struct _MM_REQUIRED_RESOURCES *Required);
|
||||
|
||||
typedef struct _MM_REQUIRED_RESOURCES
|
||||
{
|
||||
ULONG Consumer;
|
||||
ULONG Amount;
|
||||
ULONG Offset;
|
||||
ULONG State;
|
||||
PVOID Context;
|
||||
LARGE_INTEGER FileOffset;
|
||||
AcquireResource DoAcquisition;
|
||||
PFN_NUMBER Page[2];
|
||||
PVOID Buffer[2];
|
||||
SWAPENTRY SwapEntry;
|
||||
const char *File;
|
||||
int Line;
|
||||
ULONG Consumer;
|
||||
ULONG Amount;
|
||||
ULONG Offset;
|
||||
ULONG State;
|
||||
PVOID Context;
|
||||
LARGE_INTEGER FileOffset;
|
||||
AcquireResource DoAcquisition;
|
||||
PFN_NUMBER Page[2];
|
||||
PVOID Buffer[2];
|
||||
SWAPENTRY SwapEntry;
|
||||
const char *File;
|
||||
int Line;
|
||||
} MM_REQUIRED_RESOURCES, *PMM_REQUIRED_RESOURCES;
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmCreateCacheSection
|
||||
(PROS_SECTION_OBJECT *SectionObject,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PLARGE_INTEGER UMaximumSize,
|
||||
ULONG SectionPageProtection,
|
||||
ULONG AllocationAttributes,
|
||||
PFILE_OBJECT FileObject);
|
||||
MmCreateCacheSection(PROS_SECTION_OBJECT *SectionObject,
|
||||
ACCESS_MASK DesiredAccess,
|
||||
POBJECT_ATTRIBUTES ObjectAttributes,
|
||||
PLARGE_INTEGER UMaximumSize,
|
||||
ULONG SectionPageProtection,
|
||||
ULONG AllocationAttributes,
|
||||
PFILE_OBJECT FileObject);
|
||||
|
||||
PFN_NUMBER
|
||||
NTAPI
|
||||
MmWithdrawSectionPage
|
||||
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty);
|
||||
MmWithdrawSectionPage(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
BOOLEAN *Dirty);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmFinalizeSectionPageOut
|
||||
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, PFN_NUMBER Page,
|
||||
BOOLEAN Dirty);
|
||||
MmFinalizeSectionPageOut(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PFN_NUMBER Page,
|
||||
BOOLEAN Dirty);
|
||||
|
||||
/* sptab.c *******************************************************************/
|
||||
|
||||
|
@ -119,36 +122,43 @@ MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment);
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MmSetPageEntrySectionSegment
|
||||
(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Entry, const char *file, int line);
|
||||
_MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Entry,
|
||||
const char *file,
|
||||
int line);
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
_MmGetPageEntrySectionSegment
|
||||
(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset, const char *file, int line);
|
||||
_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
const char *file,
|
||||
int line);
|
||||
|
||||
#define MmSetPageEntrySectionSegment(S,O,E) _MmSetPageEntrySectionSegment(S,O,E,__FILE__,__LINE__)
|
||||
|
||||
#define MmGetPageEntrySectionSegment(S,O) _MmGetPageEntrySectionSegment(S,O,__FILE__,__LINE__)
|
||||
|
||||
typedef VOID (NTAPI *FREE_SECTION_PAGE_FUN)
|
||||
(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset);
|
||||
typedef VOID (NTAPI *FREE_SECTION_PAGE_FUN)(
|
||||
PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage);
|
||||
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
FREE_SECTION_PAGE_FUN FreePage);
|
||||
|
||||
/* Yields a lock */
|
||||
PMM_SECTION_SEGMENT
|
||||
NTAPI
|
||||
MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset);
|
||||
MmGetSectionAssociation(PFN_NUMBER Page,
|
||||
PLARGE_INTEGER Offset);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmSetSectionAssociation(PFN_NUMBER Page, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset);
|
||||
MmSetSectionAssociation(PFN_NUMBER Page,
|
||||
PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
|
@ -165,36 +175,33 @@ MmspWaitForFileLock(PFILE_OBJECT File);
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSimpleRead
|
||||
(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
BOOLEAN Paging,
|
||||
PIO_STATUS_BLOCK ReadStatus);
|
||||
MiSimpleRead(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
BOOLEAN Paging,
|
||||
PIO_STATUS_BLOCK ReadStatus);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiSimpleWrite
|
||||
(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PIO_STATUS_BLOCK ReadStatus,
|
||||
const char *file,
|
||||
int line);
|
||||
_MiSimpleWrite(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PVOID Buffer,
|
||||
ULONG Length,
|
||||
PIO_STATUS_BLOCK ReadStatus,
|
||||
const char *file,
|
||||
int line);
|
||||
|
||||
#define MiSimpleWrite(F,O,B,L,R) _MiSimpleWrite(F,O,B,L,R,__FILE__,__LINE__)
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiWriteBackPage
|
||||
(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Length,
|
||||
PFN_NUMBER Page,
|
||||
const char *File,
|
||||
int Line);
|
||||
_MiWriteBackPage(PFILE_OBJECT FileObject,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Length,
|
||||
PFN_NUMBER Page,
|
||||
const char *File,
|
||||
int Line);
|
||||
|
||||
#define MiWriteBackPage(F,O,L,P) _MiWriteBackPage(F,O,L,P,__FILE__,__LINE__)
|
||||
|
||||
|
@ -202,88 +209,96 @@ _MiWriteBackPage
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmAccessFaultCacheSection
|
||||
(KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl);
|
||||
MmAccessFaultCacheSection(KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiReadFilePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
MiReadFilePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiGetOnePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
MiGetOnePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSwapInPage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
MiSwapInPage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiWriteSwapPage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Resources);
|
||||
MiWriteSwapPage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Resources);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiWriteFilePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Resources);
|
||||
MiWriteFilePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Resources);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MiFreeSegmentPage
|
||||
(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER FileOffset);
|
||||
MiFreeSegmentPage(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER FileOffset);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiCowCacheSectionPage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID Address,
|
||||
BOOLEAN Locked,
|
||||
PMM_REQUIRED_RESOURCES Required);
|
||||
MiCowCacheSectionPage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID Address,
|
||||
BOOLEAN Locked,
|
||||
PMM_REQUIRED_RESOURCES Required);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiZeroFillSection(PVOID Address, PLARGE_INTEGER FileOffsetPtr, ULONG Length);
|
||||
MiZeroFillSection(PVOID Address,
|
||||
PLARGE_INTEGER FileOffsetPtr,
|
||||
ULONG Length);
|
||||
|
||||
VOID
|
||||
MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address);
|
||||
MmPageOutDeleteMapping(PVOID Context,
|
||||
PEPROCESS Process,
|
||||
PVOID Address);
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line);
|
||||
_MmLockSectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
const char *file,
|
||||
int line);
|
||||
|
||||
#define MmLockSectionSegment(x) _MmLockSectionSegment(x,__FILE__,__LINE__)
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment, const char *file, int line);
|
||||
_MmUnlockSectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
const char *file,
|
||||
int line);
|
||||
|
||||
#define MmUnlockSectionSegment(x) _MmUnlockSectionSegment(x,__FILE__,__LINE__)
|
||||
|
||||
VOID
|
||||
MmFreeCacheSectionPage
|
||||
(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
|
||||
PFN_NUMBER Page, SWAPENTRY SwapEntry, BOOLEAN Dirty);
|
||||
MmFreeCacheSectionPage(PVOID Context,
|
||||
MEMORY_AREA* MemoryArea,
|
||||
PVOID Address,
|
||||
PFN_NUMBER Page,
|
||||
SWAPENTRY SwapEntry,
|
||||
BOOLEAN Dirty);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN Dirty, const char *File, int Line);
|
||||
_MiFlushMappedSection(PVOID BaseAddress,
|
||||
PLARGE_INTEGER BaseOffset,
|
||||
PLARGE_INTEGER FileSize,
|
||||
BOOLEAN Dirty,
|
||||
const char *File,
|
||||
int Line);
|
||||
|
||||
#define MiFlushMappedSection(A,O,S,D) _MiFlushMappedSection(A,O,S,D,__FILE__,__LINE__)
|
||||
|
||||
|
@ -295,33 +310,32 @@ VOID
|
|||
NTAPI
|
||||
MmFreeSectionSegments(PFILE_OBJECT FileObject);
|
||||
|
||||
NTSTATUS NTAPI
|
||||
MmMapCacheViewInSystemSpaceAtOffset
|
||||
(IN PMM_SECTION_SEGMENT Segment,
|
||||
OUT PVOID * MappedBase,
|
||||
IN PLARGE_INTEGER ViewOffset,
|
||||
IN OUT PULONG ViewSize);
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmMapCacheViewInSystemSpaceAtOffset(IN PMM_SECTION_SEGMENT Segment,
|
||||
OUT PVOID* MappedBase,
|
||||
IN PLARGE_INTEGER ViewOffset,
|
||||
IN OUT PULONG ViewSize);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiMapViewOfSegment
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMM_SECTION_SEGMENT Segment,
|
||||
PVOID* BaseAddress,
|
||||
SIZE_T ViewSize,
|
||||
ULONG Protect,
|
||||
PLARGE_INTEGER ViewOffset,
|
||||
ULONG AllocationType,
|
||||
const char *file,
|
||||
int line);
|
||||
_MiMapViewOfSegment(PMMSUPPORT AddressSpace,
|
||||
PMM_SECTION_SEGMENT Segment,
|
||||
PVOID* BaseAddress,
|
||||
SIZE_T ViewSize,
|
||||
ULONG Protect,
|
||||
PLARGE_INTEGER ViewOffset,
|
||||
ULONG AllocationType,
|
||||
const char *file,
|
||||
int line);
|
||||
|
||||
#define MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType) _MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType,__FILE__,__LINE__)
|
||||
#define MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType) \
|
||||
_MiMapViewOfSegment(AddressSpace,Segment,BaseAddress,ViewSize,Protect,ViewOffset,AllocationType,__FILE__,__LINE__)
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmUnmapViewOfCacheSegment
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PVOID BaseAddress);
|
||||
MmUnmapViewOfCacheSegment(PMMSUPPORT AddressSpace,
|
||||
PVOID BaseAddress);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
|
@ -329,70 +343,78 @@ MmUnmapCacheViewInSystemSpace(PVOID Address);
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmNotPresentFaultCachePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID Address,
|
||||
BOOLEAN Locked,
|
||||
PMM_REQUIRED_RESOURCES Required);
|
||||
MmNotPresentFaultCachePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID Address,
|
||||
BOOLEAN Locked,
|
||||
PMM_REQUIRED_RESOURCES Required);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmPageOutPageFileView
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID Address,
|
||||
PMM_REQUIRED_RESOURCES Required);
|
||||
MmPageOutPageFileView(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PVOID Address,
|
||||
PMM_REQUIRED_RESOURCES Required);
|
||||
|
||||
FORCEINLINE
|
||||
BOOLEAN
|
||||
_MmTryToLockAddressSpace(IN PMMSUPPORT AddressSpace, const char *file, int line)
|
||||
_MmTryToLockAddressSpace(IN PMMSUPPORT AddressSpace,
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
BOOLEAN Result = KeTryToAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
|
||||
//DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line, AddressSpace, Result ? "true" : "false");
|
||||
return Result;
|
||||
BOOLEAN Result = KeTryToAcquireGuardedMutex(&CONTAINING_RECORD(AddressSpace, EPROCESS, Vm)->AddressCreationLock);
|
||||
//DbgPrint("(%s:%d) Try Lock Address Space %x -> %s\n", file, line, AddressSpace, Result ? "true" : "false");
|
||||
return Result;
|
||||
}
|
||||
|
||||
#define MmTryToLockAddressSpace(x) _MmTryToLockAddressSpace(x,__FILE__,__LINE__)
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiWidenSegment
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
MiWidenSegment(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSwapInSectionPage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
MiSwapInSectionPage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmExtendCacheSection(PROS_SECTION_OBJECT Section, PLARGE_INTEGER NewSize, BOOLEAN ExtendFile);
|
||||
MmExtendCacheSection(PROS_SECTION_OBJECT Section,
|
||||
PLARGE_INTEGER NewSize,
|
||||
BOOLEAN ExtendFile);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MiFlushMappedSection(PVOID BaseAddress, PLARGE_INTEGER BaseOffset, PLARGE_INTEGER FileSize, BOOLEAN Dirty, const char *File, int Line);
|
||||
_MiFlushMappedSection(PVOID BaseAddress,
|
||||
PLARGE_INTEGER BaseOffset,
|
||||
PLARGE_INTEGER FileSize,
|
||||
BOOLEAN Dirty,
|
||||
const char *File,
|
||||
int Line);
|
||||
|
||||
#define MiFlushMappedSection(A,O,S,D) _MiFlushMappedSection(A,O,S,D,__FILE__,__LINE__)
|
||||
|
||||
PVOID
|
||||
NTAPI
|
||||
MmGetSegmentRmap(PFN_NUMBER Page, PULONG RawOffset);
|
||||
MmGetSegmentRmap(PFN_NUMBER Page,
|
||||
PULONG RawOffset);
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmNotPresentFaultCacheSection
|
||||
(KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl);
|
||||
MmNotPresentFaultCacheSection(KPROCESSOR_MODE Mode,
|
||||
ULONG_PTR Address,
|
||||
BOOLEAN FromMdl);
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment, ULONG Target);
|
||||
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment,
|
||||
ULONG Target);
|
||||
|
||||
NTSTATUS
|
||||
MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed);
|
||||
MiRosTrimCache(ULONG Target,
|
||||
ULONG Priority,
|
||||
PULONG NrFreed);
|
||||
|
|
189
reactos/ntoskrnl/cache/section/reqtools.c
vendored
189
reactos/ntoskrnl/cache/section/reqtools.c
vendored
|
@ -57,74 +57,73 @@ MmBuildMdlFromPages(PMDL Mdl, PPFN_NUMBER Pages);
|
|||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiGetOnePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Required)
|
||||
MiGetOnePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Required)
|
||||
{
|
||||
int i;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
int i;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
|
||||
for (i = 0; i < Required->Amount; i++)
|
||||
{
|
||||
DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line);
|
||||
Status = MmRequestPageMemoryConsumer(Required->Consumer, TRUE, &Required->Page[i]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
while (i > 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(Required->Consumer, Required->Page[i-1]);
|
||||
i--;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
for (i = 0; i < Required->Amount; i++)
|
||||
{
|
||||
DPRINTC("MiGetOnePage(%s:%d)\n", Required->File, Required->Line);
|
||||
Status = MmRequestPageMemoryConsumer(Required->Consumer,
|
||||
TRUE,
|
||||
&Required->Page[i]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
while (i > 0)
|
||||
{
|
||||
MmReleasePageMemoryConsumer(Required->Consumer,
|
||||
Required->Page[i-1]);
|
||||
i--;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiReadFilePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources)
|
||||
MiReadFilePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES RequiredResources)
|
||||
{
|
||||
PFILE_OBJECT FileObject = RequiredResources->Context;
|
||||
PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
|
||||
PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
|
||||
NTSTATUS Status;
|
||||
PFILE_OBJECT FileObject = RequiredResources->Context;
|
||||
PPFN_NUMBER Page = &RequiredResources->Page[RequiredResources->Offset];
|
||||
PLARGE_INTEGER FileOffset = &RequiredResources->FileOffset;
|
||||
NTSTATUS Status;
|
||||
PVOID PageBuf = NULL;
|
||||
KEVENT Event;
|
||||
IO_STATUS_BLOCK IOSB;
|
||||
IO_STATUS_BLOCK IOSB;
|
||||
UCHAR MdlBase[sizeof(MDL) + sizeof(ULONG)];
|
||||
PMDL Mdl = (PMDL)MdlBase;
|
||||
KIRQL OldIrql;
|
||||
|
||||
DPRINTC
|
||||
("Pulling page %08x%08x from %wZ to %x\n",
|
||||
FileOffset->u.HighPart, FileOffset->u.LowPart,
|
||||
&FileObject->FileName,
|
||||
Page);
|
||||
DPRINTC("Pulling page %08x%08x from %wZ to %x\n",
|
||||
FileOffset->u.HighPart,
|
||||
FileOffset->u.LowPart,
|
||||
&FileObject->FileName,
|
||||
Page);
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer, TRUE, Page);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Status: %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
Status = MmRequestPageMemoryConsumer(RequiredResources->Consumer,
|
||||
TRUE,
|
||||
Page);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("Status: %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
MmInitializeMdl(Mdl, NULL, PAGE_SIZE);
|
||||
MmBuildMdlFromPages(Mdl, Page);
|
||||
Mdl->MdlFlags |= MDL_PAGES_LOCKED;
|
||||
|
||||
|
||||
KeInitializeEvent(&Event, NotificationEvent, FALSE);
|
||||
Status = IoPageRead
|
||||
(FileObject,
|
||||
Mdl,
|
||||
FileOffset,
|
||||
&Event,
|
||||
&IOSB);
|
||||
Status = IoPageRead(FileObject, Mdl, FileOffset, &Event, &IOSB);
|
||||
if (Status == STATUS_PENDING)
|
||||
{
|
||||
KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
|
||||
|
@ -141,65 +140,71 @@ MiReadFilePage
|
|||
MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
|
||||
return STATUS_NO_MEMORY;
|
||||
}
|
||||
RtlZeroMemory
|
||||
((PCHAR)PageBuf+RequiredResources->Amount,
|
||||
PAGE_SIZE-RequiredResources->Amount);
|
||||
|
||||
RtlZeroMemory((PCHAR)PageBuf+RequiredResources->Amount,
|
||||
PAGE_SIZE-RequiredResources->Amount);
|
||||
|
||||
MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf, OldIrql);
|
||||
|
||||
DPRINT("Read Status %x (Page %x)\n", Status, *Page);
|
||||
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
|
||||
DPRINT("Status: %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
DPRINT("Read Status %x (Page %x)\n", Status, *Page);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
MmReleasePageMemoryConsumer(RequiredResources->Consumer, *Page);
|
||||
DPRINT("Status: %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiSwapInPage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Resources)
|
||||
MiSwapInPage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Resources)
|
||||
{
|
||||
NTSTATUS Status;
|
||||
NTSTATUS Status;
|
||||
|
||||
Status = MmRequestPageMemoryConsumer(Resources->Consumer, TRUE, &Resources->Page[Resources->Offset]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = MmReadFromSwapPage(Resources->SwapEntry, Resources->Page[Resources->Offset]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
Status = MmRequestPageMemoryConsumer(Resources->Consumer,
|
||||
TRUE,
|
||||
&Resources->Page[Resources->Offset]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset], Resources->SwapEntry);
|
||||
Status = MmReadFromSwapPage(Resources->SwapEntry,
|
||||
Resources->Page[Resources->Offset]);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
DPRINT1("MiSwapInPage(%x,%x)\n", Resources->Page[Resources->Offset], Resources->SwapEntry);
|
||||
MmSetSavedSwapEntryPage(Resources->Page[Resources->Offset],
|
||||
Resources->SwapEntry);
|
||||
|
||||
return Status;
|
||||
DPRINT1("MiSwapInPage(%x,%x)\n",
|
||||
Resources->Page[Resources->Offset],
|
||||
Resources->SwapEntry);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MiWriteFilePage
|
||||
(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Required)
|
||||
MiWriteFilePage(PMMSUPPORT AddressSpace,
|
||||
PMEMORY_AREA MemoryArea,
|
||||
PMM_REQUIRED_RESOURCES Required)
|
||||
{
|
||||
DPRINT1("MiWriteFilePage(%x,%x)\n", Required->Page[Required->Offset], Required->FileOffset.LowPart);
|
||||
DPRINT1("MiWriteFilePage(%x,%x)\n",
|
||||
Required->Page[Required->Offset],
|
||||
Required->FileOffset.LowPart);
|
||||
|
||||
return MiWriteBackPage
|
||||
(Required->Context,
|
||||
&Required->FileOffset,
|
||||
PAGE_SIZE,
|
||||
Required->Page[Required->Offset]);
|
||||
return MiWriteBackPage(Required->Context,
|
||||
&Required->FileOffset,
|
||||
PAGE_SIZE,
|
||||
Required->Page[Required->Offset]);
|
||||
}
|
||||
|
|
276
reactos/ntoskrnl/cache/section/sptab.c
vendored
276
reactos/ntoskrnl/cache/section/sptab.c
vendored
|
@ -59,10 +59,12 @@ MiSectionPageTableFree(PRTL_GENERIC_TABLE Table, PVOID Data)
|
|||
static
|
||||
RTL_GENERIC_COMPARE_RESULTS
|
||||
NTAPI
|
||||
MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
|
||||
MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table,
|
||||
PVOID PtrA,
|
||||
PVOID PtrB)
|
||||
{
|
||||
PLARGE_INTEGER A = PtrA, B = PtrB;
|
||||
BOOLEAN Result = (A->QuadPart < B->QuadPart) ? GenericLessThan :
|
||||
BOOLEAN Result = (A->QuadPart < B->QuadPart) ? GenericLessThan :
|
||||
(A->QuadPart == B->QuadPart) ? GenericEqual : GenericGreaterThan;
|
||||
|
||||
#if 0
|
||||
|
@ -71,7 +73,7 @@ MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
|
|||
A->u.HighPart, A->u.LowPart,
|
||||
B->u.HighPart, B->u.LowPart,
|
||||
Result == GenericLessThan ? "GenericLessThan" :
|
||||
Result == GenericGreaterThan ? "GenericGreaterThan" :
|
||||
Result == GenericGreaterThan ? "GenericGreaterThan" :
|
||||
"GenericEqual");
|
||||
#endif
|
||||
|
||||
|
@ -81,48 +83,50 @@ MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
|
|||
static
|
||||
PCACHE_SECTION_PAGE_TABLE
|
||||
NTAPI
|
||||
MiSectionPageTableGet
|
||||
(PRTL_GENERIC_TABLE Table,
|
||||
PLARGE_INTEGER FileOffset)
|
||||
MiSectionPageTableGet(PRTL_GENERIC_TABLE Table,
|
||||
PLARGE_INTEGER FileOffset)
|
||||
{
|
||||
LARGE_INTEGER SearchFileOffset;
|
||||
PCACHE_SECTION_PAGE_TABLE PageTable;
|
||||
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
|
||||
PCACHE_SECTION_PAGE_TABLE PageTable;
|
||||
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart,
|
||||
ENTRIES_PER_ELEMENT * PAGE_SIZE);
|
||||
PageTable = RtlLookupElementGenericTable(Table, &SearchFileOffset);
|
||||
DPRINT
|
||||
("MiSectionPageTableGet(%08x,%08x%08x)\n",
|
||||
Table,
|
||||
FileOffset->HighPart,
|
||||
FileOffset->LowPart);
|
||||
return PageTable;
|
||||
|
||||
DPRINT("MiSectionPageTableGet(%08x,%08x%08x)\n",
|
||||
Table,
|
||||
FileOffset->HighPart,
|
||||
FileOffset->LowPart);
|
||||
|
||||
return PageTable;
|
||||
}
|
||||
|
||||
static
|
||||
PCACHE_SECTION_PAGE_TABLE
|
||||
NTAPI
|
||||
MiSectionPageTableGetOrAllocate
|
||||
(PRTL_GENERIC_TABLE Table,
|
||||
PLARGE_INTEGER FileOffset)
|
||||
MiSectionPageTableGetOrAllocate(PRTL_GENERIC_TABLE Table,
|
||||
PLARGE_INTEGER FileOffset)
|
||||
{
|
||||
LARGE_INTEGER SearchFileOffset;
|
||||
CACHE_SECTION_PAGE_TABLE SectionZeroPageTable;
|
||||
PCACHE_SECTION_PAGE_TABLE PageTableSlice =
|
||||
MiSectionPageTableGet(Table, FileOffset);
|
||||
// Please zero memory when taking away zero initialization.
|
||||
PCACHE_SECTION_PAGE_TABLE PageTableSlice = MiSectionPageTableGet(Table,
|
||||
FileOffset);
|
||||
/* Please zero memory when taking away zero initialization. */
|
||||
RtlZeroMemory(&SectionZeroPageTable, sizeof(CACHE_SECTION_PAGE_TABLE));
|
||||
if (!PageTableSlice)
|
||||
{
|
||||
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
|
||||
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart,
|
||||
ENTRIES_PER_ELEMENT * PAGE_SIZE);
|
||||
SectionZeroPageTable.FileOffset = SearchFileOffset;
|
||||
SectionZeroPageTable.Refcount = 1;
|
||||
PageTableSlice = RtlInsertElementGenericTable
|
||||
(Table, &SectionZeroPageTable, sizeof(SectionZeroPageTable), NULL);
|
||||
PageTableSlice = RtlInsertElementGenericTable(Table,
|
||||
&SectionZeroPageTable,
|
||||
sizeof(SectionZeroPageTable),
|
||||
NULL);
|
||||
if (!PageTableSlice) return NULL;
|
||||
DPRINT
|
||||
("Allocate page table %x (%08x%08x)\n",
|
||||
PageTableSlice,
|
||||
PageTableSlice->FileOffset.u.HighPart,
|
||||
PageTableSlice->FileOffset.u.LowPart);
|
||||
DPRINT("Allocate page table %x (%08x%08x)\n",
|
||||
PageTableSlice,
|
||||
PageTableSlice->FileOffset.u.HighPart,
|
||||
PageTableSlice->FileOffset.u.LowPart);
|
||||
}
|
||||
return PageTableSlice;
|
||||
}
|
||||
|
@ -131,159 +135,179 @@ VOID
|
|||
NTAPI
|
||||
MiInitializeSectionPageTable(PMM_SECTION_SEGMENT Segment)
|
||||
{
|
||||
RtlInitializeGenericTable
|
||||
(&Segment->PageTable,
|
||||
MiSectionPageTableCompare,
|
||||
MiSectionPageTableAllocate,
|
||||
MiSectionPageTableFree,
|
||||
NULL);
|
||||
RtlInitializeGenericTable(&Segment->PageTable,
|
||||
MiSectionPageTableCompare,
|
||||
MiSectionPageTableAllocate,
|
||||
MiSectionPageTableFree,
|
||||
NULL);
|
||||
|
||||
DPRINT("MiInitializeSectionPageTable(%p)\n", &Segment->PageTable);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
_MmSetPageEntrySectionSegment
|
||||
(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Entry,
|
||||
const char *file,
|
||||
int line)
|
||||
_MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
ULONG Entry,
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
ULONG PageIndex, OldEntry;
|
||||
PCACHE_SECTION_PAGE_TABLE PageTable;
|
||||
ASSERT(Segment->Locked);
|
||||
|
||||
ASSERT(Segment->Locked);
|
||||
ASSERT(!IS_SWAP_FROM_SSE(Entry) || !IS_DIRTY_SSE(Entry));
|
||||
if (Entry && !IS_SWAP_FROM_SSE(Entry))
|
||||
MmGetRmapListHeadPage(PFN_FROM_SSE(Entry));
|
||||
PageTable =
|
||||
MiSectionPageTableGetOrAllocate(&Segment->PageTable, Offset);
|
||||
|
||||
if (Entry && !IS_SWAP_FROM_SSE(Entry))
|
||||
MmGetRmapListHeadPage(PFN_FROM_SSE(Entry));
|
||||
|
||||
PageTable = MiSectionPageTableGetOrAllocate(&Segment->PageTable, Offset);
|
||||
|
||||
if (!PageTable) return STATUS_NO_MEMORY;
|
||||
ASSERT(MiSectionPageTableGet(&Segment->PageTable, Offset));
|
||||
PageTable->Segment = Segment;
|
||||
PageIndex =
|
||||
(Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
|
||||
OldEntry = PageTable->PageEntries[PageIndex];
|
||||
DPRINT("MiSetPageEntrySectionSegment(%p,%08x%08x,%x=>%x)\n",
|
||||
Segment, Offset->u.HighPart, Offset->u.LowPart, OldEntry, Entry);
|
||||
if (PFN_FROM_SSE(Entry) == PFN_FROM_SSE(OldEntry)) {
|
||||
// Nothing
|
||||
} else if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
|
||||
ASSERT(!OldEntry || IS_SWAP_FROM_SSE(OldEntry));
|
||||
MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
|
||||
} else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) {
|
||||
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
|
||||
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
||||
} else if (IS_SWAP_FROM_SSE(Entry)) {
|
||||
ASSERT(!IS_SWAP_FROM_SSE(OldEntry));
|
||||
if (OldEntry)
|
||||
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
||||
} else if (IS_SWAP_FROM_SSE(OldEntry)) {
|
||||
ASSERT(!IS_SWAP_FROM_SSE(Entry));
|
||||
if (Entry)
|
||||
MmSetSectionAssociation(PFN_FROM_SSE(OldEntry), Segment, Offset);
|
||||
} else {
|
||||
// We should not be replacing a page like this
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
|
||||
ASSERT(MiSectionPageTableGet(&Segment->PageTable, Offset));
|
||||
|
||||
PageTable->Segment = Segment;
|
||||
PageIndex = (Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
|
||||
OldEntry = PageTable->PageEntries[PageIndex];
|
||||
|
||||
DPRINT("MiSetPageEntrySectionSegment(%p,%08x%08x,%x=>%x)\n",
|
||||
Segment,
|
||||
Offset->u.HighPart,
|
||||
Offset->u.LowPart,
|
||||
OldEntry,
|
||||
Entry);
|
||||
|
||||
if (PFN_FROM_SSE(Entry) == PFN_FROM_SSE(OldEntry)) {
|
||||
/* Nothing */
|
||||
} else if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
|
||||
ASSERT(!OldEntry || IS_SWAP_FROM_SSE(OldEntry));
|
||||
MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
|
||||
} else if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) {
|
||||
ASSERT(!Entry || IS_SWAP_FROM_SSE(Entry));
|
||||
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
||||
} else if (IS_SWAP_FROM_SSE(Entry)) {
|
||||
ASSERT(!IS_SWAP_FROM_SSE(OldEntry));
|
||||
if (OldEntry)
|
||||
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
|
||||
} else if (IS_SWAP_FROM_SSE(OldEntry)) {
|
||||
ASSERT(!IS_SWAP_FROM_SSE(Entry));
|
||||
if (Entry)
|
||||
MmSetSectionAssociation(PFN_FROM_SSE(OldEntry), Segment, Offset);
|
||||
} else {
|
||||
/* We should not be replacing a page like this */
|
||||
ASSERT(FALSE);
|
||||
}
|
||||
PageTable->PageEntries[PageIndex] = Entry;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
_MmGetPageEntrySectionSegment
|
||||
(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
const char *file,
|
||||
int line)
|
||||
_MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset,
|
||||
const char *file,
|
||||
int line)
|
||||
{
|
||||
LARGE_INTEGER FileOffset;
|
||||
ULONG PageIndex, Result;
|
||||
PCACHE_SECTION_PAGE_TABLE PageTable;
|
||||
|
||||
ASSERT(Segment->Locked);
|
||||
FileOffset.QuadPart =
|
||||
ROUND_DOWN(Offset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
|
||||
FileOffset.QuadPart = ROUND_DOWN(Offset->QuadPart,
|
||||
ENTRIES_PER_ELEMENT * PAGE_SIZE);
|
||||
PageTable = MiSectionPageTableGet(&Segment->PageTable, &FileOffset);
|
||||
if (!PageTable) return 0;
|
||||
PageIndex =
|
||||
(Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
|
||||
PageIndex = (Offset->QuadPart - PageTable->FileOffset.QuadPart) / PAGE_SIZE;
|
||||
Result = PageTable->PageEntries[PageIndex];
|
||||
#if 0
|
||||
DPRINTC
|
||||
("MiGetPageEntrySectionSegment(%p,%08x%08x) => %x %s:%d\n",
|
||||
Segment,
|
||||
FileOffset.u.HighPart,
|
||||
FileOffset.u.HighPart,
|
||||
FileOffset.u.LowPart + PageIndex * PAGE_SIZE,
|
||||
Result,
|
||||
file, line);
|
||||
file, line);
|
||||
#endif
|
||||
return Result;
|
||||
}
|
||||
|
||||
VOID
|
||||
NTAPI
|
||||
MmFreePageTablesSectionSegment
|
||||
(PMM_SECTION_SEGMENT Segment, FREE_SECTION_PAGE_FUN FreePage)
|
||||
MmFreePageTablesSectionSegment(PMM_SECTION_SEGMENT Segment,
|
||||
FREE_SECTION_PAGE_FUN FreePage)
|
||||
{
|
||||
PCACHE_SECTION_PAGE_TABLE Element;
|
||||
DPRINT("MiFreePageTablesSectionSegment(%p)\n", &Segment->PageTable);
|
||||
while ((Element = RtlGetElementGenericTable(&Segment->PageTable, 0))) {
|
||||
DPRINT
|
||||
("Delete table for <%wZ> %x -> %08x%08x\n",
|
||||
Segment->FileObject ? &Segment->FileObject->FileName : NULL,
|
||||
Segment,
|
||||
Element->FileOffset.u.HighPart,
|
||||
Element->FileOffset.u.LowPart);
|
||||
if (FreePage)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ENTRIES_PER_ELEMENT; i++)
|
||||
{
|
||||
ULONG Entry;
|
||||
LARGE_INTEGER Offset;
|
||||
Offset.QuadPart = Element->FileOffset.QuadPart + i * PAGE_SIZE;
|
||||
Entry = Element->PageEntries[i];
|
||||
if (Entry && !IS_SWAP_FROM_SSE(Entry))
|
||||
{
|
||||
DPRINT("Freeing page %x:%x @ %x\n", Segment, Entry, Offset.LowPart);
|
||||
FreePage(Segment, &Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINT("Remove memory\n");
|
||||
DPRINT("Delete table for <%wZ> %x -> %08x%08x\n",
|
||||
Segment->FileObject ? &Segment->FileObject->FileName : NULL,
|
||||
Segment,
|
||||
Element->FileOffset.u.HighPart,
|
||||
Element->FileOffset.u.LowPart);
|
||||
if (FreePage)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < ENTRIES_PER_ELEMENT; i++)
|
||||
{
|
||||
ULONG Entry;
|
||||
LARGE_INTEGER Offset;
|
||||
Offset.QuadPart = Element->FileOffset.QuadPart + i * PAGE_SIZE;
|
||||
Entry = Element->PageEntries[i];
|
||||
if (Entry && !IS_SWAP_FROM_SSE(Entry))
|
||||
{
|
||||
DPRINT("Freeing page %x:%x @ %x\n",
|
||||
Segment,
|
||||
Entry,
|
||||
Offset.LowPart);
|
||||
|
||||
FreePage(Segment, &Offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
DPRINT("Remove memory\n");
|
||||
RtlDeleteElementGenericTable(&Segment->PageTable, Element);
|
||||
}
|
||||
DPRINT("Done\n");
|
||||
DPRINT("Done\n");
|
||||
}
|
||||
|
||||
PMM_SECTION_SEGMENT
|
||||
NTAPI
|
||||
MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset)
|
||||
MmGetSectionAssociation(PFN_NUMBER Page,
|
||||
PLARGE_INTEGER Offset)
|
||||
{
|
||||
ULONG RawOffset;
|
||||
ULONG RawOffset;
|
||||
PMM_SECTION_SEGMENT Segment = NULL;
|
||||
PCACHE_SECTION_PAGE_TABLE PageTable;
|
||||
|
||||
PageTable = (PCACHE_SECTION_PAGE_TABLE)MmGetSegmentRmap(Page, &RawOffset);
|
||||
if (PageTable)
|
||||
{
|
||||
Segment = PageTable->Segment;
|
||||
Offset->QuadPart = PageTable->FileOffset.QuadPart + (RawOffset << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
return(Segment);
|
||||
PageTable = (PCACHE_SECTION_PAGE_TABLE)MmGetSegmentRmap(Page,
|
||||
&RawOffset);
|
||||
if (PageTable)
|
||||
{
|
||||
Segment = PageTable->Segment;
|
||||
Offset->QuadPart = PageTable->FileOffset.QuadPart +
|
||||
(RawOffset << PAGE_SHIFT);
|
||||
}
|
||||
|
||||
return Segment;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmSetSectionAssociation(PFN_NUMBER Page, PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER Offset)
|
||||
MmSetSectionAssociation(PFN_NUMBER Page,
|
||||
PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER Offset)
|
||||
{
|
||||
PCACHE_SECTION_PAGE_TABLE PageTable;
|
||||
ULONG ActualOffset;
|
||||
PageTable = MiSectionPageTableGet(&Segment->PageTable, Offset);
|
||||
ASSERT(PageTable);
|
||||
ActualOffset = (ULONG)(Offset->QuadPart - PageTable->FileOffset.QuadPart);
|
||||
MmInsertRmap(Page, (PEPROCESS)PageTable, (PVOID)(RMAP_SEGMENT_MASK | (ActualOffset >> PAGE_SHIFT)));
|
||||
return STATUS_SUCCESS;
|
||||
ULONG ActualOffset;
|
||||
|
||||
PageTable = MiSectionPageTableGet(&Segment->PageTable, Offset);
|
||||
ASSERT(PageTable);
|
||||
|
||||
ActualOffset = (ULONG)(Offset->QuadPart - PageTable->FileOffset.QuadPart);
|
||||
MmInsertRmap(Page,
|
||||
(PEPROCESS)PageTable,
|
||||
(PVOID)(RMAP_SEGMENT_MASK | (ActualOffset >> PAGE_SHIFT)));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
|
736
reactos/ntoskrnl/cache/section/swapout.c
vendored
736
reactos/ntoskrnl/cache/section/swapout.c
vendored
|
@ -60,424 +60,498 @@ FAST_MUTEX MiGlobalPageOperation;
|
|||
|
||||
PFN_NUMBER
|
||||
NTAPI
|
||||
MmWithdrawSectionPage
|
||||
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, BOOLEAN *Dirty)
|
||||
MmWithdrawSectionPage(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
BOOLEAN *Dirty)
|
||||
{
|
||||
ULONG Entry;
|
||||
ULONG Entry;
|
||||
|
||||
DPRINT("MmWithdrawSectionPage(%x,%08x%08x,%x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart, Dirty);
|
||||
DPRINT("MmWithdrawSectionPage(%x,%08x%08x,%x)\n",
|
||||
Segment,
|
||||
FileOffset->HighPart,
|
||||
FileOffset->LowPart,
|
||||
Dirty);
|
||||
|
||||
MmLockSectionSegment(Segment);
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, FileOffset);
|
||||
MmLockSectionSegment(Segment);
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, FileOffset);
|
||||
|
||||
*Dirty = !!IS_DIRTY_SSE(Entry);
|
||||
*Dirty = !!IS_DIRTY_SSE(Entry);
|
||||
|
||||
DPRINT("Withdraw %x (%x) of %wZ\n", FileOffset->LowPart, Entry, Segment->FileObject ? &Segment->FileObject->FileName : NULL);
|
||||
DPRINT("Withdraw %x (%x) of %wZ\n",
|
||||
FileOffset->LowPart,
|
||||
Entry,
|
||||
Segment->FileObject ? &Segment->FileObject->FileName : NULL);
|
||||
|
||||
if (!Entry)
|
||||
{
|
||||
DPRINT("Stoeled!\n");
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return 0;
|
||||
}
|
||||
else if (MM_IS_WAIT_PTE(Entry))
|
||||
{
|
||||
DPRINT("WAIT\n");
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return MM_WAIT_ENTRY;
|
||||
}
|
||||
else if (Entry && !IS_SWAP_FROM_SSE(Entry))
|
||||
{
|
||||
DPRINT("Page %x\n", PFN_FROM_SSE(Entry));
|
||||
*Dirty |= (Entry & 2);
|
||||
MmSetPageEntrySectionSegment(Segment, FileOffset, MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return PFN_FROM_SSE(Entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("SWAP ENTRY?! (%x:%08x%08x)\n", Segment, FileOffset->HighPart, FileOffset->LowPart);
|
||||
ASSERT(FALSE);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return 0;
|
||||
}
|
||||
if (!Entry)
|
||||
{
|
||||
DPRINT("Stoeled!\n");
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return 0;
|
||||
}
|
||||
else if (MM_IS_WAIT_PTE(Entry))
|
||||
{
|
||||
DPRINT("WAIT\n");
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return MM_WAIT_ENTRY;
|
||||
}
|
||||
else if (Entry && !IS_SWAP_FROM_SSE(Entry))
|
||||
{
|
||||
DPRINT("Page %x\n", PFN_FROM_SSE(Entry));
|
||||
|
||||
*Dirty |= (Entry & 2);
|
||||
|
||||
MmSetPageEntrySectionSegment(Segment,
|
||||
FileOffset,
|
||||
MAKE_SWAP_SSE(MM_WAIT_ENTRY));
|
||||
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return PFN_FROM_SSE(Entry);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT1("SWAP ENTRY?! (%x:%08x%08x)\n",
|
||||
Segment,
|
||||
FileOffset->HighPart,
|
||||
FileOffset->LowPart);
|
||||
|
||||
ASSERT(FALSE);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmFinalizeSectionPageOut
|
||||
(PMM_SECTION_SEGMENT Segment, PLARGE_INTEGER FileOffset, PFN_NUMBER Page,
|
||||
BOOLEAN Dirty)
|
||||
MmFinalizeSectionPageOut(PMM_SECTION_SEGMENT Segment,
|
||||
PLARGE_INTEGER FileOffset,
|
||||
PFN_NUMBER Page,
|
||||
BOOLEAN Dirty)
|
||||
{
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN WriteZero = FALSE, WritePage = FALSE;
|
||||
SWAPENTRY Swap = MmGetSavedSwapEntryPage(Page);
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
BOOLEAN WriteZero = FALSE, WritePage = FALSE;
|
||||
SWAPENTRY Swap = MmGetSavedSwapEntryPage(Page);
|
||||
|
||||
/* Bail early if the reference count isn't where we need it */
|
||||
if (MmGetReferenceCountPage(Page) != 1)
|
||||
{
|
||||
DPRINT1("Cannot page out locked page %x with ref count %d\n", Page, MmGetReferenceCountPage(Page));
|
||||
DPRINT1("Cannot page out locked page %x with ref count %d\n",
|
||||
Page,
|
||||
MmGetReferenceCountPage(Page));
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MmLockSectionSegment(Segment);
|
||||
(void)InterlockedIncrementUL(&Segment->ReferenceCount);
|
||||
MmLockSectionSegment(Segment);
|
||||
(void)InterlockedIncrementUL(&Segment->ReferenceCount);
|
||||
|
||||
if (Dirty)
|
||||
{
|
||||
DPRINT("Finalize (dirty) Segment %x Page %x\n", Segment, Page);
|
||||
DPRINT("Segment->FileObject %x\n", Segment->FileObject);
|
||||
DPRINT("Segment->Flags %x\n", Segment->Flags);
|
||||
if (Dirty)
|
||||
{
|
||||
DPRINT("Finalize (dirty) Segment %x Page %x\n", Segment, Page);
|
||||
DPRINT("Segment->FileObject %x\n", Segment->FileObject);
|
||||
DPRINT("Segment->Flags %x\n", Segment->Flags);
|
||||
|
||||
WriteZero = TRUE;
|
||||
WritePage = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteZero = TRUE;
|
||||
}
|
||||
WriteZero = TRUE;
|
||||
WritePage = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteZero = TRUE;
|
||||
}
|
||||
|
||||
DPRINT("Status %x\n", Status);
|
||||
DPRINT("Status %x\n", Status);
|
||||
|
||||
MmUnlockSectionSegment(Segment);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
|
||||
if (WritePage)
|
||||
{
|
||||
DPRINT("MiWriteBackPage(Segment %x FileObject %x Offset %x)\n", Segment, Segment->FileObject, FileOffset->LowPart);
|
||||
Status = MiWriteBackPage(Segment->FileObject, FileOffset, PAGE_SIZE, Page);
|
||||
}
|
||||
if (WritePage)
|
||||
{
|
||||
DPRINT("MiWriteBackPage(Segment %x FileObject %x Offset %x)\n",
|
||||
Segment,
|
||||
Segment->FileObject,
|
||||
FileOffset->LowPart);
|
||||
|
||||
MmLockSectionSegment(Segment);
|
||||
Status = MiWriteBackPage(Segment->FileObject,
|
||||
FileOffset,
|
||||
PAGE_SIZE,
|
||||
Page);
|
||||
}
|
||||
|
||||
if (WriteZero && NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Setting page entry in segment %x:%x to swap %x\n", Segment, FileOffset->LowPart, Swap);
|
||||
MmSetPageEntrySectionSegment(Segment, FileOffset, Swap ? MAKE_SWAP_SSE(Swap) : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Setting page entry in segment %x:%x to page %x\n", Segment, FileOffset->LowPart, Page);
|
||||
MmSetPageEntrySectionSegment
|
||||
(Segment, FileOffset, Page ? (Dirty ? DIRTY_SSE(MAKE_PFN_SSE(Page)) : MAKE_PFN_SSE(Page)) : 0);
|
||||
}
|
||||
MmLockSectionSegment(Segment);
|
||||
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Removing page %x for real\n", Page);
|
||||
MmSetSavedSwapEntryPage(Page, 0);
|
||||
MmReleasePageMemoryConsumer(MC_CACHE, Page);
|
||||
}
|
||||
if (WriteZero && NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Setting page entry in segment %x:%x to swap %x\n",
|
||||
Segment,
|
||||
FileOffset->LowPart,
|
||||
Swap);
|
||||
|
||||
MmUnlockSectionSegment(Segment);
|
||||
MmSetPageEntrySectionSegment(Segment,
|
||||
FileOffset,
|
||||
Swap ? MAKE_SWAP_SSE(Swap) : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("Setting page entry in segment %x:%x to page %x\n",
|
||||
Segment,
|
||||
FileOffset->LowPart,
|
||||
Page);
|
||||
|
||||
if (InterlockedDecrementUL(&Segment->ReferenceCount) == 0)
|
||||
{
|
||||
MmFinalizeSegment(Segment);
|
||||
}
|
||||
MmSetPageEntrySectionSegment(Segment,
|
||||
FileOffset,
|
||||
Page ? (Dirty ? DIRTY_SSE(MAKE_PFN_SSE(Page)) : MAKE_PFN_SSE(Page)) : 0);
|
||||
}
|
||||
|
||||
/* Note: Writing may evict the segment... Nothing is guaranteed from here down */
|
||||
MiSetPageEvent(Segment, FileOffset->LowPart);
|
||||
if (NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("Removing page %x for real\n", Page);
|
||||
MmSetSavedSwapEntryPage(Page, 0);
|
||||
MmReleasePageMemoryConsumer(MC_CACHE, Page);
|
||||
}
|
||||
|
||||
DPRINT("Status %x\n", Status);
|
||||
return Status;
|
||||
MmUnlockSectionSegment(Segment);
|
||||
|
||||
if (InterlockedDecrementUL(&Segment->ReferenceCount) == 0)
|
||||
{
|
||||
MmFinalizeSegment(Segment);
|
||||
}
|
||||
|
||||
/* Note: Writing may evict the segment... Nothing is guaranteed from here down */
|
||||
MiSetPageEvent(Segment, FileOffset->LowPart);
|
||||
|
||||
DPRINT("Status %x\n", Status);
|
||||
return Status;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmPageOutCacheSection
|
||||
(PMMSUPPORT AddressSpace,
|
||||
MEMORY_AREA* MemoryArea,
|
||||
PVOID Address,
|
||||
PBOOLEAN Dirty,
|
||||
PMM_REQUIRED_RESOURCES Required)
|
||||
MmPageOutCacheSection(PMMSUPPORT AddressSpace,
|
||||
MEMORY_AREA* MemoryArea,
|
||||
PVOID Address,
|
||||
PBOOLEAN Dirty,
|
||||
PMM_REQUIRED_RESOURCES Required)
|
||||
{
|
||||
ULONG Entry;
|
||||
ULONG Entry;
|
||||
PFN_NUMBER OurPage;
|
||||
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
||||
LARGE_INTEGER TotalOffset;
|
||||
PMM_SECTION_SEGMENT Segment;
|
||||
PVOID PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
|
||||
PEPROCESS Process = MmGetAddressSpaceOwner(AddressSpace);
|
||||
LARGE_INTEGER TotalOffset;
|
||||
PMM_SECTION_SEGMENT Segment;
|
||||
PVOID PAddress = MM_ROUND_DOWN(Address, PAGE_SIZE);
|
||||
|
||||
TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress +
|
||||
MemoryArea->Data.SectionData.ViewOffset.QuadPart;
|
||||
TotalOffset.QuadPart = (ULONG_PTR)PAddress - (ULONG_PTR)MemoryArea->StartingAddress +
|
||||
MemoryArea->Data.SectionData.ViewOffset.QuadPart;
|
||||
|
||||
Segment = MemoryArea->Data.SectionData.Segment;
|
||||
Segment = MemoryArea->Data.SectionData.Segment;
|
||||
|
||||
MmLockSectionSegment(Segment);
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
MmLockSectionSegment(Segment);
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, &TotalOffset);
|
||||
|
||||
if (MmIsPageSwapEntry(Process, PAddress))
|
||||
{
|
||||
if (MmIsPageSwapEntry(Process, PAddress))
|
||||
{
|
||||
SWAPENTRY SwapEntry;
|
||||
MmGetPageFileMapping(Process, PAddress, &SwapEntry);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return SwapEntry == MM_WAIT_ENTRY ? STATUS_SUCCESS + 1 : STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
MmUnlockSectionSegment(Segment);
|
||||
return SwapEntry == MM_WAIT_ENTRY ? STATUS_SUCCESS + 1 : STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
MmDeleteRmap(Required->Page[0], Process, Address);
|
||||
MmDeleteVirtualMapping(Process, Address, FALSE, Dirty, &OurPage);
|
||||
ASSERT(OurPage == Required->Page[0]);
|
||||
|
||||
MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
|
||||
MmReleasePageMemoryConsumer(MC_CACHE, Required->Page[0]);
|
||||
|
||||
MmUnlockSectionSegment(Segment);
|
||||
MiSetPageEvent(Process, Address);
|
||||
return STATUS_SUCCESS;
|
||||
MmUnlockSectionSegment(Segment);
|
||||
MiSetPageEvent(Process, Address);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
NTAPI
|
||||
MmpPageOutPhysicalAddress(PFN_NUMBER Page)
|
||||
{
|
||||
BOOLEAN ProcRef = FALSE, PageDirty;
|
||||
PFN_NUMBER SectionPage = 0;
|
||||
PMM_RMAP_ENTRY entry;
|
||||
PMM_SECTION_SEGMENT Segment = NULL;
|
||||
LARGE_INTEGER FileOffset;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PMMSUPPORT AddressSpace = MmGetKernelAddressSpace();
|
||||
BOOLEAN Dirty = FALSE;
|
||||
PVOID Address = NULL;
|
||||
PEPROCESS Process = NULL;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
MM_REQUIRED_RESOURCES Resources = { 0 };
|
||||
BOOLEAN ProcRef = FALSE, PageDirty;
|
||||
PFN_NUMBER SectionPage = 0;
|
||||
PMM_RMAP_ENTRY entry;
|
||||
PMM_SECTION_SEGMENT Segment = NULL;
|
||||
LARGE_INTEGER FileOffset;
|
||||
PMEMORY_AREA MemoryArea;
|
||||
PMMSUPPORT AddressSpace = MmGetKernelAddressSpace();
|
||||
BOOLEAN Dirty = FALSE;
|
||||
PVOID Address = NULL;
|
||||
PEPROCESS Process = NULL;
|
||||
NTSTATUS Status = STATUS_SUCCESS;
|
||||
MM_REQUIRED_RESOURCES Resources = { 0 };
|
||||
|
||||
DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page));
|
||||
DPRINTC("Page out %x (ref ct %x)\n", Page, MmGetReferenceCountPage(Page));
|
||||
|
||||
ExAcquireFastMutex(&MiGlobalPageOperation);
|
||||
if ((Segment = MmGetSectionAssociation(Page, &FileOffset)))
|
||||
{
|
||||
DPRINTC("Withdrawing page (%x) %x:%x\n", Page, Segment, FileOffset.LowPart);
|
||||
SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty);
|
||||
DPRINTC("SectionPage %x\n", SectionPage);
|
||||
ExAcquireFastMutex(&MiGlobalPageOperation);
|
||||
if ((Segment = MmGetSectionAssociation(Page, &FileOffset)))
|
||||
{
|
||||
DPRINTC("Withdrawing page (%x) %x:%x\n",
|
||||
Page,
|
||||
Segment,
|
||||
FileOffset.LowPart);
|
||||
|
||||
if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0)
|
||||
{
|
||||
DPRINT1("In progress page out %x\n", SectionPage);
|
||||
ExReleaseFastMutex(&MiGlobalPageOperation);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(SectionPage == Page);
|
||||
}
|
||||
Resources.State = Dirty ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("No segment association for %x\n", Page);
|
||||
}
|
||||
SectionPage = MmWithdrawSectionPage(Segment, &FileOffset, &Dirty);
|
||||
DPRINTC("SectionPage %x\n", SectionPage);
|
||||
|
||||
if (SectionPage == MM_WAIT_ENTRY || SectionPage == 0)
|
||||
{
|
||||
DPRINT1("In progress page out %x\n", SectionPage);
|
||||
ExReleaseFastMutex(&MiGlobalPageOperation);
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(SectionPage == Page);
|
||||
}
|
||||
Resources.State = Dirty ? 1 : 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
DPRINT("No segment association for %x\n", Page);
|
||||
}
|
||||
|
||||
|
||||
Dirty = MmIsDirtyPageRmap(Page);
|
||||
Dirty = MmIsDirtyPageRmap(Page);
|
||||
|
||||
DPRINTC("Trying to unmap all instances of %x\n", Page);
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
entry = MmGetRmapListHeadPage(Page);
|
||||
DPRINTC("Trying to unmap all instances of %x\n", Page);
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
entry = MmGetRmapListHeadPage(Page);
|
||||
|
||||
// Entry and Segment might be null here in the case that the page
|
||||
// is new and is in the process of being swapped in
|
||||
if (!entry && !Segment)
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
DPRINT1("Page %x is in transit\n", Page);
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
goto bail;
|
||||
}
|
||||
// Entry and Segment might be null here in the case that the page
|
||||
// is new and is in the process of being swapped in
|
||||
if (!entry && !Segment)
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
DPRINT1("Page %x is in transit\n", Page);
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
while (entry != NULL && NT_SUCCESS(Status))
|
||||
{
|
||||
Process = entry->Process;
|
||||
Address = entry->Address;
|
||||
while (entry != NULL && NT_SUCCESS(Status))
|
||||
{
|
||||
Process = entry->Process;
|
||||
Address = entry->Address;
|
||||
|
||||
DPRINTC("Process %x Address %x Page %x\n", Process, Address, Page);
|
||||
DPRINTC("Process %x Address %x Page %x\n", Process, Address, Page);
|
||||
|
||||
if (RMAP_IS_SEGMENT(Address)) {
|
||||
entry = entry->Next;
|
||||
continue;
|
||||
}
|
||||
if (RMAP_IS_SEGMENT(Address)) {
|
||||
entry = entry->Next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Process && Address < MmSystemRangeStart)
|
||||
{
|
||||
// Make sure we don't try to page out part of an exiting process
|
||||
if (PspIsProcessExiting(Process))
|
||||
{
|
||||
DPRINT("bail\n");
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
goto bail;
|
||||
}
|
||||
Status = ObReferenceObject(Process);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("bail\n");
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
goto bail;
|
||||
}
|
||||
ProcRef = TRUE;
|
||||
AddressSpace = &Process->Vm;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
if (Process && Address < MmSystemRangeStart)
|
||||
{
|
||||
/* Make sure we don't try to page out part of an exiting process */
|
||||
if (PspIsProcessExiting(Process))
|
||||
{
|
||||
DPRINT("bail\n");
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
goto bail;
|
||||
}
|
||||
Status = ObReferenceObject(Process);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("bail\n");
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
goto bail;
|
||||
}
|
||||
ProcRef = TRUE;
|
||||
AddressSpace = &Process->Vm;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddressSpace = MmGetKernelAddressSpace();
|
||||
}
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
|
||||
RtlZeroMemory(&Resources, sizeof(Resources));
|
||||
RtlZeroMemory(&Resources, sizeof(Resources));
|
||||
|
||||
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
if ((((ULONG_PTR)Address) & 0xFFF) != 0)
|
||||
{
|
||||
KeBugCheck(MEMORY_MANAGEMENT);
|
||||
}
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
|
||||
do
|
||||
{
|
||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
||||
if (MemoryArea == NULL ||
|
||||
MemoryArea->DeleteInProgress)
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
DPRINTC("bail\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
DPRINTC
|
||||
("Type %x (%x -> %x)\n",
|
||||
MemoryArea->Type,
|
||||
MemoryArea->StartingAddress,
|
||||
MemoryArea->EndingAddress);
|
||||
|
||||
Resources.DoAcquisition = NULL;
|
||||
|
||||
Resources.Page[0] = Page;
|
||||
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
do
|
||||
{
|
||||
MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, Address);
|
||||
if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
|
||||
{
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
DPRINTC("bail\n");
|
||||
goto bail;
|
||||
}
|
||||
|
||||
DPRINT("%x:%x, page %x %x\n", Process, Address, Page, Resources.Page[0]);
|
||||
PageDirty = FALSE;
|
||||
Status = MmPageOutCacheSection
|
||||
(AddressSpace, MemoryArea, Address, &PageDirty, &Resources);
|
||||
Dirty |= PageDirty;
|
||||
DPRINT("%x\n", Status);
|
||||
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
||||
if (Status == STATUS_SUCCESS + 1)
|
||||
{
|
||||
// Wait page ... the other guy has it, so we'll just fail for now
|
||||
DPRINT1("Wait entry ... can't continue\n");
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto bail;
|
||||
}
|
||||
else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
|
||||
{
|
||||
DPRINTC("DoAcquisition %x\n", Resources.DoAcquisition);
|
||||
Status = Resources.DoAcquisition(AddressSpace, MemoryArea, &Resources);
|
||||
DPRINTC("Status %x\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("bail\n");
|
||||
goto bail;
|
||||
}
|
||||
else Status = STATUS_MM_RESTART_OPERATION;
|
||||
}
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
}
|
||||
while (Status == STATUS_MM_RESTART_OPERATION);
|
||||
DPRINTC("Type %x (%x -> %x)\n",
|
||||
MemoryArea->Type,
|
||||
MemoryArea->StartingAddress,
|
||||
MemoryArea->EndingAddress);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
Resources.DoAcquisition = NULL;
|
||||
Resources.Page[0] = Page;
|
||||
|
||||
if (ProcRef)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
ProcRef = FALSE;
|
||||
}
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address)));
|
||||
entry = MmGetRmapListHeadPage(Page);
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
|
||||
DPRINTC("Entry %x\n", entry);
|
||||
}
|
||||
DPRINT("%x:%x, page %x %x\n",
|
||||
Process,
|
||||
Address,
|
||||
Page,
|
||||
Resources.Page[0]);
|
||||
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
PageDirty = FALSE;
|
||||
|
||||
Status = MmPageOutCacheSection(AddressSpace,
|
||||
MemoryArea,
|
||||
Address,
|
||||
&PageDirty,
|
||||
&Resources);
|
||||
|
||||
Dirty |= PageDirty;
|
||||
DPRINT("%x\n", Status);
|
||||
|
||||
ASSERT(KeGetCurrentIrql() <= APC_LEVEL);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
||||
if (Status == STATUS_SUCCESS + 1)
|
||||
{
|
||||
// Wait page ... the other guy has it, so we'll just fail for now
|
||||
DPRINT1("Wait entry ... can't continue\n");
|
||||
Status = STATUS_UNSUCCESSFUL;
|
||||
goto bail;
|
||||
}
|
||||
else if (Status == STATUS_MORE_PROCESSING_REQUIRED)
|
||||
{
|
||||
DPRINTC("DoAcquisition %x\n", Resources.DoAcquisition);
|
||||
|
||||
Status = Resources.DoAcquisition(AddressSpace,
|
||||
MemoryArea,
|
||||
&Resources);
|
||||
|
||||
DPRINTC("Status %x\n", Status);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("bail\n");
|
||||
goto bail;
|
||||
}
|
||||
else Status = STATUS_MM_RESTART_OPERATION;
|
||||
}
|
||||
|
||||
MmLockAddressSpace(AddressSpace);
|
||||
}
|
||||
while (Status == STATUS_MM_RESTART_OPERATION);
|
||||
|
||||
MmUnlockAddressSpace(AddressSpace);
|
||||
|
||||
if (ProcRef)
|
||||
{
|
||||
ObDereferenceObject(Process);
|
||||
ProcRef = FALSE;
|
||||
}
|
||||
|
||||
ExAcquireFastMutex(&RmapListLock);
|
||||
ASSERT(!MM_IS_WAIT_PTE(MmGetPfnForProcess(Process, Address)));
|
||||
entry = MmGetRmapListHeadPage(Page);
|
||||
|
||||
DPRINTC("Entry %x\n", entry);
|
||||
}
|
||||
|
||||
ExReleaseFastMutex(&RmapListLock);
|
||||
|
||||
bail:
|
||||
DPRINTC("BAIL %x\n", Status);
|
||||
DPRINTC("BAIL %x\n", Status);
|
||||
|
||||
if (Segment)
|
||||
{
|
||||
ULONG RefCount;
|
||||
if (Segment)
|
||||
{
|
||||
ULONG RefCount;
|
||||
|
||||
DPRINTC("About to finalize section page %x (%x:%x) Status %x %s\n", Page, Segment, FileOffset.LowPart, Status, Dirty ? "dirty" : "clean");
|
||||
DPRINTC("About to finalize section page %x (%x:%x) Status %x %s\n",
|
||||
Page,
|
||||
Segment,
|
||||
FileOffset.LowPart,
|
||||
Status,
|
||||
Dirty ? "dirty" : "clean");
|
||||
|
||||
if (!NT_SUCCESS(Status) ||
|
||||
!NT_SUCCESS
|
||||
(Status = MmFinalizeSectionPageOut
|
||||
(Segment, &FileOffset, Page, Dirty)))
|
||||
{
|
||||
DPRINTC
|
||||
("Failed to page out %x, replacing %x at %x in segment %x\n",
|
||||
SectionPage, FileOffset.LowPart, Segment);
|
||||
MmLockSectionSegment(Segment);
|
||||
MmSetPageEntrySectionSegment(Segment, &FileOffset, Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page)));
|
||||
MmUnlockSectionSegment(Segment);
|
||||
}
|
||||
if (!NT_SUCCESS(Status) ||
|
||||
!NT_SUCCESS(Status = MmFinalizeSectionPageOut(Segment,
|
||||
&FileOffset,
|
||||
Page,
|
||||
Dirty)))
|
||||
{
|
||||
DPRINTC("Failed to page out %x, replacing %x at %x in segment %x\n",
|
||||
SectionPage,
|
||||
FileOffset.LowPart,
|
||||
Segment);
|
||||
|
||||
// Alas, we had the last reference
|
||||
if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
|
||||
MmFinalizeSegment(Segment);
|
||||
}
|
||||
MmLockSectionSegment(Segment);
|
||||
|
||||
if (ProcRef)
|
||||
{
|
||||
DPRINTC("Dereferencing process...\n");
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
MmSetPageEntrySectionSegment(Segment,
|
||||
&FileOffset,
|
||||
Dirty ? MAKE_PFN_SSE(Page) : DIRTY_SSE(MAKE_PFN_SSE(Page)));
|
||||
|
||||
ExReleaseFastMutex(&MiGlobalPageOperation);
|
||||
DPRINTC("%s %x %x\n", NT_SUCCESS(Status) ? "Evicted" : "Spared", Page, Status);
|
||||
return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||
MmUnlockSectionSegment(Segment);
|
||||
}
|
||||
|
||||
/* Alas, we had the last reference */
|
||||
if ((RefCount = InterlockedDecrementUL(&Segment->ReferenceCount)) == 0)
|
||||
MmFinalizeSegment(Segment);
|
||||
}
|
||||
|
||||
if (ProcRef)
|
||||
{
|
||||
DPRINTC("Dereferencing process...\n");
|
||||
ObDereferenceObject(Process);
|
||||
}
|
||||
|
||||
ExReleaseFastMutex(&MiGlobalPageOperation);
|
||||
|
||||
DPRINTC("%s %x %x\n",
|
||||
NT_SUCCESS(Status) ? "Evicted" : "Spared",
|
||||
Page,
|
||||
Status);
|
||||
|
||||
return NT_SUCCESS(Status) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
ULONG
|
||||
NTAPI
|
||||
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment, ULONG Target)
|
||||
MiCacheEvictPages(PMM_SECTION_SEGMENT Segment,
|
||||
ULONG Target)
|
||||
{
|
||||
ULONG Entry, Result = 0, i, j;
|
||||
NTSTATUS Status;
|
||||
PFN_NUMBER Page;
|
||||
LARGE_INTEGER Offset;
|
||||
ULONG Entry, Result = 0, i, j;
|
||||
NTSTATUS Status;
|
||||
PFN_NUMBER Page;
|
||||
LARGE_INTEGER Offset;
|
||||
|
||||
MmLockSectionSegment(Segment);
|
||||
MmLockSectionSegment(Segment);
|
||||
|
||||
for (i = 0; i < RtlNumberGenericTableElements(&Segment->PageTable); i++) {
|
||||
PCACHE_SECTION_PAGE_TABLE Element = RtlGetElementGenericTable(&Segment->PageTable, i);
|
||||
ASSERT(Element);
|
||||
Offset = Element->FileOffset;
|
||||
for (j = 0; j < ENTRIES_PER_ELEMENT; j++, Offset.QuadPart += PAGE_SIZE) {
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||
if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
|
||||
Page = PFN_FROM_SSE(Entry);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
Status = MmpPageOutPhysicalAddress(Page);
|
||||
if (NT_SUCCESS(Status))
|
||||
Result++;
|
||||
MmLockSectionSegment(Segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < RtlNumberGenericTableElements(&Segment->PageTable); i++) {
|
||||
|
||||
MmUnlockSectionSegment(Segment);
|
||||
PCACHE_SECTION_PAGE_TABLE Element = RtlGetElementGenericTable(&Segment->PageTable,
|
||||
i);
|
||||
|
||||
return Result;
|
||||
ASSERT(Element);
|
||||
|
||||
Offset = Element->FileOffset;
|
||||
for (j = 0; j < ENTRIES_PER_ELEMENT; j++, Offset.QuadPart += PAGE_SIZE) {
|
||||
Entry = MmGetPageEntrySectionSegment(Segment, &Offset);
|
||||
if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
|
||||
Page = PFN_FROM_SSE(Entry);
|
||||
MmUnlockSectionSegment(Segment);
|
||||
Status = MmpPageOutPhysicalAddress(Page);
|
||||
if (NT_SUCCESS(Status))
|
||||
Result++;
|
||||
MmLockSectionSegment(Segment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MmUnlockSectionSegment(Segment);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
extern LIST_ENTRY MiSegmentList;
|
||||
|
@ -486,7 +560,9 @@ extern LIST_ENTRY MiSegmentList;
|
|||
// This can fall away when our section implementation supports
|
||||
// demand paging properly
|
||||
NTSTATUS
|
||||
MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
||||
MiRosTrimCache(ULONG Target,
|
||||
ULONG Priority,
|
||||
PULONG NrFreed)
|
||||
{
|
||||
ULONG Freed;
|
||||
PLIST_ENTRY Entry;
|
||||
|
@ -494,9 +570,11 @@ MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed)
|
|||
*NrFreed = 0;
|
||||
|
||||
DPRINT1("Need to trim %d cache pages\n", Target);
|
||||
for (Entry = MiSegmentList.Flink; *NrFreed < Target && Entry != &MiSegmentList; Entry = Entry->Flink) {
|
||||
for (Entry = MiSegmentList.Flink;
|
||||
*NrFreed < Target && Entry != &MiSegmentList;
|
||||
Entry = Entry->Flink) {
|
||||
Segment = CONTAINING_RECORD(Entry, MM_SECTION_SEGMENT, ListOfSegments);
|
||||
// Defer to MM to try recovering pages from it
|
||||
/* Defer to MM to try recovering pages from it */
|
||||
Freed = MiCacheEvictPages(Segment, Target);
|
||||
*NrFreed += Freed;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue