00047 :
00048
00049 This function performs
the shutdown of memory management. This
00050
is accomplished by writing
out all modified pages which are
00051 destined
for files other than
the paging
file.
00052
00053 Arguments:
00054
00055 None.
00056
00057 Return Value:
00058
00059
TRUE if the pages were successfully written,
FALSE otherwise.
00060
00061 --*/
00062
00063 {
00064 PFN_NUMBER ModifiedPage;
00065
PMMPFN Pfn1;
00066
PSUBSECTION Subsection;
00067
PCONTROL_AREA ControlArea;
00068 PPFN_NUMBER Page;
00069 PFN_NUMBER MdlHack[(
sizeof(
MDL)/
sizeof(PFN_NUMBER)) +
MM_MAXIMUM_WRITE_CLUSTER];
00070
PMDL Mdl;
00071
NTSTATUS Status;
00072
KEVENT IoEvent;
00073 IO_STATUS_BLOCK IoStatus;
00074 KIRQL OldIrql;
00075 LARGE_INTEGER StartingOffset;
00076 ULONG count;
00077 PFN_NUMBER j;
00078 ULONG k;
00079 PFN_NUMBER first;
00080 ULONG write;
00081
PMMPAGING_FILE PagingFile;
00082
00083
00084
00085
00086
00087
if (!
MmSystemShutdown) {
00088
00089
MmLockPagableSectionByHandle(ExPageLockHandle);
00090
00091 Mdl = (
PMDL)&MdlHack;
00092 Page = (PPFN_NUMBER)(Mdl + 1);
00093
00094
KeInitializeEvent (&IoEvent, NotificationEvent, FALSE);
00095
00096
MmInitializeMdl(Mdl,
00097 NULL,
00098 PAGE_SIZE);
00099
00100 Mdl->
MdlFlags |=
MDL_PAGES_LOCKED;
00101
00102
LOCK_PFN (OldIrql);
00103
00104 ModifiedPage =
MmModifiedPageListHead.
Flink;
00105
while (ModifiedPage !=
MM_EMPTY_LIST) {
00106
00107
00108
00109
00110
00111 Pfn1 =
MI_PFN_ELEMENT (ModifiedPage);
00112
00113
if (Pfn1->
OriginalPte.
u.Soft.Prototype == 1) {
00114
00115
00116
00117
00118
00119 Subsection =
MiGetSubsectionAddress (&Pfn1->
OriginalPte);
00120 ControlArea = Subsection->
ControlArea;
00121
if ((!ControlArea->
u.Flags.Image) &&
00122 (!ControlArea->
u.Flags.NoModifiedWriting)) {
00123
00124
MiUnlinkPageFromList (Pfn1);
00125
00126
00127
00128
00129
00130 Pfn1->
u3.e1.Modified = 0;
00131
00132
00133
00134
00135
00136
00137
MI_ADD_LOCKED_PAGE_CHARGE_FOR_MODIFIED_PAGE (Pfn1, 26);
00138 Pfn1->
u3.e2.ReferenceCount += 1;
00139
00140 *Page = ModifiedPage;
00141 ControlArea->
NumberOfMappedViews += 1;
00142 ControlArea->
NumberOfPfnReferences += 1;
00143
00144
UNLOCK_PFN (OldIrql);
00145
00146 StartingOffset.QuadPart =
MiStartingOffset (Subsection,
00147 Pfn1->
PteAddress);
00148
00149 Mdl->
StartVa = (PVOID)ULongToPtr(Pfn1->
u3.e1.PageColor << PAGE_SHIFT);
00150
KeClearEvent (&IoEvent);
00151
Status =
IoSynchronousPageWrite (
00152 ControlArea->
FilePointer,
00153 Mdl,
00154 &StartingOffset,
00155 &IoEvent,
00156 &IoStatus );
00157
00158
00159
00160
00161
00162
00163
if (!
NT_SUCCESS(Status)) {
00164
KeSetEvent (&IoEvent, 0, FALSE);
00165 }
00166
00167
Status =
KeWaitForSingleObject (&IoEvent,
00168 WrPageOut,
00169 KernelMode,
00170 FALSE,
00171 (PLARGE_INTEGER)&MmTwentySeconds);
00172
00173
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
00174
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
00175 }
00176
00177
if (
Status == STATUS_TIMEOUT) {
00178
00179
00180
00181
00182
00183
00184
00185
LOCK_PFN (OldIrql);
00186 Pfn1->
u3.e1.Modified = 1;
00187
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 27);
00188
MiDecrementReferenceCount (ModifiedPage);
00189 ControlArea->
NumberOfMappedViews -= 1;
00190 ControlArea->
NumberOfPfnReferences -= 1;
00191
00192
00193
00194
00195
00196
MiCheckControlArea (ControlArea, NULL, OldIrql);
00197
00198
MmUnlockPagableImageSection(ExPageLockHandle);
00199
00200
return FALSE;
00201 }
00202
00203
LOCK_PFN (OldIrql);
00204
MI_REMOVE_LOCKED_PAGE_CHARGE (Pfn1, 27);
00205
MiDecrementReferenceCount (ModifiedPage);
00206 ControlArea->
NumberOfMappedViews -= 1;
00207 ControlArea->
NumberOfPfnReferences -= 1;
00208
00209
00210
00211
00212
00213
MiCheckControlArea (ControlArea, NULL, OldIrql);
00214
LOCK_PFN (OldIrql);
00215
00216
00217
00218
00219
00220 ModifiedPage =
MmModifiedPageListHead.
Flink;
00221
continue;
00222 }
00223 }
00224 ModifiedPage = Pfn1->
u1.Flink;
00225 }
00226
00227
UNLOCK_PFN (OldIrql);
00228
00229
00230
00231
00232
00233
00234
if (
MmAvailablePages < (
MmFreeGoal * 2)) {
00235 LARGE_INTEGER FiveSeconds = {(ULONG)(-5 * 1000 * 1000 * 10), -1};
00236
00237
KeSetEvent (&MmModifiedPageWriterEvent, 0, FALSE);
00238
KeDelayExecutionThread (KernelMode,
00239 FALSE,
00240 (PLARGE_INTEGER)&FiveSeconds);
00241 }
00242
00243
00244
00245
00246
00247
00248
MmSystemShutdown = 1;
00249
00250
00251
00252
00253
00254
00255
if (
MmZeroPageFile) {
00256
00257
00258
00259
00260
00261 Mdl->
StartVa =
NULL;
00262 j = 0;
00263 k = 0;
00264 Page = (PPFN_NUMBER)(Mdl + 1);
00265
00266
LOCK_PFN (OldIrql);
00267
00268
if (
MmAvailablePages < (
MmModifiedWriteClusterSize + 20)) {
00269
UNLOCK_PFN(OldIrql);
00270
MmUnlockPagableImageSection(ExPageLockHandle);
00271
return TRUE;
00272 }
00273
00274
do {
00275 *Page =
MiRemoveZeroPage ((ULONG)j);
00276 Pfn1 =
MI_PFN_ELEMENT (*Page);
00277 Pfn1->
u3.e2.ReferenceCount = 1;
00278
ASSERT (Pfn1->
u2.ShareCount == 0);
00279 Pfn1->
OriginalPte.
u.Long = 0;
00280
MI_SET_PFN_DELETED (Pfn1);
00281 Page += 1;
00282 j += 1;
00283 }
while (j <
MmModifiedWriteClusterSize);
00284
00285
while (k <
MmNumberOfPagingFiles) {
00286
00287 PagingFile =
MmPagingFile[k];
00288
00289 count = 0;
00290 write =
FALSE;
00291
00292
for (j = 1; j < PagingFile->
Size; j += 1) {
00293
00294
if (RtlCheckBit (PagingFile->
Bitmap, j) == 0) {
00295
00296
if (count == 0) {
00297 first = j;
00298 }
00299 count += 1;
00300
if (count ==
MmModifiedWriteClusterSize) {
00301 write =
TRUE;
00302 }
00303 }
else {
00304
if (count != 0) {
00305
00306
00307
00308
00309
00310 write =
TRUE;
00311 }
00312 }
00313
00314
if ((j == (PagingFile->
Size - 1)) &&
00315 (count != 0)) {
00316 write =
TRUE;
00317 }
00318
00319
if (write) {
00320
00321
UNLOCK_PFN (OldIrql);
00322
00323 StartingOffset.QuadPart = (LONGLONG)first <<
PAGE_SHIFT;
00324 Mdl->
ByteCount = count <<
PAGE_SHIFT;
00325
KeClearEvent (&IoEvent);
00326
00327
Status =
IoSynchronousPageWrite (PagingFile->
File,
00328 Mdl,
00329 &StartingOffset,
00330 &IoEvent,
00331 &IoStatus);
00332
00333
00334
00335
00336
00337
00338
if (!
NT_SUCCESS(Status)) {
00339
KeSetEvent (&IoEvent, 0, FALSE);
00340 }
00341
00342
Status =
KeWaitForSingleObject (&IoEvent,
00343 WrPageOut,
00344 KernelMode,
00345 FALSE,
00346 (PLARGE_INTEGER)&MmTwentySeconds);
00347
00348
if (Mdl->
MdlFlags &
MDL_MAPPED_TO_SYSTEM_VA) {
00349
MmUnmapLockedPages (Mdl->
MappedSystemVa, Mdl);
00350 }
00351
00352
if (
Status == STATUS_TIMEOUT) {
00353
00354
00355
00356
00357
00358
00359
00360 j = 0;
00361 Page = (PPFN_NUMBER)(Mdl + 1);
00362
LOCK_PFN (OldIrql);
00363
do {
00364
MiDecrementReferenceCount (*Page);
00365 Page += 1;
00366 j += 1;
00367 }
while (j <
MmModifiedWriteClusterSize);
00368
UNLOCK_PFN (OldIrql);
00369
00370
MmUnlockPagableImageSection(ExPageLockHandle);
00371
return FALSE;
00372 }
00373
00374 count = 0;
00375 write =
FALSE;
00376
LOCK_PFN (OldIrql);
00377 }
00378 }
00379 k += 1;
00380 }
00381 j = 0;
00382 Page = (PPFN_NUMBER)(Mdl + 1);
00383
do {
00384
MiDecrementReferenceCount (*Page);
00385 Page += 1;
00386 j += 1;
00387 }
while (j <
MmModifiedWriteClusterSize);
00388
UNLOCK_PFN (OldIrql);
00389 }
00390
MmUnlockPagableImageSection(ExPageLockHandle);
00391 }
00392
return TRUE;
00393 }
}