summaryrefslogtreecommitdiff
path: root/src/mscorlib/src/System/Runtime/MemoryFailPoint.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/mscorlib/src/System/Runtime/MemoryFailPoint.cs')
-rw-r--r--src/mscorlib/src/System/Runtime/MemoryFailPoint.cs180
1 files changed, 98 insertions, 82 deletions
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);
}
}