1 /* $Id: pagefile.c,v 1.3 2000/03/26 19:38:32 ea 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>
18 #include <internal/debug.h>
20 /* TYPES *********************************************************************/
22 typedef ULONG SWAPENTRY
;
24 typedef struct _PPAGINGFILE
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 /* FUNCTIONS *****************************************************************/
50 VOID
MmInitPagingFile(VOID
)
52 KeInitializeSpinLock(&PagingFileListLock
);
56 MiReservedSwapPages
= 0;
59 VOID
MmReserveSwapPages(ULONG Nr
)
63 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
64 MiReservedSwapPages
= MiReservedSwapPages
+ Nr
;
65 MiFreeSwapPages
= MiFreeSwapPages
- Nr
;
66 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
69 VOID
MmDereserveSwapPages(ULONG Nr
)
73 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
74 MiReservedSwapPages
= MiReservedSwapPages
- Nr
;
75 MiFreeSwapPages
= MiFreeSwapPages
- Nr
;
76 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
79 ULONG
MiAllocPageFromPagingFile(PPAGINGFILE PagingFile
)
85 KeAcquireSpinLock(&PagingFile
->AllocMapLock
, &oldIrql
);
87 for (i
= 0; i
< PagingFile
->AllocMapSize
; i
++)
89 off
= find_first_zero_bit(PagingFile
->AllocMap
,
90 PagingFile
->AllocMapSize
* 32);
91 clear_bit(off
% 32, &PagingFile
->AllocMap
[off
/ 32]);
92 PagingFile
->UsedPages
--;
93 PagingFile
->FreePages
++;
94 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
98 KeReleaseSpinLock(&PagingFile
->AllocMapLock
, oldIrql
);
102 VOID
MmFreeSwapPage(SWAPENTRY Entry
)
108 i
= (Entry
>> 24) - 1;
109 off
= Entry
& 0xffffff;
111 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
112 KeAcquireSpinLockAtDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
114 set_bit(off
% 32, &PagingFileList
[i
]->AllocMap
[off
/ 32]);
116 PagingFileList
[i
]->FreePages
++;
117 PagingFileList
[i
]->UsedPages
--;
122 KeReleaseSpinLockFromDpcLevel(&PagingFileList
[i
]->AllocMapLock
);
123 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
126 SWAPENTRY
MmAllocSwapPage(VOID
)
133 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
135 if (MiFreeSwapPages
== 0)
137 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
141 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
143 if (PagingFileList
[i
] != NULL
&&
144 PagingFileList
[i
]->FreePages
>= 1)
146 off
= MiAllocPageFromPagingFile(PagingFileList
[i
]);
149 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
151 entry
= ((i
+1) << 24) || off
;
156 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
160 NTSTATUS STDCALL
NtCreatePagingFile(IN PUNICODE_STRING PageFileName
,
161 IN ULONG MinimumSize
,
162 IN ULONG MaximumSize
,
163 OUT PULONG ActualSize
)
166 OBJECT_ATTRIBUTES ObjectAttributes
;
168 IO_STATUS_BLOCK IoStatus
;
169 PFILE_OBJECT FileObject
;
170 PPAGINGFILE PagingFile
;
175 InitializeObjectAttributes(&ObjectAttributes
,
180 Status
= NtCreateFile(&FileHandle
,
188 FILE_SYNCHRONOUS_IO_NONALERT
,
191 if (!NT_SUCCESS(Status
))
196 Status
= ObReferenceObjectByHandle(FileHandle
,
202 if (!NT_SUCCESS(Status
))
210 PagingFile
= ExAllocatePool(NonPagedPool
, sizeof(*PagingFile
));
211 if (PagingFile
== NULL
)
213 ObDereferenceObject(FileObject
);
214 return(STATUS_NO_MEMORY
);
217 PagingFile
->FileObject
= FileObject
;
218 PagingFile
->MaximumSize
= PagingFile
->CurrentSize
= MinimumSize
;
219 PagingFile
->FreePages
= MinimumSize
;
220 PagingFile
->UsedPages
= 0;
221 KeInitializeSpinLock(&PagingFile
->AllocMapLock
);
223 AllocMapSize
= (MinimumSize
/ 32) + 1;
224 PagingFile
->AllocMap
= ExAllocatePool(NonPagedPool
,
225 AllocMapSize
* sizeof(ULONG
));
226 PagingFile
->AllocMapSize
= AllocMapSize
;
228 if (PagingFile
->AllocMap
== NULL
)
230 ExFreePool(PagingFile
);
231 ObDereferenceObject(FileObject
);
232 return(STATUS_NO_MEMORY
);
235 KeAcquireSpinLock(&PagingFileListLock
, &oldIrql
);
236 for (i
= 0; i
< MAX_PAGING_FILES
; i
++)
238 if (PagingFileList
[i
] == NULL
)
240 PagingFileList
[i
] = PagingFile
;
244 MiFreeSwapPages
= MiFreeSwapPages
+ MinimumSize
;
245 KeReleaseSpinLock(&PagingFileListLock
, oldIrql
);
247 return(STATUS_SUCCESS
);