2 * Copyright (C) 1998-2005 ReactOS Team (and the authors from the programmers section)
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19 * PROJECT: ReactOS kernel
20 * FILE: ntoskrnl/cache/section/reqtools.c
21 * PURPOSE: Implements section objects
23 * PROGRAMMERS: Rex Jolliff
36 * Thomas Weidenmueller
37 * Gunnar Andre' Dalsnes
46 This file contains functions used by fault.c to do blocking resource
47 acquisition. To call one of these functions, fill out your
48 MM_REQUIRED_RESOURCES with a pointer to the desired function and configure
49 the other members as below.
52 /* INCLUDES *****************************************************************/
59 #define DPRINTC DPRINT
63 MmBuildMdlFromPages(PMDL Mdl
, PPFN_NUMBER Pages
);
67 Blocking function to acquire zeroed pages from the balancer.
71 Required->Amount: Number of pages to acquire
72 Required->Consumer: consumer to charge the page to
76 Required->Pages[0..Amount]: Allocated pages.
78 The function fails unless all requested pages can be allocated.
83 MiGetOnePage(PMMSUPPORT AddressSpace
,
84 PMEMORY_AREA MemoryArea
,
85 PMM_REQUIRED_RESOURCES Required
)
88 NTSTATUS Status
= STATUS_SUCCESS
;
90 for (i
= 0; i
< Required
->Amount
; i
++)
92 DPRINTC("MiGetOnePage(%s:%d)\n", Required
->File
, Required
->Line
);
93 Status
= MmRequestPageMemoryConsumer(Required
->Consumer
,
96 if (!NT_SUCCESS(Status
))
100 MmReleasePageMemoryConsumer(Required
->Consumer
,
101 Required
->Page
[i
-1]);
113 Blocking function to read (part of) a page from a file.
117 Required->Context: a FILE_OBJECT to read
118 Required->Consumer: consumer to charge the page to
119 Required->FileOffset: Offset to read at
120 Required->Amount: Number of bytes to read (0 -> 4096)
124 Required->Page[Required->Offset]: The allocated and read in page
126 The indicated page is filled to Required->Amount with file data and zeroed
133 MiReadFilePage(PMMSUPPORT AddressSpace
,
134 PMEMORY_AREA MemoryArea
,
135 PMM_REQUIRED_RESOURCES RequiredResources
)
137 PFILE_OBJECT FileObject
= RequiredResources
->Context
;
138 PPFN_NUMBER Page
= &RequiredResources
->Page
[RequiredResources
->Offset
];
139 PLARGE_INTEGER FileOffset
= &RequiredResources
->FileOffset
;
141 PVOID PageBuf
= NULL
;
143 IO_STATUS_BLOCK IOSB
;
144 UCHAR MdlBase
[sizeof(MDL
) + sizeof(ULONG
)];
145 PMDL Mdl
= (PMDL
)MdlBase
;
148 DPRINTC("Pulling page %I64x from %wZ to %Ix\n",
149 FileOffset
->QuadPart
,
150 &FileObject
->FileName
,
153 Status
= MmRequestPageMemoryConsumer(RequiredResources
->Consumer
,
157 if (!NT_SUCCESS(Status
))
159 DPRINT1("Status: %x\n", Status
);
163 MmInitializeMdl(Mdl
, NULL
, PAGE_SIZE
);
164 MmBuildMdlFromPages(Mdl
, Page
);
165 Mdl
->MdlFlags
|= MDL_PAGES_LOCKED
;
167 KeInitializeEvent(&Event
, NotificationEvent
, FALSE
);
168 Status
= IoPageRead(FileObject
, Mdl
, FileOffset
, &Event
, &IOSB
);
169 if (Status
== STATUS_PENDING
)
171 KeWaitForSingleObject(&Event
, Executive
, KernelMode
, FALSE
, NULL
);
172 Status
= IOSB
.Status
;
174 if (Mdl
->MdlFlags
& MDL_MAPPED_TO_SYSTEM_VA
)
176 MmUnmapLockedPages (Mdl
->MappedSystemVa
, Mdl
);
179 PageBuf
= MiMapPageInHyperSpace(PsGetCurrentProcess(), *Page
, &OldIrql
);
182 MmReleasePageMemoryConsumer(RequiredResources
->Consumer
, *Page
);
183 return STATUS_NO_MEMORY
;
186 RtlZeroMemory((PCHAR
)PageBuf
+RequiredResources
->Amount
,
187 PAGE_SIZE
-RequiredResources
->Amount
);
189 MiUnmapPageInHyperSpace(PsGetCurrentProcess(), PageBuf
, OldIrql
);
191 DPRINT("Read Status %x (Page %x)\n", Status
, *Page
);
193 if (!NT_SUCCESS(Status
))
195 MmReleasePageMemoryConsumer(RequiredResources
->Consumer
, *Page
);
196 DPRINT("Status: %x\n", Status
);
200 return STATUS_SUCCESS
;
205 Blocking function to read a swap page into a memory page.
209 Required->Consumer: consumer to charge the page to
210 Required->SwapEntry: swap entry to use
214 Required->Page[Required->Offset]: Populated page
220 MiSwapInPage(PMMSUPPORT AddressSpace
,
221 PMEMORY_AREA MemoryArea
,
222 PMM_REQUIRED_RESOURCES Resources
)
226 Status
= MmRequestPageMemoryConsumer(Resources
->Consumer
,
228 &Resources
->Page
[Resources
->Offset
]);
229 if (!NT_SUCCESS(Status
))
231 DPRINT1("MmRequestPageMemoryConsumer failed, status = %x\n", Status
);
235 Status
= MmReadFromSwapPage(Resources
->SwapEntry
,
236 Resources
->Page
[Resources
->Offset
]);
237 if (!NT_SUCCESS(Status
))
239 DPRINT1("MmReadFromSwapPage failed, status = %x\n", Status
);
243 MmSetSavedSwapEntryPage(Resources
->Page
[Resources
->Offset
],
244 Resources
->SwapEntry
);
246 DPRINT1("MiSwapInPage(%x,%x)\n",
247 Resources
->Page
[Resources
->Offset
],
248 Resources
->SwapEntry
);
255 A way to write a page without a lock acquired using the same blocking mechanism
256 as resource acquisition.
260 Required->Page[Required->Offset]: Page to write
261 Required->Context: FILE_OBJECT to write to
262 Required->FileOffset: offset to write at
264 This always does a paging write with whole page size. Note that paging IO
265 doesn't change the valid data length of a file.
271 MiWriteFilePage(PMMSUPPORT AddressSpace
,
272 PMEMORY_AREA MemoryArea
,
273 PMM_REQUIRED_RESOURCES Required
)
275 DPRINT1("MiWriteFilePage(%x,%x)\n",
276 Required
->Page
[Required
->Offset
],
277 Required
->FileOffset
.LowPart
);
279 return MiWriteBackPage(Required
->Context
,
280 &Required
->FileOffset
,
282 Required
->Page
[Required
->Offset
]);