0d7249bafdf488d3900a5a2c65a1394125a50425
[reactos.git] / reactos / ntoskrnl / mm / pagefile.c
1 /* $Id: pagefile.c,v 1.3 2000/03/26 19:38:32 ea Exp $
2 *
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)
8 * UPDATE HISTORY:
9 * Created 22/05/98
10 */
11
12 /* INCLUDES *****************************************************************/
13
14 #include <ddk/ntddk.h>
15 #include <internal/bitops.h>
16 #include <internal/io.h>
17
18 #include <internal/debug.h>
19
20 /* TYPES *********************************************************************/
21
22 typedef ULONG SWAPENTRY;
23
24 typedef struct _PPAGINGFILE
25 {
26 LIST_ENTRY PagingFileListEntry;
27 PFILE_OBJECT FileObject;
28 ULONG MaximumSize;
29 ULONG CurrentSize;
30 ULONG FreePages;
31 ULONG UsedPages;
32 PULONG AllocMap;
33 KSPIN_LOCK AllocMapLock;
34 ULONG AllocMapSize;
35 } PAGINGFILE, *PPAGINGFILE;
36
37 /* GLOBALS *******************************************************************/
38
39 #define MAX_PAGING_FILES (32)
40
41 static PPAGINGFILE PagingFileList[MAX_PAGING_FILES];
42 static KSPIN_LOCK PagingFileListLock;
43
44 static ULONG MiFreeSwapPages;
45 static ULONG MiUsedSwapPages;
46 static ULONG MiReservedSwapPages;
47
48 /* FUNCTIONS *****************************************************************/
49
50 VOID MmInitPagingFile(VOID)
51 {
52 KeInitializeSpinLock(&PagingFileListLock);
53
54 MiFreeSwapPages = 0;
55 MiUsedSwapPages = 0;
56 MiReservedSwapPages = 0;
57 }
58
59 VOID MmReserveSwapPages(ULONG Nr)
60 {
61 KIRQL oldIrql;
62
63 KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
64 MiReservedSwapPages = MiReservedSwapPages + Nr;
65 MiFreeSwapPages = MiFreeSwapPages - Nr;
66 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
67 }
68
69 VOID MmDereserveSwapPages(ULONG Nr)
70 {
71 KIRQL oldIrql;
72
73 KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
74 MiReservedSwapPages = MiReservedSwapPages - Nr;
75 MiFreeSwapPages = MiFreeSwapPages - Nr;
76 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
77 }
78
79 ULONG MiAllocPageFromPagingFile(PPAGINGFILE PagingFile)
80 {
81 KIRQL oldIrql;
82 ULONG i;
83 ULONG off;
84
85 KeAcquireSpinLock(&PagingFile->AllocMapLock, &oldIrql);
86
87 for (i = 0; i < PagingFile->AllocMapSize; i++)
88 {
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);
95 return(off + 1);
96 }
97
98 KeReleaseSpinLock(&PagingFile->AllocMapLock, oldIrql);
99 return(0);
100 }
101
102 VOID MmFreeSwapPage(SWAPENTRY Entry)
103 {
104 ULONG i;
105 ULONG off;
106 KIRQL oldIrql;
107
108 i = (Entry >> 24) - 1;
109 off = Entry & 0xffffff;
110
111 KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
112 KeAcquireSpinLockAtDpcLevel(&PagingFileList[i]->AllocMapLock);
113
114 set_bit(off % 32, &PagingFileList[i]->AllocMap[off / 32]);
115
116 PagingFileList[i]->FreePages++;
117 PagingFileList[i]->UsedPages--;
118
119 MiFreeSwapPages++;
120 MiUsedSwapPages--;
121
122 KeReleaseSpinLockFromDpcLevel(&PagingFileList[i]->AllocMapLock);
123 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
124 }
125
126 SWAPENTRY MmAllocSwapPage(VOID)
127 {
128 KIRQL oldIrql;
129 ULONG i;
130 ULONG off;
131 SWAPENTRY entry;
132
133 KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
134
135 if (MiFreeSwapPages == 0)
136 {
137 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
138 return(0);
139 }
140
141 for (i = 0; i < MAX_PAGING_FILES; i++)
142 {
143 if (PagingFileList[i] != NULL &&
144 PagingFileList[i]->FreePages >= 1)
145 {
146 off = MiAllocPageFromPagingFile(PagingFileList[i]);
147 MiUsedSwapPages++;
148 MiFreeSwapPages--;
149 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
150
151 entry = ((i+1) << 24) || off;
152 return(entry);
153 }
154 }
155
156 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
157 return(0);
158 }
159
160 NTSTATUS STDCALL NtCreatePagingFile(IN PUNICODE_STRING PageFileName,
161 IN ULONG MinimumSize,
162 IN ULONG MaximumSize,
163 OUT PULONG ActualSize)
164 {
165 NTSTATUS Status;
166 OBJECT_ATTRIBUTES ObjectAttributes;
167 HANDLE FileHandle;
168 IO_STATUS_BLOCK IoStatus;
169 PFILE_OBJECT FileObject;
170 PPAGINGFILE PagingFile;
171 KIRQL oldIrql;
172 ULONG AllocMapSize;
173 ULONG i;
174
175 InitializeObjectAttributes(&ObjectAttributes,
176 PageFileName,
177 0,
178 NULL,
179 NULL);
180 Status = NtCreateFile(&FileHandle,
181 FILE_ALL_ACCESS,
182 &ObjectAttributes,
183 &IoStatus,
184 NULL,
185 0,
186 0,
187 FILE_OPEN,
188 FILE_SYNCHRONOUS_IO_NONALERT,
189 NULL,
190 0);
191 if (!NT_SUCCESS(Status))
192 {
193 return(Status);
194 }
195
196 Status = ObReferenceObjectByHandle(FileHandle,
197 FILE_ALL_ACCESS,
198 IoFileObjectType,
199 UserMode,
200 (PVOID*)&FileObject,
201 NULL);
202 if (!NT_SUCCESS(Status))
203 {
204 NtClose(FileHandle);
205 return(Status);
206 }
207
208 NtClose(FileHandle);
209
210 PagingFile = ExAllocatePool(NonPagedPool, sizeof(*PagingFile));
211 if (PagingFile == NULL)
212 {
213 ObDereferenceObject(FileObject);
214 return(STATUS_NO_MEMORY);
215 }
216
217 PagingFile->FileObject = FileObject;
218 PagingFile->MaximumSize = PagingFile->CurrentSize = MinimumSize;
219 PagingFile->FreePages = MinimumSize;
220 PagingFile->UsedPages = 0;
221 KeInitializeSpinLock(&PagingFile->AllocMapLock);
222
223 AllocMapSize = (MinimumSize / 32) + 1;
224 PagingFile->AllocMap = ExAllocatePool(NonPagedPool,
225 AllocMapSize * sizeof(ULONG));
226 PagingFile->AllocMapSize = AllocMapSize;
227
228 if (PagingFile->AllocMap == NULL)
229 {
230 ExFreePool(PagingFile);
231 ObDereferenceObject(FileObject);
232 return(STATUS_NO_MEMORY);
233 }
234
235 KeAcquireSpinLock(&PagingFileListLock, &oldIrql);
236 for (i = 0; i < MAX_PAGING_FILES; i++)
237 {
238 if (PagingFileList[i] == NULL)
239 {
240 PagingFileList[i] = PagingFile;
241 break;
242 }
243 }
244 MiFreeSwapPages = MiFreeSwapPages + MinimumSize;
245 KeReleaseSpinLock(&PagingFileListLock, oldIrql);
246
247 return(STATUS_SUCCESS);
248 }
249
250
251 /* EOF */