Inheritance: OutOfMemoryException
Exemple #1
0
        [System.Security.SecurityCritical]  // auto-generated_required
        public MemoryFailPoint(int sizeInMegabytes)
        {
            if (sizeInMegabytes <= 0)
                throw new ArgumentOutOfRangeException("sizeInMegabytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            Contract.EndContractBlock();

            ulong size = ((ulong)sizeInMegabytes) << 20;
            _reservedMemory = size;

            // Check to see that we both have enough memory on the system
            // and that we have enough room within the user section of the 
            // process's address space.  Also, we need to use the GC segment
            // 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);
            if (segmentSize >= TopOfMemory)
                throw new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_TooBig"));

            ulong requestedSizeRounded = (ulong)(Math.Ceiling((double)sizeInMegabytes / MemoryCheckGranularity) * MemoryCheckGranularity);
            //re-convert into bytes
            requestedSizeRounded <<= 20;

            ulong availPageFile = 0;  // available VM (physical + page file)
            ulong totalAddressSpaceFree = 0;  // non-contiguous free address space

            // Check for available memory, with 2 attempts at getting more 
            // memory.  
            // Stage 0: If we don't have enough, trigger a GC.  
            // Stage 1: If we don't have enough, try growing the swap file.
            // Stage 2: Update memory state, then fail or leave loop.
            //
            // (In the future, we could consider adding another stage after 
            // Stage 0 to run finalizers.  However, before doing that make sure
            // that we could abort this constructor when we call 
            // 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++) {
                CheckForAvailableMemory(out availPageFile, out totalAddressSpaceFree);

                // If we have enough room, then skip some stages.
                // Note that multiple threads can still lead to a race condition for our free chunk
                // of address space, which can't be easily solved.
                ulong reserved = SharedStatics.MemoryFailPointReservedMemory;
                ulong segPlusReserved = segmentSize + reserved;
                bool overflow = segPlusReserved < segmentSize || segPlusReserved < reserved;
                bool needPageFile = availPageFile < (requestedSizeRounded + reserved + LowMemoryFudgeFactor) || overflow;
                bool needAddressSpace = totalAddressSpaceFree < segPlusReserved || overflow;

                // 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) {
                    CheckForFreeAddressSpace(segmentSize, false);
                }
                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, 
                               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)
                        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"));
#if _DEBUG
                        e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize,
                             needPageFile, needAddressSpace, needContiguousVASpace, 
                             availPageFile >> 20, totalAddressSpaceFree >> 20,
                             LastKnownFreeAddressSpace >> 20, reserved);
#endif
                        throw e;
                    }

                    if (needContiguousVASpace) {
                        InsufficientMemoryException e = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_VAFrag"));
#if _DEBUG
                        e.Data["MemFailPointState"] = new MemoryFailPointState(sizeInMegabytes, segmentSize,
                             needPageFile, needAddressSpace, needContiguousVASpace, 
                             availPageFile >> 20, totalAddressSpaceFree >> 20,
                             LastKnownFreeAddressSpace >> 20, reserved);
#endif
                        throw e;
                    }

                    break;

                default:
                    Contract.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));
            if (LastKnownFreeAddressSpace < 0)
                CheckForFreeAddressSpace(segmentSize, true);
            
            RuntimeHelpers.PrepareConstrainedRegions();
            try {
            }
            finally {
                SharedStatics.AddMemoryFailPointReservation((long) size);
                _mustSubtractReservation = true;
            }
        }
        public unsafe MemoryFailPoint(int sizeInMegabytes)
        {
            if (sizeInMegabytes <= 0)
            {
                throw new ArgumentOutOfRangeException("sizeInMegabytes", Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum"));
            }
            ulong num = ((ulong) sizeInMegabytes) << 20;
            this._reservedMemory = num;
            ulong size = (ulong) (Math.Ceiling((double) (((float) num) / ((float) GCSegmentSize))) * GCSegmentSize);
            if (size >= TopOfMemory)
            {
                throw new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_TooBig"));
            }
            ulong availPageFile = 0L;
            ulong totalAddressSpaceFree = 0L;
            for (int i = 0; i < 3; i++)
            {
                CheckForAvailableMemory(out availPageFile, out totalAddressSpaceFree);
                ulong memoryFailPointReservedMemory = SharedStatics.MemoryFailPointReservedMemory;
                ulong num7 = size + memoryFailPointReservedMemory;
                bool flag = (num7 < size) || (num7 < memoryFailPointReservedMemory);
                bool flag2 = (availPageFile < (num7 + ((ulong) 0x1000000L))) || flag;
                bool flag3 = (totalAddressSpaceFree < num7) || flag;
                long tickCount = Environment.TickCount;
                if (((tickCount > (LastTimeCheckingAddressSpace + 0x2710L)) || (tickCount < LastTimeCheckingAddressSpace)) || (LastKnownFreeAddressSpace < size))
                {
                    CheckForFreeAddressSpace(size, false);
                }
                bool flag4 = LastKnownFreeAddressSpace < size;
                if ((!flag2 && !flag3) && !flag4)
                {
                    break;
                }
                switch (i)
                {
                    case 0:
                    {
                        GC.Collect();
                        continue;
                    }
                    case 1:
                        if (!flag2)
                        {
                            continue;
                        }
                        RuntimeHelpers.PrepareConstrainedRegions();
                        try
                        {
                            continue;
                        }
                        finally
                        {
                            UIntPtr numBytes = new UIntPtr(size);
                            void* address = Win32Native.VirtualAlloc(null, numBytes, 0x1000, 4);
                            if ((address != null) && !Win32Native.VirtualFree(address, UIntPtr.Zero, 0x8000))
                            {
                                __Error.WinIOError();
                            }
                        }
                        break;

                    case 2:
                        break;

                    default:
                    {
                        continue;
                    }
                }
                if (flag2 || flag3)
                {
                    InsufficientMemoryException exception = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint"));
                    throw exception;
                }
                if (flag4)
                {
                    InsufficientMemoryException exception2 = new InsufficientMemoryException(Environment.GetResourceString("InsufficientMemory_MemFailPoint_VAFrag"));
                    throw exception2;
                }
            }
            Interlocked.Add(ref LastKnownFreeAddressSpace, (long) -num);
            if (LastKnownFreeAddressSpace < 0L)
            {
                CheckForFreeAddressSpace(size, true);
            }
            RuntimeHelpers.PrepareConstrainedRegions();
            try
            {
            }
            finally
            {
                SharedStatics.AddMemoryFailPointReservation((long) num);
                this._mustSubtractReservation = true;
            }
        }