Пример #1
0
        private PagerState.AllocationInfo RemapViewOfFileAtAddress(long allocationSize, ulong offsetInFile, byte *baseAddress)
        {
            var offset = new SplitValue {
                Value = offsetInFile
            };

            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      null, HandleInheritability.None, true);

            var newMappingBaseAddress = Win32MemoryMapNativeMethods.MapViewOfFileEx(mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(),
                                                                                    Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                    offset.High, offset.Low,
                                                                                    new UIntPtr((ulong)allocationSize),
                                                                                    baseAddress);

            var hasMappingSucceeded = newMappingBaseAddress != null && newMappingBaseAddress != (byte *)0;

            if (!hasMappingSucceeded)
            {
                mmf.Dispose();
                return(null);
            }

            return(new PagerState.AllocationInfo
            {
                BaseAddress = newMappingBaseAddress,
                Size = allocationSize,
                MappedFile = mmf
            });
        }
        private PagerState.AllocationInfo TryCreateNewFileMappingAtAddress(long allocationSize, byte *baseAddress)
        {
            var newMemoryMappedFile   = MemoryMappedFile.CreateNew(null, allocationSize);
            var newFileMappingHandle  = newMemoryMappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var newMappingBaseAddress = Win32MemoryMapNativeMethods.MapViewOfFileEx(newFileMappingHandle,
                                                                                    Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                                                                    Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                    0, 0,
                                                                                    UIntPtr.Zero,
                                                                                    baseAddress);

            var hasMappingSucceeded = newMappingBaseAddress != null && newMappingBaseAddress != (byte *)0;

            if (!hasMappingSucceeded)
            {
                newMemoryMappedFile.Dispose();
                return(null);
            }

            return(new PagerState.AllocationInfo
            {
                BaseAddress = newMappingBaseAddress,
                Size = allocationSize,
                MappedFile = newMemoryMappedFile
            });
        }
Пример #3
0
        private PagerState CreatePagerState()
        {
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      HandleInheritability.None, true);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();

            Win32MemoryMapNativeMethods.NativeFileMapAccessType mmFileAccessType;
            if (_copyOnWriteMode)
            {
                mmFileAccessType = Win32MemoryMapNativeMethods.NativeFileMapAccessType.Copy;
            }
            else
            {
                mmFileAccessType = _access == Win32NativeFileAccess.GenericRead
                    ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read
                    : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                   Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write;
            }
            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     mmFileAccessType,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);


            if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted
            {
                var innerException = new Win32Exception(Marshal.GetLastWin32Error(), "Failed to MapView of file " + FileName);

                var errorMessage = string.Format(
                    "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes",
                    (_fileStream.Length));

                throw new OutOfMemoryException(errorMessage, innerException);
            }

            NativeMemory.RegisterFileMapping(_fileInfo.FullName, new IntPtr(startingBaseAddressPtr), _fileStream.Length);

            // If we are working on memory validation mode, then protect the pages by default.
            ProtectPageRange(startingBaseAddressPtr, (ulong)_fileStream.Length);

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = _fileStream.Length,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            return(newPager);
        }
        private PagerState CreatePagerState()
        {
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      HandleInheritability.None, true);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var mmFileAccessType  = _access == Win32NativeFileAccess.GenericRead
                ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read
                    : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write;

            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     mmFileAccessType,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);


            if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted
            {
                var innerException = new Win32Exception();

                var errorMessage = string.Format(
                    "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes",
                    (_fileStream.Length));

                throw new OutOfMemoryException(errorMessage, innerException);
            }

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = _fileStream.Length,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            newPager.AddRef(); // one for the pager
            return(newPager);
        }
Пример #5
0
        private PagerState CreatePagerState()
        {
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      null, HandleInheritability.None, true);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var mmFileAccessType  = _access == Win32NativeFileAccess.GenericRead
                                ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read
                                        : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write;

            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     mmFileAccessType,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);


            if (startingBaseAddressPtr == (byte *)0)            //system didn't succeed in mapping the address where we wanted
            {
                throw new Win32Exception();
            }

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = _fileStream.Length,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            newPager.AddRef();             // one for the pager
            return(newPager);
        }
        private PagerState CreateInitialPagerState(long size)
        {
            var allocationSize = NearestSizeToAllocationGranularity(size);
            var mmf            = MemoryMappedFile.CreateNew(null, allocationSize, MemoryMappedFileAccess.ReadWrite);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();

            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                                                                     Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);

            if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted
            {
                throw new Win32Exception();
            }

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = allocationSize,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            newPager.AddRef();

            return(newPager);
        }
        private PagerState AllocateMorePagesAndRemapContinuously(long allocationSize)
        {
            var retryCount = 0;

            while (retryCount++ < MaxAllocationRetries)
            {
                byte *newBaseAddress;
                if (TryFindContinuousMemory((ulong)(_totalAllocationSize + allocationSize), out newBaseAddress) == false)
                {
                    var message =
                        string.Format(
                            "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of size = {0} bytes\r\n" +
                            "It is likely that we are suffering from virtual memory exhaustion or memory fragmentation.\r\n" +
                            "64 bits process: {1}\r\n" +
                            "If you are running in 32 bits, this is expected, and you need to run in 64 bits to resume normal operations.\r\n" +
                            "If you are running in 64 bits, this is likely an error and should be reported."
                            , (_totalAllocationSize + allocationSize), Environment.Is64BitProcess);
                    throw new OutOfMemoryException(message);
                }

                bool failedToAllocate = false;
                long offset           = 0;
                var  allocationInfoAfterReallocation = new List <PagerState.AllocationInfo>();
                foreach (var allocationInfo in PagerState.AllocationInfos)
                {
                    var newAlloctedBaseAddress = Win32MemoryMapNativeMethods.MapViewOfFileEx(allocationInfo.MappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle(),
                                                                                             Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                                                                             Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                             0, 0,
                                                                                             UIntPtr.Zero,
                                                                                             newBaseAddress + offset);

                    if (newAlloctedBaseAddress == null || newAlloctedBaseAddress == (byte *)0)
                    {
                        Debug.WriteLine("Failed to remap file continuously. Unmapping already mapped files and re-trying");
                        UndoMappings(allocationInfoAfterReallocation);
                        failedToAllocate = true;
                        break;
                    }

                    offset += allocationInfo.Size;
                    allocationInfoAfterReallocation.Add(new PagerState.AllocationInfo
                    {
                        BaseAddress = newAlloctedBaseAddress,
                        MappedFile  = allocationInfo.MappedFile,
                        Size        = allocationInfo.Size
                    });
                }

                if (failedToAllocate)
                {
                    continue;
                }

                var newAllocationInfo = TryCreateNewFileMappingAtAddress(allocationSize, newBaseAddress + _totalAllocationSize);
                if (newAllocationInfo == null)
                {
                    UndoMappings(allocationInfoAfterReallocation);
                    continue;
                }

                var newPagerState = new PagerState(this)
                {
                    Files           = PagerState.Files.Concat(newAllocationInfo.MappedFile),
                    AllocationInfos = allocationInfoAfterReallocation.Concat(newAllocationInfo),
                    MapBase         = newBaseAddress
                };
                return(newPagerState);
            }

            throw new InvalidOperationException(
                      string.Format(
                          "Something bad has happened, after {0} tries, could not find any spot in virtual memory to remap continuous virtual memory for {1:##,###;;0} bytes",
                          MaxAllocationRetries, allocationSize));
        }