test: shutdown.c Source File

Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

# shutdown.c

Go to the documentation of this file.

    00001 /*++
    00002
    00003 Copyright (c) 1991  Microsoft Corporation
    00004
    00005 Module Name:
    00006
    00007     shutdown.c
    00008
    00009 Abstract:
    00010
    00011     This module contains the initialization for the memory management
    00012     system.
    00013
    00014 Author:
    00015
    00016     Lou Perazzoli (loup) 21-Aug-1991
    00017     Landy Wang (landyw) 02-June-1997
    00018
    00019 Revision History:
    00020
    00021 --*/
    00022
    00023 #include "mi.h"
    00024
    00025 extern ULONG MmSystemShutdown;
    00026
    00027 VOID
    00028 MmReleaseAllMemory (
    00029     VOID
    00030     );
    00031
    00032 #ifdef ALLOC_PRAGMA
    00033 #pragma alloc_text(PAGELK,MmShutdownSystem)
    00034 #pragma alloc_text(PAGEVRFY,MmReleaseAllMemory)
    00035 #endif
    00036
    00037 ULONG MmZeroPageFile;
    00038
    00039
    00040 BOOLEAN
    00041 MmShutdownSystem (
    00042     VOID
    00043     )
    00044
    00045 /*++
    00046
    00047 Routine Description:
    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     // Don't do this more than once.
    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             // There are modified pages.
    00109             //
    00110
    00111             Pfn1 = MI_PFN_ELEMENT (ModifiedPage);
    00112
    00113             if (Pfn1->OriginalPte.u.Soft.Prototype == 1) {
    00114
    00115                 //
    00116                 // This page is destined for a file.
    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                     // Issue the write.
    00128                     //
    00129
    00130                     Pfn1->u3.e1.Modified = 0;
    00131
    00132                     //
    00133                     // Up the reference count for the physical page as there
    00134                     // is I/O in progress.
    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                     // Ignore all I/O failures - there is nothing that can be
    00160                     // done at this point.
    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                         // The write did not complete in 20 seconds, assume
    00181                         // that the file systems are hung and return an
    00182                         // error.
    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                         // This routine returns with the PFN lock released!
    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                     // This routine returns with the PFN lock released!
    00211                     //
    00212
    00213                     MiCheckControlArea (ControlArea, NULL, OldIrql);
    00214                     LOCK_PFN (OldIrql);
    00215
    00216                     //
    00217                     // Restart scan at the front of the list.
    00218                     //
    00219
    00220                     ModifiedPage = MmModifiedPageListHead.Flink;
    00221                     continue;
    00222                 }
    00223             }
    00224             ModifiedPage = Pfn1->u1.Flink;
    00225         }
    00226
    00227         UNLOCK_PFN (OldIrql);
    00228
    00229         //
    00230         // If a high number of modified pages still exist, start the
    00231         // modified page writer and wait for 5 seconds.
    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         // Indicate to the modified page writer that the system has
    00245         // shutdown.
    00246         //
    00247
    00248         MmSystemShutdown = 1;
    00249
    00250         //
    00251         // Check to see if the paging file should be overwritten.
    00252         // Only free blocks are written.
    00253         //
    00254
    00255         if (MmZeroPageFile) {
    00256
    00257             //
    00258             // Get pages to complete the write request.
    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                             // Issue a write.
    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                         // Ignore all I/O failures - there is nothing that can
    00335                         // be done at this point.
    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                             // The write did not complete in 20 seconds, assume
    00356                             // that the file systems are hung and return an
    00357                             // error.
    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 }