Swapping to disk

svn path=/trunk/; revision=2467
This commit is contained in:
David Welch 2001-12-31 19:06:49 +00:00
parent 36214fbd89
commit 3ea11463b3
17 changed files with 1006 additions and 208 deletions

View file

@ -1,4 +1,4 @@
# $Id: Makefile,v 1.60 2001/12/31 01:53:44 dwelch Exp $ # $Id: Makefile,v 1.61 2001/12/31 19:06:46 dwelch Exp $
# #
# ReactOS Operating System # ReactOS Operating System
# #
@ -151,7 +151,8 @@ OBJECTS_MM = \
mm/mpw.o \ mm/mpw.o \
mm/pageop.o \ mm/pageop.o \
mm/balance.o \ mm/balance.o \
mm/rmap.o mm/rmap.o \
mm/slab.o
# I/O Subsystem (Io) # I/O Subsystem (Io)
OBJECTS_IO = \ OBJECTS_IO = \

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: view.c,v 1.32 2001/12/31 01:53:44 dwelch Exp $ /* $Id: view.c,v 1.33 2001/12/31 19:06:47 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -357,8 +357,9 @@ CcRosRequestCacheSegment(PBCB Bcb,
STATIC VOID STATIC VOID
CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr, CcFreeCachePage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
BOOLEAN Dirty) SWAPENTRY SwapEntry, BOOLEAN Dirty)
{ {
assert(SwapEntry == 0);
if (PhysAddr != 0) if (PhysAddr != 0)
{ {
MmReleasePageMemoryConsumer(MC_CACHE, (PVOID)PhysAddr); MmReleasePageMemoryConsumer(MC_CACHE, (PVOID)PhysAddr);

View file

@ -62,7 +62,7 @@ typedef ULONG SWAPENTRY;
typedef struct typedef struct
{ {
ULONG Pages[NR_SECTION_PAGE_ENTRIES]; ULONG Entry[NR_SECTION_PAGE_ENTRIES];
} SECTION_PAGE_TABLE, *PSECTION_PAGE_TABLE; } SECTION_PAGE_TABLE, *PSECTION_PAGE_TABLE;
typedef struct typedef struct
@ -141,23 +141,12 @@ typedef struct
} Data; } Data;
} MEMORY_AREA, *PMEMORY_AREA; } MEMORY_AREA, *PMEMORY_AREA;
typedef struct _KCIRCULAR_QUEUE
{
ULONG First;
ULONG Last;
ULONG CurrentSize;
ULONG MaximumSize;
PVOID* Mem;
} KCIRCULAR_QUEUE, *PKCIRCULAR_QUEUE;
typedef struct _MADDRESS_SPACE typedef struct _MADDRESS_SPACE
{ {
LIST_ENTRY MAreaListHead; LIST_ENTRY MAreaListHead;
KMUTEX Lock; KMUTEX Lock;
ULONG LowestAddress; ULONG LowestAddress;
struct _EPROCESS* Process; struct _EPROCESS* Process;
PMEMORY_AREA WorkingSetArea;
KCIRCULAR_QUEUE WSQueue;
PUSHORT PageTableRefCountTable; PUSHORT PageTableRefCountTable;
ULONG PageTableRefCountTableSize; ULONG PageTableRefCountTableSize;
} MADDRESS_SPACE, *PMADDRESS_SPACE; } MADDRESS_SPACE, *PMADDRESS_SPACE;
@ -189,7 +178,8 @@ NTSTATUS MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress, PVOID BaseAddress,
ULONG Length, ULONG Length,
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea,
PVOID Address, ULONG PhysAddr, BOOLEAN Dirty), PVOID Address, ULONG PhysAddr, SWAPENTRY SwapEntry,
BOOLEAN Dirty),
PVOID FreePageContext); PVOID FreePageContext);
VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead); VOID MmDumpMemoryAreas(PLIST_ENTRY ListHead);
NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea); NTSTATUS MmLockMemoryArea(MEMORY_AREA* MemoryArea);
@ -507,5 +497,12 @@ MmTrimUserMemory(ULONG Target, ULONG Priority, PULONG NrFreedPages);
VOID VOID
MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, ULONG* PhysicalAddr); MmDisableVirtualMapping(PEPROCESS Process, PVOID Address, BOOL* WasDirty, ULONG* PhysicalAddr);
VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address); VOID MmEnableVirtualMapping(PEPROCESS Process, PVOID Address);
VOID
MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY* SwapEntry);
NTSTATUS
MmCreatePageFileMapping(PEPROCESS Process,
PVOID Address,
SWAPENTRY SwapEntry);
BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address);
#endif #endif

View file

@ -1,4 +1,4 @@
/* $Id: kdebug.c,v 1.29 2001/09/09 09:47:18 hbirr Exp $ /* $Id: kdebug.c,v 1.30 2001/12/31 19:06:47 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -302,6 +302,8 @@ KeEnterKernelDebugger (VOID)
VOID STDCALL VOID STDCALL
KdSystemDebugControl(ULONG Code) KdSystemDebugControl(ULONG Code)
{ {
extern VOID PsDumpThreads(BOOLEAN IncludeSystem);
/* A - Dump the entire contents of the non-paged pool. */ /* A - Dump the entire contents of the non-paged pool. */
if (Code == 0) if (Code == 0)
{ {
@ -336,10 +338,12 @@ KdSystemDebugControl(ULONG Code)
/* F */ /* F */
else if (Code == 5) else if (Code == 5)
{ {
PsDumpThreads(TRUE);
} }
/* G */ /* G */
else if (Code == 6) else if (Code == 6)
{ {
PsDumpThreads(FALSE);
} }
/* H */ /* H */
else if (Code == 7) else if (Code == 7)

View file

@ -44,8 +44,9 @@
VOID VOID
KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr, KeFreeStackPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
BOOLEAN Dirty) SWAPENTRY SwapEntry, BOOLEAN Dirty)
{ {
assert(SwapEntry == 0);
if (PhysAddr != 0) if (PhysAddr != 0)
{ {
MmDereferencePage((PVOID)PhysAddr); MmDereferencePage((PVOID)PhysAddr);

View file

@ -1,4 +1,4 @@
/* $Id: cont.c,v 1.15 2001/12/31 01:53:45 dwelch Exp $ /* $Id: cont.c,v 1.16 2001/12/31 19:06:47 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -21,8 +21,9 @@
VOID STATIC VOID STATIC
MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr, MmFreeContinuousPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
BOOLEAN Dirty) SWAPENTRY SwapEntry, BOOLEAN Dirty)
{ {
assert(SwapEntry == 0);
if (PhysAddr != 0) if (PhysAddr != 0)
{ {
MmDereferencePage((PVOID)PhysAddr); MmDereferencePage((PVOID)PhysAddr);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: page.c,v 1.30 2001/12/31 01:53:46 dwelch Exp $ /* $Id: page.c,v 1.31 2001/12/31 19:06:48 dwelch Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/i386/page.c * FILE: ntoskrnl/mm/i386/page.c
@ -508,6 +508,85 @@ MmDeleteVirtualMapping(PEPROCESS Process, PVOID Address, BOOL FreePage,
} }
} }
VOID
MmDeletePageFileMapping(PEPROCESS Process, PVOID Address, SWAPENTRY* SwapEntry)
/*
* FUNCTION: Delete a virtual mapping
*/
{
ULONG Pte;
PULONG Pde;
PEPROCESS CurrentProcess = PsGetCurrentProcess();
BOOLEAN WasValid;
/*
* If we are setting a page in another process we need to be in its
* context.
*/
if (Process != NULL && Process != CurrentProcess)
{
KeAttachProcess(Process);
}
/*
* Set the page directory entry, we may have to copy the entry from
* the global page directory.
*/
Pde = ADDR_TO_PDE(Address);
if ((*Pde) == 0 &&
MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)] != 0)
{
(*Pde) = MmGlobalKernelPageDirectory[ADDR_TO_PDE_OFFSET(Address)];
FLUSH_TLB;
}
if ((*Pde) == 0)
{
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
*SwapEntry = 0;
return;
}
/*
* Atomically set the entry to zero and get the old value.
*/
Pte = (ULONG)InterlockedExchange((PLONG)ADDR_TO_PTE(Address), 0);
FLUSH_TLB;
/*
* Decrement the reference count for this page table.
*/
if (Process != NULL && WasValid &&
Process->AddressSpace.PageTableRefCountTable != NULL &&
ADDR_TO_PAGE_TABLE(Address) < 768)
{
PUSHORT Ptrc;
Ptrc = Process->AddressSpace.PageTableRefCountTable;
Ptrc[ADDR_TO_PAGE_TABLE(Address)]--;
if (Ptrc[ADDR_TO_PAGE_TABLE(Address)] == 0)
{
MmFreePageTable(Process, Address);
}
}
/*
* If necessary go back to the original context
*/
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
/*
* Return some information to the caller
*/
*SwapEntry = Pte >> 1;
}
BOOLEAN BOOLEAN
Mmi386MakeKernelPageTableGlobal(PVOID PAddress) Mmi386MakeKernelPageTableGlobal(PVOID PAddress)
{ {
@ -680,6 +759,13 @@ BOOLEAN MmIsPagePresent(PEPROCESS Process, PVOID Address)
return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT); return((MmGetPageEntryForProcess1(Process, Address)) & PA_PRESENT);
} }
BOOLEAN MmIsPageSwapEntry(PEPROCESS Process, PVOID Address)
{
ULONG Pte;
Pte = MmGetPageEntryForProcess1(Process, Address);
return((!(Pte & PA_PRESENT)) && Pte != 0);
}
NTSTATUS NTSTATUS
MmCreateVirtualMappingForKernel(PVOID Address, MmCreateVirtualMappingForKernel(PVOID Address,
ULONG flProtect, ULONG flProtect,
@ -726,8 +812,13 @@ MmCreateVirtualMappingForKernel(PVOID Address,
} }
return(Status); return(Status);
} }
if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
{
KeBugCheck(0);
}
if (PAGE_MASK((*Pte)) != 0) if (PAGE_MASK((*Pte)) != 0)
{ {
MmMarkPageUnmapped((PVOID)PAGE_MASK((*Pte)));
} }
*Pte = PhysicalAddress | Attributes; *Pte = PhysicalAddress | Attributes;
if (Process != NULL && if (Process != NULL &&
@ -749,6 +840,76 @@ MmCreateVirtualMappingForKernel(PVOID Address,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
NTSTATUS
MmCreatePageFileMapping(PEPROCESS Process,
PVOID Address,
SWAPENTRY SwapEntry)
{
PEPROCESS CurrentProcess;
PULONG Pte;
NTSTATUS Status;
if (Process != NULL)
{
CurrentProcess = PsGetCurrentProcess();
}
else
{
CurrentProcess = NULL;
}
if (Process == NULL && Address < (PVOID)KERNEL_BASE)
{
DPRINT1("No process\n");
KeBugCheck(0);
}
if (Process != NULL && Address >= (PVOID)KERNEL_BASE)
{
DPRINT1("Setting kernel address with process context\n");
KeBugCheck(0);
}
if (SwapEntry & (1 << 31))
{
KeBugCheck(0);
}
if (Process != NULL && Process != CurrentProcess)
{
KeAttachProcess(Process);
}
Status = MmGetPageEntry2(Address, &Pte);
if (!NT_SUCCESS(Status))
{
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
return(Status);
}
if (PAGE_MASK((*Pte)) != 0)
{
MmMarkPageUnmapped((PVOID)PAGE_MASK((*Pte)));
}
*Pte = SwapEntry << 1;
if (Process != NULL &&
Process->AddressSpace.PageTableRefCountTable != NULL &&
ADDR_TO_PAGE_TABLE(Address) < 768)
{
PUSHORT Ptrc;
Ptrc = Process->AddressSpace.PageTableRefCountTable;
Ptrc[ADDR_TO_PAGE_TABLE(Address)]++;
}
FLUSH_TLB;
if (Process != NULL && Process != CurrentProcess)
{
KeDetachProcess();
}
return(STATUS_SUCCESS);
}
NTSTATUS NTSTATUS
MmCreateVirtualMappingUnsafe(PEPROCESS Process, MmCreateVirtualMappingUnsafe(PEPROCESS Process,
PVOID Address, PVOID Address,
@ -797,6 +958,10 @@ MmCreateVirtualMappingUnsafe(PEPROCESS Process,
} }
return(Status); return(Status);
} }
if (PAGE_MASK((*Pte)) != 0 && !((*Pte) & PA_PRESENT))
{
KeBugCheck(0);
}
if (PAGE_MASK((*Pte)) != 0) if (PAGE_MASK((*Pte)) != 0)
{ {
MmMarkPageUnmapped((PVOID)PAGE_MASK((*Pte))); MmMarkPageUnmapped((PVOID)PAGE_MASK((*Pte)));
@ -893,10 +1058,19 @@ MmGetPhysicalAddress(PVOID vaddr)
*/ */
{ {
PHYSICAL_ADDRESS p; PHYSICAL_ADDRESS p;
ULONG Pte;
DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr); DPRINT("MmGetPhysicalAddress(vaddr %x)\n", vaddr);
p.QuadPart = PAGE_MASK(*MmGetPageEntry(vaddr)); Pte = *MmGetPageEntry(vaddr);
if (Pte & PA_PRESENT)
{
p.QuadPart = PAGE_MASK(Pte);
}
else
{
p.QuadPart = 0;
}
return p; return p;
} }

View file

@ -295,7 +295,7 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
PVOID BaseAddress, PVOID BaseAddress,
ULONG Length, ULONG Length,
VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, VOID (*FreePage)(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address,
ULONG PhysAddr, BOOLEAN Dirty), ULONG PhysAddr, SWAPENTRY SwapEntry, BOOLEAN Dirty),
PVOID FreePageContext) PVOID FreePageContext)
{ {
MEMORY_AREA* MemoryArea; MEMORY_AREA* MemoryArea;
@ -315,14 +315,25 @@ MmFreeMemoryArea(PMADDRESS_SPACE AddressSpace,
{ {
ULONG PhysAddr; ULONG PhysAddr;
BOOL Dirty; BOOL Dirty;
SWAPENTRY SwapEntry = 0;
if (MmIsPageSwapEntry(AddressSpace->Process,
MemoryArea->BaseAddress + (i * PAGESIZE)))
{
MmDeletePageFileMapping(AddressSpace->Process,
MemoryArea->BaseAddress + (i * PAGESIZE),
&SwapEntry);
}
else
{
MmDeleteVirtualMapping(AddressSpace->Process, MmDeleteVirtualMapping(AddressSpace->Process,
MemoryArea->BaseAddress + (i*PAGESIZE), MemoryArea->BaseAddress + (i*PAGESIZE),
FALSE, &Dirty, &PhysAddr); FALSE, &Dirty, &PhysAddr);
}
if (FreePage != NULL) if (FreePage != NULL)
{ {
FreePage(FreePageContext, MemoryArea, FreePage(FreePageContext, MemoryArea,
MemoryArea->BaseAddress + (i * PAGESIZE), PhysAddr, Dirty); MemoryArea->BaseAddress + (i * PAGESIZE), PhysAddr, SwapEntry, Dirty);
} }
} }

View file

@ -1,4 +1,4 @@
/* $Id: ncache.c,v 1.13 2001/12/31 01:53:45 dwelch Exp $ /* $Id: ncache.c,v 1.14 2001/12/31 19:06:47 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -86,8 +86,9 @@ MmAllocateNonCachedMemory(IN ULONG NumberOfBytes)
VOID STATIC VOID STATIC
MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr, MmFreeNonCachedPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
BOOLEAN Dirty) SWAPENTRY SwapEntry, BOOLEAN Dirty)
{ {
assert(SwapEntry == 0);
if (PhysAddr != 0) if (PhysAddr != 0)
{ {
MmDereferencePage((PVOID)PhysAddr); MmDereferencePage((PVOID)PhysAddr);

View file

@ -1,4 +1,4 @@
/* $Id: npool.c,v 1.52 2001/12/31 01:53:45 dwelch Exp $ /* $Id: npool.c,v 1.53 2001/12/31 19:06:47 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -1013,7 +1013,7 @@ ExAllocateWholePageBlock(ULONG UserSize)
for (i = 0; i < NrPages; i++) for (i = 0; i < NrPages; i++)
{ {
Page = MmAllocPage(0); Page = MmAllocPage(MC_NPPOOL, 0);
if (Page == NULL) if (Page == NULL)
{ {
KeBugCheck(0); KeBugCheck(0);

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: pagefile.c,v 1.13 2001/12/06 00:54:54 dwelch Exp $ /* $Id: pagefile.c,v 1.14 2001/12/31 19:06:47 dwelch Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/pagefile.c * FILE: ntoskrnl/mm/pagefile.c
@ -96,7 +96,7 @@ static BYTE MmCoreDumpHeader[PAGESIZE];
*/ */
#define FILE_FROM_ENTRY(i) ((i) >> 24) #define FILE_FROM_ENTRY(i) ((i) >> 24)
#define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1) #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1)
#define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) || ((j) + 1)) #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) | ((j) + 1))
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -122,7 +122,7 @@ NTSTATUS MmWriteToSwapPage(SWAPENTRY SwapEntry, PMDL Mdl)
Mdl, Mdl,
&file_offset, &file_offset,
&Iosb, &Iosb,
FALSE); TRUE);
return(Status); return(Status);
} }
@ -204,6 +204,7 @@ MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
{ {
KIRQL oldIrql; KIRQL oldIrql;
ULONG i, j; ULONG i, j;
static BOOLEAN SwapSpaceMessage = FALSE;
KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql); KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
@ -221,14 +222,19 @@ MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
continue; continue;
} }
PagingFile->AllocMap[i] |= (1 << j); PagingFile->AllocMap[i] |= (1 << j);
PagingFile->UsedPages--; PagingFile->UsedPages++;
PagingFile->FreePages++; PagingFile->FreePages--;
KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
return((i * 32) + j); return((i * 32) + j);
} }
KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql); KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
return(0); if (!SwapSpaceMessage)
{
DPRINT1("MM: Out of swap space.\n");
SwapSpaceMessage = TRUE;
}
return(0xFFFFFFFF);
} }
VOID VOID
@ -242,9 +248,13 @@ MmFreeSwapPage(SWAPENTRY Entry)
off = OFFSET_FROM_ENTRY(Entry); off = OFFSET_FROM_ENTRY(Entry);
KeAcquireSpinLock(&PagingFileListLock, &oldIrql); KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
if (PagingFileList[i] == NULL)
{
KeBugCheck(0);
}
KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock); KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock);
PagingFileList[i]->AllocMap[off / 32] |= (1 << (off % 32)); PagingFileList[i]->AllocMap[off / 32] &= (~(1 << (off % 32)));
PagingFileList[i]->FreePages++; PagingFileList[i]->FreePages++;
PagingFileList[i]->UsedPages--; PagingFileList[i]->UsedPages--;
@ -278,7 +288,7 @@ MmAllocSwapPage(VOID)
PagingFileList[i]->FreePages >= 1) PagingFileList[i]->FreePages >= 1)
{ {
off = MiAllocPageFromPagingFile(PagingFileList[i]); off = MiAllocPageFromPagingFile(PagingFileList[i]);
if (off != 0) if (off == 0xFFFFFFFF)
{ {
KeBugCheck(0); KeBugCheck(0);
KeReleaseSpinLock(&PagingFileListLock, oldIrql); KeReleaseSpinLock(&PagingFileListLock, oldIrql);
@ -334,6 +344,11 @@ NtCreatePagingFile(IN PUNICODE_STRING PageFileName,
KIRQL oldIrql; KIRQL oldIrql;
ULONG AllocMapSize; ULONG AllocMapSize;
ULONG i; ULONG i;
PVOID Buffer;
LARGE_INTEGER ByteOffset;
DPRINT1("NtCreatePagingFile(PageFileName %wZ, MinimumSize %d)\n",
PageFileName, MinimumSize);
InitializeObjectAttributes(&ObjectAttributes, InitializeObjectAttributes(&ObjectAttributes,
PageFileName, PageFileName,
@ -347,7 +362,7 @@ NtCreatePagingFile(IN PUNICODE_STRING PageFileName,
NULL, NULL,
0, 0,
0, 0,
FILE_OPEN, FILE_OPEN_IF,
FILE_SYNCHRONOUS_IO_NONALERT, FILE_SYNCHRONOUS_IO_NONALERT,
NULL, NULL,
0); 0);
@ -356,6 +371,24 @@ NtCreatePagingFile(IN PUNICODE_STRING PageFileName,
return(Status); return(Status);
} }
Buffer = ExAllocatePool(NonPagedPool, 4096);
memset(Buffer, 0, 4096);
ByteOffset.QuadPart = MinimumSize * 4096;
Status = NtWriteFile(FileHandle,
NULL,
NULL,
NULL,
&IoStatus,
Buffer,
4096,
&ByteOffset,
NULL);
if (!NT_SUCCESS(Status))
{
NtClose(FileHandle);
return(Status);
}
Status = ObReferenceObjectByHandle(FileHandle, Status = ObReferenceObjectByHandle(FileHandle,
FILE_ALL_ACCESS, FILE_ALL_ACCESS,
IoFileObjectType, IoFileObjectType,

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: section.c,v 1.70 2001/12/31 01:53:45 dwelch Exp $ /* $Id: section.c,v 1.71 2001/12/31 19:06:48 dwelch Exp $
* *
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/section.c * FILE: ntoskrnl/mm/section.c
@ -65,8 +65,13 @@ static GENERIC_MAPPING MmpSectionMapping = {
#define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S') #define TAG_MM_SECTION_SEGMENT TAG('M', 'M', 'S', 'S')
#define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T') #define TAG_SECTION_PAGE_TABLE TAG('M', 'S', 'P', 'T')
#define SHARE_COUNT(E) ((E) & 0xFFF) #define PAGE_FROM_SSE(E) ((E) & 0xFFFFF000)
#define MAX_SHARE_COUNT 0xFFF #define SHARE_COUNT_FROM_SSE(E) (((E) & 0x00000FFE) >> 1)
#define IS_SWAP_FROM_SSE(E) ((E) & 0x00000001)
#define MAX_SHARE_COUNT 0x7FF
#define MAKE_SSE(P, C) ((P) | ((C) << 1))
#define SWAPENTRY_FROM_SSE(E) ((E) >> 1)
#define MAKE_SWAP_SSE(S) (((S) << 1) | 0x1)
/* FUNCTIONS *****************************************************************/ /* FUNCTIONS *****************************************************************/
@ -189,7 +194,7 @@ MmSetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
DPRINT("Table %x\n", Table); DPRINT("Table %x\n", Table);
} }
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset); TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
Table->Pages[TableOffset] = Entry; Table->Entry[TableOffset] = Entry;
} }
@ -212,7 +217,7 @@ MmGetPageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
return(0); return(0);
} }
TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset); TableOffset = PAGE_TO_SECTION_PAGE_TABLE_OFFSET(Offset);
Entry = Table->Pages[TableOffset]; Entry = Table->Entry[TableOffset];
return(Entry); return(Entry);
} }
@ -228,12 +233,16 @@ MmSharePageEntrySectionSegment(PMM_SECTION_SEGMENT Segment,
DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n"); DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
KeBugCheck(0); KeBugCheck(0);
} }
if (SHARE_COUNT(Entry) == MAX_SHARE_COUNT) if (SHARE_COUNT_FROM_SSE(Entry) == MAX_SHARE_COUNT)
{ {
DPRINT1("Maximum share count reached\n"); DPRINT1("Maximum share count reached\n");
KeBugCheck(0); KeBugCheck(0);
} }
Entry = (Entry & 0xFFFFF000) | (SHARE_COUNT(Entry) + 1); if (IS_SWAP_FROM_SSE(Entry))
{
KeBugCheck(0);
}
Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) + 1);
MmSetPageEntrySectionSegment(Segment, Offset, Entry); MmSetPageEntrySectionSegment(Segment, Offset, Entry);
} }
@ -251,17 +260,21 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n"); DPRINT1("Entry == 0 for MmSharePageEntrySectionSegment\n");
KeBugCheck(0); KeBugCheck(0);
} }
if (SHARE_COUNT(Entry) == 0) if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{ {
DPRINT1("Zero share count for unshare\n"); DPRINT1("Zero share count for unshare\n");
KeBugCheck(0); KeBugCheck(0);
} }
Entry = (Entry & 0xFFFFF000) | (SHARE_COUNT(Entry) - 1); if (IS_SWAP_FROM_SSE(Entry))
{
KeBugCheck(0);
}
Entry = MAKE_SSE(PAGE_FROM_SSE(Entry), SHARE_COUNT_FROM_SSE(Entry) - 1);
/* /*
* If we reducing the share count of this entry to zero then set the entry to zero and * If we reducing the share count of this entry to zero then set the entry to zero and
* tell the cache the page is no longer mapped. * tell the cache the page is no longer mapped.
*/ */
if (SHARE_COUNT(Entry) == 0) if (SHARE_COUNT_FROM_SSE(Entry) == 0)
{ {
PFILE_OBJECT FileObject; PFILE_OBJECT FileObject;
PREACTOS_COMMON_FCB_HEADER Fcb; PREACTOS_COMMON_FCB_HEADER Fcb;
@ -288,7 +301,7 @@ MmUnsharePageEntrySectionSegment(PSECTION_OBJECT Section,
{ {
MmSetPageEntrySectionSegment(Segment, Offset, Entry); MmSetPageEntrySectionSegment(Segment, Offset, Entry);
} }
return(SHARE_COUNT(Entry) > 1); return(SHARE_COUNT_FROM_SSE(Entry) > 1);
} }
NTSTATUS NTSTATUS
@ -508,7 +521,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
{ {
Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart); Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
Page = (PVOID)(Entry & 0xFFFFF000); Page = (PVOID)(PAGE_FROM_SSE(Entry));
MmReferencePage(Page); MmReferencePage(Page);
MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart); MmSharePageEntrySectionSegment(Segment, Offset.u.LowPart);
@ -533,6 +546,70 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
return(STATUS_SUCCESS); return(STATUS_SUCCESS);
} }
/*
* Must be private page we have swapped out.
*/
if (MmIsPageSwapEntry(NULL, (PVOID)PAddress))
{
SWAPENTRY SwapEntry;
PMDL Mdl;
MmUnlockSectionSegment(Segment);
MmUnlockSection(Section);
Status = MmRequestPageMemoryConsumer(MC_USER, FALSE, &Page);
if (!NT_SUCCESS(Status))
{
KeBugCheck(0);
}
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
MmBuildMdlFromPages(Mdl, (PULONG)&Page);
Status = MmReadFromSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status))
{
KeBugCheck(0);
}
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
Address,
MemoryArea->Attributes,
(ULONG)Page);
while (Status == STATUS_NO_MEMORY)
{
MmUnlockAddressSpace(AddressSpace);
KeBugCheck(0);
MmLockAddressSpace(AddressSpace);
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
Address,
MemoryArea->Attributes,
(ULONG)Page);
}
if (!NT_SUCCESS(Status))
{
DPRINT1("MmCreateVirtualMapping failed, not out of memory\n");
KeBugCheck(0);
return(Status);
}
/*
* Add the page to the process's working set
*/
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
/*
* Finish the operation
*/
if (Locked)
{
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
}
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
return(STATUS_SUCCESS);
}
/* /*
* Satisfying a page fault on a map of /Device/PhysicalMemory is easy * Satisfying a page fault on a map of /Device/PhysicalMemory is easy
*/ */
@ -615,7 +692,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
/* /*
* Get the entry corresponding to the offset within the section * Get the entry corresponding to the offset within the section
*/ */
Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart) & 0xFFFFF000; Entry = MmGetPageEntrySectionSegment(Segment, Offset.u.LowPart);
if (Entry == 0) if (Entry == 0)
{ {
@ -667,7 +744,83 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
* Check the entry. No one should change the status of a page * Check the entry. No one should change the status of a page
* that has a pending page-in. * that has a pending page-in.
*/ */
Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart) & 0xFFFFF000; Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
if (Entry != Entry1)
{
DbgPrint("Someone changed ppte entry while we slept\n");
KeBugCheck(0);
}
/*
* Mark the offset within the section as having valid, in-memory
* data
*/
Entry = (ULONG)Page;
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
Status = MmCreateVirtualMapping(PsGetCurrentProcess(),
Address,
Attributes,
(ULONG)Page);
MmInsertRmap(Page, PsGetCurrentProcess(), (PVOID)PAGE_ROUND_DOWN(Address));
if (!NT_SUCCESS(Status))
{
DbgPrint("Unable to create virtual mapping\n");
KeBugCheck(0);
}
if (Locked)
{
MmLockPage((PVOID)MmGetPhysicalAddressForProcess(NULL, Address));
}
PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp);
MmUnlockSectionSegment(Segment);
MmUnlockSection(Section);
DPRINT("MmNotPresentFaultSectionView succeeded\n");
return(STATUS_SUCCESS);
}
else if (IS_SWAP_FROM_SSE(Entry))
{
SWAPENTRY SwapEntry;
PMDL Mdl;
SwapEntry = SWAPENTRY_FROM_SSE(Entry);
/*
* Release all our locks and read in the page from disk
*/
MmUnlockSectionSegment(Segment);
MmUnlockSection(Section);
MmUnlockAddressSpace(AddressSpace);
Status = MmRequestPageMemoryConsumer(MC_USER, TRUE, &Page);
if (!NT_SUCCESS(Status))
{
KeBugCheck(0);
}
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
MmBuildMdlFromPages(Mdl, (PULONG)&Page);
Status = MmReadFromSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status))
{
KeBugCheck(0);
}
/*
* Relock the address space, section and segment
*/
MmLockAddressSpace(AddressSpace);
MmLockSection(Section);
MmLockSectionSegment(Segment);
/*
* Check the entry. No one should change the status of a page
* that has a pending page-in.
*/
Entry1 = MmGetPageEntrySectionSegment(Segment, Offset.QuadPart);
if (Entry != Entry1) if (Entry != Entry1)
{ {
DbgPrint("Someone changed ppte entry while we slept\n"); DbgPrint("Someone changed ppte entry while we slept\n");
@ -711,7 +864,7 @@ MmNotPresentFaultSectionView(PMADDRESS_SPACE AddressSpace,
* take another reference to the page * take another reference to the page
*/ */
Page = (PVOID)Entry; Page = (PVOID)PAGE_FROM_SSE(Entry);
MmReferencePage(Page); MmReferencePage(Page);
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
@ -854,6 +1007,11 @@ MmAccessFaultSectionView(PMADDRESS_SPACE AddressSpace,
memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGESIZE); memcpy(NewAddress, (PVOID)PAGE_ROUND_DOWN(Address), PAGESIZE);
ExUnmapPage(NewAddress); ExUnmapPage(NewAddress);
/*
* Delete the old entry.
*/
MmDeleteVirtualMapping(PsGetCurrentProcess(), Address, FALSE, NULL, NULL);
/* /*
* Set the PTE to point to the new page * Set the PTE to point to the new page
*/ */
@ -891,13 +1049,14 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
{ {
MM_SECTION_PAGEOUT_CONTEXT* PageOutContext; MM_SECTION_PAGEOUT_CONTEXT* PageOutContext;
BOOL WasDirty; BOOL WasDirty;
PVOID PhysicalAddress;
PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context; PageOutContext = (MM_SECTION_PAGEOUT_CONTEXT*)Context;
MmDeleteVirtualMapping(Process, MmDeleteVirtualMapping(Process,
Address, Address,
FALSE, FALSE,
&WasDirty, &WasDirty,
NULL); (PULONG)&PhysicalAddress);
PageOutContext->WasDirty = PageOutContext->WasDirty || WasDirty; PageOutContext->WasDirty = PageOutContext->WasDirty || WasDirty;
if (!PageOutContext->Private) if (!PageOutContext->Private)
{ {
@ -906,6 +1065,7 @@ MmPageOutDeleteMapping(PVOID Context, PEPROCESS Process, PVOID Address)
PageOutContext->Offset.u.LowPart, PageOutContext->Offset.u.LowPart,
PageOutContext->WasDirty); PageOutContext->WasDirty);
} }
MmDereferencePage(PhysicalAddress);
} }
NTSTATUS NTSTATUS
@ -986,6 +1146,10 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
Context.WasDirty = FALSE; Context.WasDirty = FALSE;
Context.Private = Private = ((PVOID)(Entry & 0xFFFFF000) != PhysicalAddress); Context.Private = Private = ((PVOID)(Entry & 0xFFFFF000) != PhysicalAddress);
/*
* Take an additional reference to the page.
*/
MmReferencePage(PhysicalAddress);
/* /*
* Paging only data mapped read-only is easy. * Paging only data mapped read-only is easy.
@ -1055,6 +1219,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
*/ */
if (DirectMapped) if (DirectMapped)
{ {
MmDereferencePage((PVOID)PhysicalAddress);
PageOp->Status = STATUS_SUCCESS; PageOp->Status = STATUS_SUCCESS;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp); MmReleasePageOp(PageOp);
@ -1090,13 +1255,13 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
* set it back into section segment entry so we don't loose our * set it back into section segment entry so we don't loose our
* copy. Otherwise it will be handled by the cache manager. * copy. Otherwise it will be handled by the cache manager.
*/ */
if (!DirectMapped) Status = MmCreateVirtualMapping(MemoryArea->Process,
{ Address,
MemoryArea->Attributes,
(ULONG)PhysicalAddress);
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, (ULONG)PhysicalAddress); MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, (ULONG)PhysicalAddress);
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
} }
}
PageOp->Status = STATUS_UNSUCCESSFUL; PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp); MmReleasePageOp(PageOp);
@ -1112,7 +1277,7 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
Status = MmWriteToSwapPage(SwapEntry, Mdl); Status = MmWriteToSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("MM: Failed to write to swap page\n"); DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
/* /*
* As above: undo our actions. * As above: undo our actions.
* FIXME: Also free the swap page. * FIXME: Also free the swap page.
@ -1129,13 +1294,13 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
} }
else else
{ {
if (!DirectMapped) Status = MmCreateVirtualMapping(MemoryArea->Process,
{ Address,
MemoryArea->Attributes,
(ULONG)PhysicalAddress);
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, (ULONG)PhysicalAddress); MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, (ULONG)PhysicalAddress);
MmSharePageEntrySectionSegment(Segment, Offset.QuadPart); MmSharePageEntrySectionSegment(Segment, Offset.QuadPart);
} }
}
PageOp->Status = STATUS_UNSUCCESSFUL; PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
MmReleasePageOp(PageOp); MmReleasePageOp(PageOp);
@ -1145,9 +1310,23 @@ MmPageOutSectionView(PMADDRESS_SPACE AddressSpace,
/* /*
* Otherwise we have succeeded. * Otherwise we have succeeded.
*/ */
if (!DirectMapped) DPRINT1("MM: Wrote section page to swap!\n");
{
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
if (Private)
{
Status = MmCreatePageFileMapping(MemoryArea->Process,
Address,
SwapEntry);
if (!NT_SUCCESS(Status))
{
KeBugCheck(0);
}
}
else
{
Entry = MAKE_SWAP_SSE(SwapEntry);
MmSetPageEntrySectionSegment(Segment, Offset.QuadPart, Entry);
} }
PageOp->Status = STATUS_SUCCESS; PageOp->Status = STATUS_SUCCESS;
@ -2166,14 +2345,18 @@ NtMapViewOfSection(HANDLE SectionHandle,
VOID STATIC VOID STATIC
MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr, MmFreeSectionPage(PVOID Context, MEMORY_AREA* MemoryArea, PVOID Address, ULONG PhysAddr,
BOOLEAN Dirty) SWAPENTRY SwapEntry, BOOLEAN Dirty)
{ {
PMEMORY_AREA MArea; PMEMORY_AREA MArea;
ULONG Entry; ULONG Entry;
MArea = (PMEMORY_AREA)Context; MArea = (PMEMORY_AREA)Context;
if (PhysAddr != 0) if (SwapEntry != 0)
{
MmFreeSwapPage(SwapEntry);
}
else if (PhysAddr != 0)
{ {
ULONG Offset; ULONG Offset;

315
reactos/ntoskrnl/mm/slab.c Normal file
View file

@ -0,0 +1,315 @@
/*
* ReactOS kernel
* Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Id: slab.c,v 1.1 2001/12/31 19:06:48 dwelch Exp $
*
* COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel
* FILE: ntoskrnl/mm/slab.c
* PURPOSE: kernel memory managment functions
* PROGRAMMER: David Welch (welch@cwcom.net)
* UPDATE HISTORY:
* Created 27/12/01
*/
/* INCLUDES *****************************************************************/
#include <ddk/ntddk.h>
#include <internal/mm.h>
#define NDEBUG
#include <internal/debug.h>
/* TYPES ********************************************************************/
typedef VOID (*SLAB_CACHE_CONSTRUCTOR)(VOID*, ULONG);
typedef VOID (*SLAB_CACHE_DESTRUCTOR)(VOID*, ULONG);
struct _SLAB_CACHE_PAGE;
typedef struct _SLAB_CACHE
{
SLAB_CACHE_CONSTRUCTOR Constructor;
SLAB_CACHE_DESTRUCTOR Destructor;
ULONG BaseSize;
ULONG ObjectSize;
ULONG ObjectsPerPage;
LIST_ENTRY PageListHead;
struct _SLAB_CACHE_PAGE* FirstFreePage;
KSPIN_LOCK SlabLock;
} SLAB_CACHE, *PSLAB_CACHE;
typedef struct _SLAB_CACHE_BUFCTL
{
struct _SLAB_CACHE_BUFCTL* NextFree;
} SLAB_CACHE_BUFCTL, *PSLAB_CACHE_BUFCTL;
typedef struct _SLAB_CACHE_PAGE
{
LIST_ENTRY PageListEntry;
PSLAB_CACHE_BUFCTL FirstFreeBuffer;
ULONG ReferenceCount;
} SLAB_CACHE_PAGE, *PSLAB_CACHE_PAGE;
/* GLOBALS ******************************************************************/
/* FUNCTIONS ****************************************************************/
PSLAB_CACHE
ExCreateSlabCache(PUNICODE_STRING Name, ULONG Size, ULONG Align,
SLAB_CACHE_CONSTRUCTOR Constructor,
SLAB_CACHE_DESTRUCTOR Destructor)
{
PSLAB_CACHE Slab;
ULONG ObjectSize;
ULONG AlignSize;
Slab = ExAllocatePool(NonPagedPool, sizeof(SLAB_CACHE));
if (Slab == NULL)
{
return(NULL);
}
Slab->Constructor = Constructor;
Slab->Destructor = Destructor;
Slab->BaseSize = Size;
ObjectSize = Size + sizeof(SLAB_CACHE_BUFCTL);
AlignSize = Align - (ObjectSize % Align);
Slab->ObjectSize = ObjectSize + AlignSize;
Slab->ObjectsPerPage = (PAGESIZE - sizeof(SLAB_CACHE_PAGE)) / Slab->ObjectSize;
InitializeListHead(&Slab->PageListHead);
KeInitializeSpinLock(&Slab->SlabLock);
return(Slab);
}
PSLAB_CACHE_PAGE
ExGrowSlabCache(PSLAB_CACHE Slab)
{
PSLAB_CACHE_PAGE SlabPage;
PVOID PhysicalPage;
PVOID Page;
NTSTATUS Status;
ULONG i;
PSLAB_CACHE_BUFCTL BufCtl;
PVOID Object;
Status = MmRequestPageMemoryConsumer(MC_NPPOOL, TRUE, &PhysicalPage);
if (!NT_SUCCESS(Status))
{
return(NULL);
}
Page = ExAllocatePageWithPhysPage((ULONG)PhysicalPage);
if (Page == NULL)
{
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage);
return(NULL);
}
SlabPage = (PSLAB_CACHE_PAGE)(Page + PAGESIZE - sizeof(SLAB_CACHE_PAGE));
SlabPage->ReferenceCount = 0;
SlabPage->FirstFreeBuffer = (PSLAB_CACHE_BUFCTL)Page;
for (i = 0; i < Slab->ObjectsPerPage; i++)
{
BufCtl = (PSLAB_CACHE_BUFCTL)(Page + (i * Slab->ObjectSize));
Object = (PVOID)(BufCtl + 1);
if (Slab->Constructor != NULL)
{
Slab->Constructor(Object, Slab->BaseSize);
}
if (i == (Slab->ObjectsPerPage - 1))
{
BufCtl->NextFree = (PSLAB_CACHE_BUFCTL)(Page + ((i + 1) * Slab->ObjectSize));
}
else
{
BufCtl->NextFree = NULL;
}
}
return(SlabPage);
}
PVOID
ExAllocateSlabCache(PSLAB_CACHE Slab, BOOLEAN MayWait)
{
KIRQL oldIrql;
PSLAB_CACHE_PAGE Page;
PVOID Object;
BOOLEAN NewPage;
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
/*
* Check if there is a slab with free objects
* present, if so allocation from it, if
* not grow the slab.
*/
if (Slab->FirstFreePage == NULL)
{
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
Page = ExGrowSlabCache(Slab);
NewPage = TRUE;
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
}
else
{
Page = Slab->FirstFreePage;
NewPage = FALSE;
}
/*
* We shouldn't have got a page without free buffer.
*/
if (Page->FirstFreeBuffer == NULL)
{
DPRINT1("First free page had no free buffers.\n");
KeBugCheck(0);
}
/*
* Allocate the first free object from the page.
*/
Object = (PVOID)Page->FirstFreeBuffer + sizeof(SLAB_CACHE_BUFCTL);
Page->FirstFreeBuffer = Page->FirstFreeBuffer->NextFree;
Page->ReferenceCount++;
/*
* If we just allocate all the objects from this page
* and it was the first free page then adjust the
* first free page pointer and move the page to the head
* of the list.
*/
if (Page->ReferenceCount == Slab->ObjectsPerPage && !NewPage)
{
if (Page->PageListEntry.Flink == &Slab->PageListHead)
{
Slab->FirstFreePage = NULL;
}
else
{
PSLAB_CACHE_PAGE NextPage;
NextPage = CONTAINING_RECORD(Page->PageListEntry.Flink,
SLAB_CACHE_PAGE,
PageListEntry);
Slab->FirstFreePage = NextPage;
}
RemoveEntryList(&Page->PageListEntry);
InsertHeadList(&Slab->PageListHead, &Page->PageListEntry);
}
/*
* Otherwise if we created a new page then add it to the end of
* the page list.
*/
else if (NewPage)
{
InsertTailList(&Slab->PageListHead, &Page->PageListEntry);
if (Slab->FirstFreePage == NULL)
{
Slab->FirstFreePage = Page;
}
}
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
return(Object);
}
VOID
ExFreeFromPageSlabCache(PSLAB_CACHE Slab,
PSLAB_CACHE_PAGE Page,
PVOID Object)
{
PSLAB_CACHE_BUFCTL BufCtl;
BufCtl = (PSLAB_CACHE_BUFCTL)(Object - sizeof(SLAB_CACHE_BUFCTL));
BufCtl->NextFree = Page->FirstFreeBuffer;
Page->FirstFreeBuffer = BufCtl;
Page->ReferenceCount--;
}
VOID
ExFreeSlabCache(PSLAB_CACHE Slab, PVOID Object)
{
KIRQL oldIrql;
PLIST_ENTRY current_entry;
PSLAB_CACHE_PAGE current;
KeAcquireSpinLock(&Slab->SlabLock, &oldIrql);
current_entry = Slab->PageListHead.Flink;
while (current_entry != &Slab->PageListHead)
{
PVOID Base;
current = CONTAINING_RECORD(current_entry,
SLAB_CACHE_PAGE,
PageListEntry);
Base = (PVOID)current + sizeof(SLAB_CACHE_PAGE) - PAGESIZE;
if (Base >= Object &&
(Base + PAGESIZE - sizeof(SLAB_CACHE_PAGE)) >=
(Object + Slab->ObjectSize))
{
ExFreeFromPageSlabCache(Slab, current, Object);
/*
* If the page just become free then rearrange things.
*/
if (current->ReferenceCount == (Slab->ObjectsPerPage - 1))
{
RemoveEntryList(&current->PageListEntry);
InsertTailList(&Slab->PageListHead, &current->PageListEntry);
if (Slab->FirstFreePage == NULL)
{
Slab->FirstFreePage = current;
}
}
KeReleaseSpinLock(&Slab->SlabLock, oldIrql);
return;
}
}
DPRINT1("Tried to free object not in cache.\n");
KeBugCheck(0);
}
VOID
ExDestroySlabCache(PSLAB_CACHE Slab)
{
PLIST_ENTRY current_entry;
PSLAB_CACHE_PAGE current;
ULONG i;
PVOID Object;
current_entry = Slab->PageListHead.Flink;
while (current_entry != &Slab->PageListHead)
{
PVOID Base;
PVOID PhysicalPage;
current = CONTAINING_RECORD(current_entry,
SLAB_CACHE_PAGE,
PageListEntry);
Base = (PVOID)current + sizeof(SLAB_CACHE_PAGE) - PAGESIZE;
if (Slab->Destructor != NULL)
{
for (i = 0; i < Slab->ObjectsPerPage; i++)
{
Object = Base + (i * Slab->ObjectSize) + sizeof(SLAB_CACHE_BUFCTL);
Slab->Destructor(Object, Slab->BaseSize);
}
}
PhysicalPage = (PVOID)MmGetPhysicalAddressForProcess(NULL, Base);
ExUnmapPage(Base);
MmReleasePageMemoryConsumer(MC_NPPOOL, PhysicalPage);
}
ExFreePool(Slab);
}

View file

@ -1,4 +1,4 @@
/* $Id: virtual.c,v 1.51 2001/12/31 01:53:45 dwelch Exp $ /* $Id: virtual.c,v 1.52 2001/12/31 19:06:48 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top directory * COPYRIGHT: See COPYING in the top directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -156,7 +156,6 @@ MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
SwapEntry = MmAllocSwapPage(); SwapEntry = MmAllocSwapPage();
if (SwapEntry == 0) if (SwapEntry == 0)
{ {
DPRINT("MM: Out of swap space.\n");
MmEnableVirtualMapping(MemoryArea->Process, Address); MmEnableVirtualMapping(MemoryArea->Process, Address);
PageOp->Status = STATUS_UNSUCCESSFUL; PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
@ -173,7 +172,7 @@ MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
Status = MmWriteToSwapPage(SwapEntry, Mdl); Status = MmWriteToSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
{ {
DPRINT1("MM: Failed to write to swap page\n"); DPRINT1("MM: Failed to write to swap page (Status was 0x%.8X)\n", Status);
MmEnableVirtualMapping(MemoryArea->Process, Address); MmEnableVirtualMapping(MemoryArea->Process, Address);
PageOp->Status = STATUS_UNSUCCESSFUL; PageOp->Status = STATUS_UNSUCCESSFUL;
KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE); KeSetEvent(&PageOp->CompletionEvent, IO_NO_INCREMENT, FALSE);
@ -184,7 +183,9 @@ MmPageOutVirtualMemory(PMADDRESS_SPACE AddressSpace,
/* /*
* Otherwise we have succeeded, free the page * Otherwise we have succeeded, free the page
*/ */
DPRINT1("MM: Swapped out virtual memory swap!\n");
MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL); MmDeleteVirtualMapping(MemoryArea->Process, Address, FALSE, NULL, NULL);
MmCreatePageFileMapping(MemoryArea->Process, Address, SwapEntry);
MmDeleteAllRmaps(PhysicalAddress, NULL, NULL); MmDeleteAllRmaps(PhysicalAddress, NULL, NULL);
MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress); MmReleasePageMemoryConsumer(MC_USER, PhysicalAddress);
PageOp->Status = STATUS_SUCCESS; PageOp->Status = STATUS_SUCCESS;
@ -314,6 +315,24 @@ MmNotPresentFaultVirtualMemory(PMADDRESS_SPACE AddressSpace,
MmLockAddressSpace(AddressSpace); MmLockAddressSpace(AddressSpace);
} }
/*
* Handle swapped out pages.
*/
if (MmIsPageSwapEntry(NULL, Address))
{
SWAPENTRY SwapEntry;
PMDL Mdl;
MmDeletePageFileMapping(NULL, Address, &SwapEntry);
Mdl = MmCreateMdl(NULL, NULL, PAGESIZE);
MmBuildMdlFromPages(Mdl, (PULONG)&Page);
Status = MmReadFromSwapPage(SwapEntry, Mdl);
if (!NT_SUCCESS(Status))
{
KeBugCheck(0);
}
}
/* /*
* Set the page. If we fail because we are out of memory then * Set the page. If we fail because we are out of memory then
* try again * try again
@ -381,6 +400,18 @@ MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
{ {
LARGE_INTEGER PhysicalAddr; LARGE_INTEGER PhysicalAddr;
if (MmIsPageSwapEntry(AddressSpace->Process,
BaseAddress + (i * PAGESIZE)))
{
SWAPENTRY SwapEntry;
MmDeletePageFileMapping(AddressSpace->Process,
BaseAddress + (i * PAGESIZE),
&SwapEntry);
MmFreeSwapPage(SwapEntry);
}
else
{
PhysicalAddr = MmGetPhysicalAddress(BaseAddress + (i*PAGESIZE)); PhysicalAddr = MmGetPhysicalAddress(BaseAddress + (i*PAGESIZE));
MmDeleteVirtualMapping(AddressSpace->Process, MmDeleteVirtualMapping(AddressSpace->Process,
BaseAddress + (i*PAGESIZE), BaseAddress + (i*PAGESIZE),
@ -393,6 +424,7 @@ MmModifyAttributes(PMADDRESS_SPACE AddressSpace,
} }
} }
} }
}
/* /*
* If we are changing the protection attributes of a committed region then * If we are changing the protection attributes of a committed region then
@ -1006,6 +1038,7 @@ MmFreeVirtualMemoryPage(PVOID Context,
MEMORY_AREA* MemoryArea, MEMORY_AREA* MemoryArea,
PVOID Address, PVOID Address,
ULONG PhysicalAddr, ULONG PhysicalAddr,
SWAPENTRY SwapEntry,
BOOLEAN Dirty) BOOLEAN Dirty)
{ {
PEPROCESS Process = (PEPROCESS)Context; PEPROCESS Process = (PEPROCESS)Context;
@ -1015,6 +1048,10 @@ MmFreeVirtualMemoryPage(PVOID Context,
MmDeleteRmap((PVOID)PhysicalAddr, Process, Address); MmDeleteRmap((PVOID)PhysicalAddr, Process, Address);
MmDereferencePage((PVOID)PhysicalAddr); MmDereferencePage((PVOID)PhysicalAddr);
} }
else if (SwapEntry != 0)
{
MmFreeSwapPage(SwapEntry);
}
} }
VOID VOID

View file

@ -16,7 +16,7 @@
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
/* $Id: handle.c,v 1.33 2001/11/20 02:29:45 dwelch Exp $ /* $Id: handle.c,v 1.34 2001/12/31 19:06:48 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -136,19 +136,27 @@ NTSTATUS STDCALL NtDuplicateObject (IN HANDLE SourceProcessHandle,
ASSERT_IRQL(PASSIVE_LEVEL); ASSERT_IRQL(PASSIVE_LEVEL);
ObReferenceObjectByHandle(SourceProcessHandle, Status = ObReferenceObjectByHandle(SourceProcessHandle,
PROCESS_DUP_HANDLE, PROCESS_DUP_HANDLE,
NULL, NULL,
UserMode, UserMode,
(PVOID*)&SourceProcess, (PVOID*)&SourceProcess,
NULL); NULL);
ObReferenceObjectByHandle(TargetProcessHandle, if (!NT_SUCCESS(Status))
{
return(Status);
}
Status = ObReferenceObjectByHandle(TargetProcessHandle,
PROCESS_DUP_HANDLE, PROCESS_DUP_HANDLE,
NULL, NULL,
UserMode, UserMode,
(PVOID*)&TargetProcess, (PVOID*)&TargetProcess,
NULL); NULL);
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(SourceProcess);
return(Status);
}
KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql); KeAcquireSpinLock(&SourceProcess->HandleTable.ListLock, &oldIrql);
SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable, SourceHandleRep = ObpGetObjectByHandle(&SourceProcess->HandleTable,
SourceHandle); SourceHandle);

View file

@ -1,4 +1,4 @@
/* $Id: thread.c,v 1.80 2001/12/05 01:40:25 dwelch Exp $ /* $Id: thread.c,v 1.81 2001/12/31 19:06:48 dwelch Exp $
* *
* COPYRIGHT: See COPYING in the top level directory * COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS kernel * PROJECT: ReactOS kernel
@ -83,19 +83,21 @@ PsInsertIntoThreadList(KPRIORITY Priority, PETHREAD Thread)
PiNrRunnableThreads++; PiNrRunnableThreads++;
} }
VOID PsDumpThreads(VOID) VOID PsDumpThreads(BOOLEAN IncludeSystem)
{ {
PLIST_ENTRY current_entry; PLIST_ENTRY current_entry;
PETHREAD current; PETHREAD current;
ULONG t; ULONG t;
ULONG i;
// return;
current_entry = PiThreadListHead.Flink; current_entry = PiThreadListHead.Flink;
t = 0; t = 0;
while (current_entry != &PiThreadListHead) while (current_entry != &PiThreadListHead)
{ {
PULONG Ebp;
PULONG Esp;
current = CONTAINING_RECORD(current_entry, ETHREAD, current = CONTAINING_RECORD(current_entry, ETHREAD,
Tcb.ThreadListEntry); Tcb.ThreadListEntry);
t++; t++;
@ -104,14 +106,31 @@ VOID PsDumpThreads(VOID)
DbgPrint("Too many threads on list\n"); DbgPrint("Too many threads on list\n");
return; return;
} }
DbgPrint("current %x current->Tcb.State %d eip %x/%x ", if (IncludeSystem || current->ThreadsProcess->UniqueProcessId >= 6)
current, current->Tcb.State, {
0, current->Tcb.LastEip); DbgPrint("current->Tcb.State %d PID.TID %d.%d Name %.8s\n",
// KeDumpStackFrames((PVOID)current->Tcb.KernelStack, current->Tcb.State, current->ThreadsProcess->UniqueProcessId,
// 16); current->Cid.UniqueThread, current->ThreadsProcess->ImageFileName);
DbgPrint("PID %d ", current->ThreadsProcess->UniqueProcessId); if (current->Tcb.State == THREAD_STATE_RUNNABLE ||
current->Tcb.State == THREAD_STATE_SUSPENDED ||
current->Tcb.State == THREAD_STATE_BLOCKED)
{
Esp = (PULONG)current->Tcb.KernelStack;
Ebp = (PULONG)Esp[3];
DbgPrint("Ebp 0x%.8X\n", Ebp);
i = 0;
while (Ebp != 0 && Ebp >= (PULONG)current->Tcb.StackLimit)
{
DbgPrint("Frame: 0x%.8X Eip: 0x%.8X%s", Ebp[0], Ebp[1],
(i % 2) == 1 ? "\n" : "");
Ebp = (PULONG)Ebp[0];
}
if ((i % 2) == 0)
{
DbgPrint("\n"); DbgPrint("\n");
}
}
}
current_entry = current_entry->Flink; current_entry = current_entry->Flink;
} }
} }

View file

@ -1,4 +1,4 @@
/* $Id: init.c,v 1.28 2001/12/02 23:37:25 dwelch Exp $ /* $Id: init.c,v 1.29 2001/12/31 19:06:49 dwelch Exp $
* *
* init.c - Session Manager initialization * init.c - Session Manager initialization
* *
@ -58,6 +58,7 @@ PWSTR SmSystemEnvironment = NULL;
/* FUNCTIONS ****************************************************************/ /* FUNCTIONS ****************************************************************/
#if 0
static VOID static VOID
SmCreatePagingFiles (VOID) SmCreatePagingFiles (VOID)
{ {
@ -126,27 +127,38 @@ SmCreatePagingFiles (VOID)
} }
} }
} }
#endif
#if 0 #if 1
static VOID static VOID
SmCreatePagingFiles (VOID) SmCreatePagingFiles (VOID)
{ {
UNICODE_STRING FileName; UNICODE_STRING FileName;
ULONG ulCurrentSize; ULONG ulCurrentSize;
NTSTATUS Status;
/* FIXME: Read file names from registry */ /* FIXME: Read file names from registry */
RtlInitUnicodeString (&FileName, RtlInitUnicodeString (&FileName,
L"\\SystemRoot\\pagefile.sys"); L"\\SystemRoot\\pagefile.sys");
NtCreatePagingFile (&FileName, Status = NtCreatePagingFile (&FileName,
50, 50,
80, 80,
&ulCurrentSize); &ulCurrentSize);
if (!NT_SUCCESS(Status))
{
PrintString("SM: Failed to create paging file (Status was 0x%.8X)\n", Status);
}
}
#else
static VOID
SmCreatePagingFiles (VOID)
{
/* Nothing. */
} }
#endif #endif
static VOID static VOID
SmInitDosDevices(VOID) SmInitDosDevices(VOID)
{ {
@ -437,7 +449,7 @@ BOOL InitSessionManager (HANDLE Children[])
/* FIXME: Load the well known DLLs */ /* FIXME: Load the well known DLLs */
/* Create paging files */ /* Create paging files */
// SmCreatePagingFiles (); SmCreatePagingFiles ();
/* Load remaining registry hives */ /* Load remaining registry hives */
NtInitializeRegistry (FALSE); NtInitializeRegistry (FALSE);