From a56e30c8d33048216567753d9d3fefc2152af8ac Mon Sep 17 00:00:00 2001 From: Jiyoung Yun Date: Thu, 13 Apr 2017 14:17:19 +0900 Subject: Imported Upstream version 2.0.0.11353 --- src/mscorlib/src/System/Runtime/MemoryFailPoint.cs | 180 +++++++++++---------- 1 file changed, 98 insertions(+), 82 deletions(-) (limited to 'src/mscorlib/src/System/Runtime/MemoryFailPoint.cs') diff --git a/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs b/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs index 84b8ba9e1e..f9f87bc928 100644 --- a/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs +++ b/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs @@ -139,7 +139,7 @@ namespace System.Runtime // count of "reserved" memory, and decrement this in Dispose and // in the critical finalizer. See // SharedStatics.MemoryFailPointReservedMemory - + private ulong _reservedMemory; // The size of this request (from user) private bool _mustSubtractReservation; // Did we add data to SharedStatics? @@ -155,7 +155,7 @@ namespace System.Runtime public MemoryFailPoint(int sizeInMegabytes) { if (sizeInMegabytes <= 0) - throw new ArgumentOutOfRangeException(nameof(sizeInMegabytes), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); + throw new ArgumentOutOfRangeException(nameof(sizeInMegabytes), SR.ArgumentOutOfRange_NeedNonNegNum); Contract.EndContractBlock(); #if !FEATURE_PAL // Remove this when CheckForAvailableMemory is able to provide legitimate estimates @@ -168,9 +168,9 @@ namespace System.Runtime // size, not the amount of memory the user wants to allocate. // Consider correcting this to reflect free memory within the GC // heap, and to check both the normal & large object heaps. - ulong segmentSize = (ulong) (Math.Ceiling((double)size / GCSegmentSize) * GCSegmentSize); + ulong segmentSize = (ulong)(Math.Ceiling((double)size / GCSegmentSize) * GCSegmentSize); if (segmentSize >= TopOfMemory) - throw new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_TooBig")); + throw new InsufficientMemoryException(SR.InsufficientMemory_MemFailPoint_TooBig); ulong requestedSizeRounded = (ulong)(Math.Ceiling((double)sizeInMegabytes / MemoryCheckGranularity) * MemoryCheckGranularity); //re-convert into bytes @@ -191,7 +191,8 @@ namespace System.Runtime // GC.WaitForPendingFinalizers, noting that this method uses a CER // so it can't be aborted, and we have a critical finalizer. It // would probably work, but do some thinking first.) - for(int stage = 0; stage < 3; stage++) { + for (int stage = 0; stage < 3; stage++) + { CheckForAvailableMemory(out availPageFile, out totalAddressSpaceFree); // If we have enough room, then skip some stages. @@ -206,99 +207,109 @@ namespace System.Runtime // Ensure our cached amount of free address space is not stale. long now = Environment.TickCount; // Handle wraparound. if ((now > LastTimeCheckingAddressSpace + CheckThreshold || now < LastTimeCheckingAddressSpace) || - LastKnownFreeAddressSpace < (long) segmentSize) { + LastKnownFreeAddressSpace < (long)segmentSize) + { CheckForFreeAddressSpace(segmentSize, false); } - bool needContiguousVASpace = (ulong) LastKnownFreeAddressSpace < segmentSize; + bool needContiguousVASpace = (ulong)LastKnownFreeAddressSpace < segmentSize; BCLDebug.Trace("MEMORYFAILPOINT", "MemoryFailPoint: Checking for {0} MB, for allocation size of {1} MB, stage {9}. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved via process's MemoryFailPoints: {8} MB", - segmentSize >> 20, sizeInMegabytes, needPageFile, - needAddressSpace, needContiguousVASpace, - availPageFile >> 20, totalAddressSpaceFree >> 20, + segmentSize >> 20, sizeInMegabytes, needPageFile, + needAddressSpace, needContiguousVASpace, + availPageFile >> 20, totalAddressSpaceFree >> 20, LastKnownFreeAddressSpace >> 20, reserved, stage); if (!needPageFile && !needAddressSpace && !needContiguousVASpace) break; - switch(stage) { - case 0: - // The GC will release empty segments to the OS. This will - // relieve us from having to guess whether there's - // enough memory in either GC heap, and whether - // internal fragmentation will prevent those - // allocations from succeeding. - GC.Collect(); - continue; - - case 1: - // Do this step if and only if the page file is too small. - if (!needPageFile) + switch (stage) + { + case 0: + // The GC will release empty segments to the OS. This will + // relieve us from having to guess whether there's + // enough memory in either GC heap, and whether + // internal fragmentation will prevent those + // allocations from succeeding. + GC.Collect(); continue; - // Attempt to grow the OS's page file. Note that we ignore - // any allocation routines from the host intentionally. - RuntimeHelpers.PrepareConstrainedRegions(); - try { - } - finally { - // This shouldn't overflow due to the if clauses above. - UIntPtr numBytes = new UIntPtr(segmentSize); - unsafe { - void * pMemory = Win32Native.VirtualAlloc(null, numBytes, Win32Native.MEM_COMMIT, Win32Native.PAGE_READWRITE); - if (pMemory != null) { - bool r = Win32Native.VirtualFree(pMemory, UIntPtr.Zero, Win32Native.MEM_RELEASE); - if (!r) - __Error.WinIOError(); + case 1: + // Do this step if and only if the page file is too small. + if (!needPageFile) + continue; + + // Attempt to grow the OS's page file. Note that we ignore + // any allocation routines from the host intentionally. + RuntimeHelpers.PrepareConstrainedRegions(); + try + { + } + finally + { + // This shouldn't overflow due to the if clauses above. + UIntPtr numBytes = new UIntPtr(segmentSize); + unsafe + { + void* pMemory = Win32Native.VirtualAlloc(null, numBytes, Win32Native.MEM_COMMIT, Win32Native.PAGE_READWRITE); + if (pMemory != null) + { + bool r = Win32Native.VirtualFree(pMemory, UIntPtr.Zero, Win32Native.MEM_RELEASE); + if (!r) + __Error.WinIOError(); + } } } - } - continue; - - case 2: - // The call to CheckForAvailableMemory above updated our - // state. - if (needPageFile || needAddressSpace) { - InsufficientMemoryException e = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint")); + continue; + + case 2: + // The call to CheckForAvailableMemory above updated our + // state. + if (needPageFile || needAddressSpace) + { + InsufficientMemoryException e = new InsufficientMemoryException(SR.InsufficientMemory_MemFailPoint); #if _DEBUG - e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize, - needPageFile, needAddressSpace, needContiguousVASpace, - availPageFile >> 20, totalAddressSpaceFree >> 20, - LastKnownFreeAddressSpace >> 20, reserved); + e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize, + needPageFile, needAddressSpace, needContiguousVASpace, + availPageFile >> 20, totalAddressSpaceFree >> 20, + LastKnownFreeAddressSpace >> 20, reserved); #endif - throw e; - } + throw e; + } - if (needContiguousVASpace) { - InsufficientMemoryException e = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_VAFrag")); + if (needContiguousVASpace) + { + InsufficientMemoryException e = new InsufficientMemoryException(SR.InsufficientMemory_MemFailPoint_VAFrag); #if _DEBUG - e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize, - needPageFile, needAddressSpace, needContiguousVASpace, - availPageFile >> 20, totalAddressSpaceFree >> 20, - LastKnownFreeAddressSpace >> 20, reserved); + e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize, + needPageFile, needAddressSpace, needContiguousVASpace, + availPageFile >> 20, totalAddressSpaceFree >> 20, + LastKnownFreeAddressSpace >> 20, reserved); #endif - throw e; - } + throw e; + } - break; + break; - default: - Debug.Assert(false, "Fell through switch statement!"); - break; + default: + Debug.Assert(false, "Fell through switch statement!"); + break; } } // Success - we have enough room the last time we checked. // Now update our shared state in a somewhat atomic fashion // and handle a simple race condition with other MemoryFailPoint instances. - AddToLastKnownFreeAddressSpace(-((long) size)); + AddToLastKnownFreeAddressSpace(-((long)size)); if (LastKnownFreeAddressSpace < 0) CheckForFreeAddressSpace(segmentSize, true); - + RuntimeHelpers.PrepareConstrainedRegions(); - try { + try + { } - finally { - SharedStatics.AddMemoryFailPointReservation((long) size); + finally + { + SharedStatics.AddMemoryFailPointReservation((long)size); _mustSubtractReservation = true; } #endif @@ -334,11 +345,11 @@ namespace System.Runtime // this will hurt, as long as we never increment this number in // the Dispose method. If we do an extra bit of checking every // once in a while, but we avoid taking a lock, we may win. - LastKnownFreeAddressSpace = (long) freeSpaceAfterGCHeap; + LastKnownFreeAddressSpace = (long)freeSpaceAfterGCHeap; LastTimeCheckingAddressSpace = Environment.TickCount; if (freeSpaceAfterGCHeap < size && shouldThrow) - throw new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_VAFrag")); + throw new InsufficientMemoryException(SR.InsufficientMemory_MemFailPoint_VAFrag); return freeSpaceAfterGCHeap >= size; } @@ -346,28 +357,30 @@ namespace System.Runtime // of pages. If we didn't have enough address space, we still return // a positive value < size, to help potentially avoid the overhead of // this check if we use a MemoryFailPoint with a smaller size next. - private static unsafe ulong MemFreeAfterAddress(void * address, ulong size) + private static unsafe ulong MemFreeAfterAddress(void* address, ulong size) { if (size >= TopOfMemory) return 0; ulong largestFreeRegion = 0; Win32Native.MEMORY_BASIC_INFORMATION memInfo = new Win32Native.MEMORY_BASIC_INFORMATION(); - UIntPtr sizeOfMemInfo = (UIntPtr) Marshal.SizeOf(memInfo); - - while (((ulong)address) + size < TopOfMemory) { + UIntPtr sizeOfMemInfo = (UIntPtr)Marshal.SizeOf(memInfo); + + while (((ulong)address) + size < TopOfMemory) + { UIntPtr r = Win32Native.VirtualQuery(address, ref memInfo, sizeOfMemInfo); if (r == UIntPtr.Zero) __Error.WinIOError(); ulong regionSize = memInfo.RegionSize.ToUInt64(); - if (memInfo.State == Win32Native.MEM_FREE) { + if (memInfo.State == Win32Native.MEM_FREE) + { if (regionSize >= size) return regionSize; else largestFreeRegion = Math.Max(largestFreeRegion, regionSize); } - address = (void *) ((ulong) address + regionSize); + address = (void*)((ulong)address + regionSize); } return largestFreeRegion; } @@ -398,11 +411,14 @@ namespace System.Runtime // This is just bookkeeping to ensure multiple threads can really // get enough memory, and this does not actually reserve memory // within the GC heap. - if (_mustSubtractReservation) { + if (_mustSubtractReservation) + { RuntimeHelpers.PrepareConstrainedRegions(); - try { + try + { } - finally { + finally + { SharedStatics.AddMemoryFailPointReservation(-((long)_reservedMemory)); _mustSubtractReservation = false; } @@ -465,9 +481,9 @@ namespace System.Runtime public override String ToString() { return String.Format(System.Globalization.CultureInfo.InvariantCulture, "MemoryFailPoint detected insufficient memory to guarantee an operation could complete. Checked for {0} MB, for allocation size of {1} MB. Need page file? {2} Need Address Space? {3} Need Contiguous address space? {4} Avail page file: {5} MB Total free VA space: {6} MB Contiguous free address space (found): {7} MB Space reserved by process's MemoryFailPoints: {8} MB", - _segmentSize >> 20, _allocationSizeInMB, _needPageFile, - _needAddressSpace, _needContiguousVASpace, - _availPageFile >> 20, _totalFreeAddressSpace >> 20, + _segmentSize >> 20, _allocationSizeInMB, _needPageFile, + _needAddressSpace, _needContiguousVASpace, + _availPageFile >> 20, _totalFreeAddressSpace >> 20, _lastKnownFreeAddressSpace >> 20, _reservedMem); } } -- cgit v1.2.3