reactos/ntoskrnl/cache/section/sptab.c
Timo Kreuzer 406dfdbc87 [CMAKE]
Sync trunk (rr49606)

svn path=/branches/cmake-bringup/; revision=49607
2010-11-16 13:43:39 +00:00

267 lines
7.7 KiB
C

/*
* Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/section.c
* PURPOSE: Section object page tables
*
* PROGRAMMERS: arty
*/
/* INCLUDES *****************************************************************/
#include <ntoskrnl.h>
#include "newmm.h"
#define NDEBUG
#include <debug.h>
#define DPRINTC DPRINT
/* TYPES *********************************************************************/
extern KSPIN_LOCK MiSectionPageTableLock;
static
PVOID
NTAPI
MiSectionPageTableAllocate(PRTL_GENERIC_TABLE Table, CLONG Bytes)
{
PVOID Result;
Result = ExAllocatePoolWithTag(NonPagedPool, Bytes, 'MmPt');
DPRINT("MiSectionPageTableAllocate(%d) => %p\n", Bytes, Result);
return Result;
}
static
VOID
NTAPI
MiSectionPageTableFree(PRTL_GENERIC_TABLE Table, PVOID Data)
{
DPRINT("MiSectionPageTableFree(%p)\n", Data);
ExFreePoolWithTag(Data, 'MmPt');
}
static
RTL_GENERIC_COMPARE_RESULTS
NTAPI
MiSectionPageTableCompare(PRTL_GENERIC_TABLE Table, PVOID PtrA, PVOID PtrB)
{
PLARGE_INTEGER A = PtrA, B = PtrB;
BOOLEAN Result = (A->QuadPart < B->QuadPart) ? GenericLessThan :
(A->QuadPart == B->QuadPart) ? GenericEqual : GenericGreaterThan;
DPRINT
("Compare: %08x%08x vs %08x%08x => %s\n",
A->u.HighPart, A->u.LowPart,
B->u.HighPart, B->u.LowPart,
Result == GenericLessThan ? "GenericLessThan" :
Result == GenericGreaterThan ? "GenericGreaterThan" :
"GenericEqual");
return Result;
}
static
PCACHE_SECTION_PAGE_TABLE
NTAPI
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);
PageTable = RtlLookupElementGenericTable(Table, &SearchFileOffset);
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)
{
LARGE_INTEGER SearchFileOffset;
PCACHE_SECTION_PAGE_TABLE PageTableSlice =
MiSectionPageTableGet(Table, FileOffset);
if (!PageTableSlice)
{
CACHE_SECTION_PAGE_TABLE SectionZeroPageTable = { };
SearchFileOffset.QuadPart = ROUND_DOWN(FileOffset->QuadPart, ENTRIES_PER_ELEMENT * PAGE_SIZE);
SectionZeroPageTable.FileOffset = SearchFileOffset;
SectionZeroPageTable.Refcount = 1;
PageTableSlice = RtlInsertElementGenericTable
(Table, &SectionZeroPageTable, sizeof(SectionZeroPageTable), NULL);
DPRINT
("Allocate page table %x (%08x%08x)\n",
PageTableSlice,
PageTableSlice->FileOffset.u.HighPart,
PageTableSlice->FileOffset.u.LowPart);
if (!PageTableSlice) return NULL;
}
return PageTableSlice;
}
VOID
NTAPI
MiInitializeSectionPageTable(PMM_CACHE_SECTION_SEGMENT Segment)
{
RtlInitializeGenericTable
(&Segment->PageTable,
MiSectionPageTableCompare,
MiSectionPageTableAllocate,
MiSectionPageTableFree,
NULL);
DPRINT("MiInitializeSectionPageTable(%p)\n", &Segment->PageTable);
}
NTSTATUS
NTAPI
_MiSetPageEntryCacheSectionSegment
(PMM_CACHE_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
ULONG Entry,
const char *file,
int line)
{
ULONG PageIndex, OldEntry;
PCACHE_SECTION_PAGE_TABLE PageTable;
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];
if (OldEntry && !IS_SWAP_FROM_SSE(OldEntry)) {
MmDeleteSectionAssociation(PFN_FROM_SSE(OldEntry));
}
if (Entry && !IS_SWAP_FROM_SSE(Entry)) {
MmSetSectionAssociation(PFN_FROM_SSE(Entry), Segment, Offset);
}
PageTable->PageEntries[PageIndex] = Entry;
DPRINT
("MiSetPageEntrySectionSegment(%p,%08x%08x,%x) %s:%d\n",
Segment, Offset->u.HighPart, Offset->u.LowPart, Entry, file, line);
return STATUS_SUCCESS;
}
ULONG
NTAPI
_MiGetPageEntryCacheSectionSegment
(PMM_CACHE_SECTION_SEGMENT Segment,
PLARGE_INTEGER Offset,
const char *file,
int line)
{
LARGE_INTEGER FileOffset;
ULONG PageIndex, Result;
PCACHE_SECTION_PAGE_TABLE PageTable;
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;
Result = PageTable->PageEntries[PageIndex];
#if 0
DPRINTC
("MiGetPageEntrySectionSegment(%p,%08x%08x) => %x %s:%d\n",
Segment,
FileOffset.u.HighPart,
FileOffset.u.LowPart + PageIndex * PAGE_SIZE,
Result,
file, line);
#endif
return Result;
}
VOID
NTAPI
MiFreePageTablesSectionSegment
(PMM_CACHE_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 %x -> %08x%08x\n",
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))
{
DPRINTC("Freeing page %x:%x @ %x\n", Segment, Entry, Offset.LowPart);
FreePage(Segment, &Offset);
}
}
}
DPRINT("Remove memory\n");
RtlDeleteElementGenericTable(&Segment->PageTable, Element);
}
DPRINT("Done\n");
}
PMM_CACHE_SECTION_SEGMENT
NTAPI
MmGetSectionAssociation(PFN_NUMBER Page, PLARGE_INTEGER Offset)
{
ULONG RawOffset;
PMM_CACHE_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);
}
NTSTATUS
NTAPI
MmSetSectionAssociation(PFN_NUMBER Page, PMM_CACHE_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;
}