1 /* $Id: pagefile.c,v 1.8 2001/01/08 02:14:06 dwelch Exp $
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/pagefile.c
6 * PURPOSE: Paging file functions
7 * PROGRAMMER: David Welch (welch@mcmail.com)
12 /* INCLUDES *****************************************************************/
14 #include <ddk/ntddk.h>
15 #include <internal/bitops.h>
16 #include <internal/io.h>
17 #include <internal/mm.h>
18 #include <napi/core.h>
20 #include <internal/debug.h>
22 /* TYPES *********************************************************************/
24 typedef struct _PAGINGFILE
26 LIST_ENTRY PagingFileListEntry
;
27 PFILE_OBJECT FileObject
;
33 KSPIN_LOCK AllocMapLock
;
35 } PAGINGFILE
, *PPAGINGFILE
;
37 /* GLOBALS *******************************************************************/
39 #define MAX_PAGING_FILES (32)
41 static PPAGINGFILE PagingFileList
[MAX_PAGING_FILES
];
42 static KSPIN_LOCK PagingFileListLock
;
44 static ULONG MiFreeSwapPages
;
45 static ULONG MiUsedSwapPages
;
46 static ULONG MiReservedSwapPages
;
48 #define MM_PAGEFILE_COMMIT_RATIO (1)
49 #define MM_PAGEFILE_COMMIT_GRACE (256)
52 static PVOID MmCoreDumpPageFrame
;
53 static BYTE MmCoreDumpHeader
[PAGESIZE
];
56 #define FILE_FROM_ENTRY(i) ((i) >> 24)
57 #define OFFSET_FROM_ENTRY(i) (((i) & 0xffffff) - 1)
59 #define ENTRY_FROM_FILE_OFFSET(i, j) (((i) << 24) || ((j) + 1))
61 /* FUNCTIONS *****************************************************************/
63 NTSTATUS
MmWriteToSwapPage(SWAPENTRY SwapEntry
, PMDL Mdl
)
66 LARGE_INTEGER file_offset
;
73 return(STATUS_UNSUCCESSFUL
);
76 i
= FILE_FROM_ENTRY(SwapEntry
);
77 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
79 file_offset
.QuadPart
= offset
* 4096;
81 Status
= IoPageWrite(PagingFileList
[i
]->FileObject
,
88 NTSTATUS
MmReadFromSwapPage(SWAPENTRY SwapEntry
, PMDL Mdl
)
91 LARGE_INTEGER file_offset
;
98 return(STATUS_UNSUCCESSFUL
);
101 i
= FILE_FROM_ENTRY(SwapEntry
);
102 offset
= OFFSET_FROM_ENTRY(SwapEntry
);
104 file_offset
.QuadPart
= offset
* 4096;
106 Status
= IoPageRead(PagingFileList
[i
]->FileObject
,
113 VOID
MmInitPagingFile(VOID
)
117 KeInitializeSpinLock(&PagingFileListLock
);
121 MiReservedSwapPages
= 0;
123 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
125 PagingFileList
[i
] = NULL
;
129 VOID
MmReserveSwapPages(ULONG Nr
)
133 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
134 MiReservedSwapPages
= MiReservedSwapPages
+ Nr
;
135 // MiFreeSwapPages = MiFreeSwapPages - Nr;
136 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
139 VOID
MmDereserveSwapPages(ULONG Nr
)
143 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
144 MiReservedSwapPages
= MiReservedSwapPages
- Nr
;
145 // MiFreeSwapPages = MiFreeSwapPages - Nr;
146 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
149 ULONG
MiAllocPageFromPagingFile(PPAGINGFILE PagingFile
)
155 KeAcquireSpinLock(&PagingFile
->AllocMapLock
, &oldIrql
);
157 for (i
= 0; i
< PagingFile
->AllocMapSize
; i
++)
159 off
= find_first_zero_bit(PagingFile
->AllocMap
,
160 PagingFile
->AllocMapSize
* 32);
161 clear_bit(off
% 32, &PagingFile
->AllocMap
[off
/ 32]);
162 PagingFile
->UsedPages
--;
163 PagingFile
->FreePages
++;
164 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
168 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
172 VOID
MmFreeSwapPage(SWAPENTRY Entry
)
178 i
= FILE_FROM_ENTRY(Entry
);
179 off
= OFFSET_FROM_ENTRY(Entry
);
181 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
182 KeAcquireSpinLockAtDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
184 set_bit(off
% 32, &PagingFileList
[i
]->AllocMap
[off
/ 32]);
186 PagingFileList
[i
]->FreePages
++;
187 PagingFileList
[i
]->UsedPages
--;
192 KeReleaseSpinLockFromDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
193 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
196 SWAPENTRY
MmAllocSwapPage(VOID
)
203 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
205 if (MiFreeSwapPages
== 0)
207 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
211 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
213 if (PagingFileList
[i
] != NULL
&&
214 PagingFileList
[i
]->FreePages
>= 1)
216 off
= MiAllocPageFromPagingFile(PagingFileList
[i
]);
220 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
221 return(STATUS_UNSUCCESSFUL
);
225 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
227 entry
= ENTRY_FROM_FILE_OFFSET(i
, off
);
232 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
237 NTSTATUS STDCALL
MmDumpToPagingFile(PCONTEXT Context
,
242 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->Magic
=
243 MM_CORE_DUMP_HEADER_MAGIC
;
244 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->Version
=
245 MM_CORE_DUMP_HEADER_VERSION
;
246 memcpy(&((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->Context
,
249 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->DumpLength
= 0;
250 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->BugCode
= BugCode
;
251 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->ExceptionCode
=
253 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->Cr2
= Cr2
;
254 ((PMM_CORE_DUMP_HEADER
)MmCoreDumpHeader
)->Cr3
= 0;
258 NTSTATUS STDCALL
NtCreatePagingFile(IN PUNICODE_STRING PageFileName
,
259 IN ULONG MinimumSize
,
260 IN ULONG MaximumSize
,
261 OUT PULONG ActualSize
)
264 OBJECT_ATTRIBUTES ObjectAttributes
;
266 IO_STATUS_BLOCK IoStatus
;
267 PFILE_OBJECT FileObject
;
268 PPAGINGFILE PagingFile
;
273 InitializeObjectAttributes(&ObjectAttributes
,
278 Status
= NtCreateFile(&FileHandle
,
286 FILE_SYNCHRONOUS_IO_NONALERT
,
289 if (!NT_SUCCESS(Status
))
294 Status
= ObReferenceObjectByHandle(FileHandle
,
300 if (!NT_SUCCESS(Status
))
308 PagingFile
= ExAllocatePool(NonPagedPool
, sizeof(*PagingFile
));
309 if (PagingFile
== NULL
)
311 ObDereferenceObject(FileObject
);
312 return(STATUS_NO_MEMORY
);
315 PagingFile
->FileObject
= FileObject
;
316 PagingFile
->MaximumSize
= PagingFile
->CurrentSize
= MinimumSize
;
317 PagingFile
->FreePages
= MinimumSize
;
318 PagingFile
->UsedPages
= 0;
319 KeInitializeSpinLock(&PagingFile
->AllocMapLock
);
321 AllocMapSize
= (MinimumSize
/ 32) + 1;
322 PagingFile
->AllocMap
= ExAllocatePool(NonPagedPool
,
323 AllocMapSize
* sizeof(ULONG
));
324 PagingFile
->AllocMapSize
= AllocMapSize
;
326 if (PagingFile
->AllocMap
== NULL
)
328 ExFreePool(PagingFile
);
329 ObDereferenceObject(FileObject
);
330 return(STATUS_NO_MEMORY
);
333 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
334 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
336 if (PagingFileList
[i
] == NULL
)
338 PagingFileList
[i
] = PagingFile
;
342 MiFreeSwapPages
= MiFreeSwapPages
+ MinimumSize
;
343 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
345 return(STATUS_SUCCESS
);