private PagerState.AllocationInfo TryCreateNewFileMappingAtAddress(long allocationSize, byte *baseAddress)
        {
            var newMemoryMappedFile   = MemoryMappedFile.CreateNew(null, allocationSize);
            var newFileMappingHandle  = newMemoryMappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var newMappingBaseAddress = MemoryMapNativeMethods.MapViewOfFileEx(newFileMappingHandle,
                                                                               MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.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
            });
        }
Ejemplo n.º 2
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 = MemoryMapNativeMethods.MapViewOfFileEx(mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(),
                                                                               MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.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 static void UndoMappings(IEnumerable <PagerState.AllocationInfo> newAllocationInfos)
 {
     foreach (var newAllocationInfo in newAllocationInfos)
     {
         MemoryMapNativeMethods.UnmapViewOfFile(newAllocationInfo.BaseAddress);
     }
 }
Ejemplo n.º 4
0
 public override void Sync()
 {
     if (MemoryMapNativeMethods.FlushViewOfFile(PagerState.MapBase, new IntPtr(PagerState.Accessor.Capacity)) == false)
     {
         throw new Win32Exception();
     }
     if (MemoryMapNativeMethods.FlushFileBuffers(_handle) == false)
     {
         throw new Win32Exception();
     }
 }
Ejemplo n.º 5
0
        public override void Sync()
        {
            if (PagerState.AllocationInfos.Any(allocationInfo =>
                                               MemoryMapNativeMethods.FlushViewOfFile(allocationInfo.BaseAddress, new IntPtr(allocationInfo.Size)) == false))
            {
                throw new Win32Exception();
            }

            if (MemoryMapNativeMethods.FlushFileBuffers(_handle) == false)
            {
                throw new Win32Exception();
            }
        }
Ejemplo n.º 6
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 == NativeFileAccess.GenericRead
                                ? MemoryMapNativeMethods.NativeFileMapAccessType.Read
                                : MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.NativeFileMapAccessType.Write;

            var startingBaseAddressPtr = MemoryMapNativeMethods.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 },
                Accessor        = null,          //not available since MapViewOfFileEx is used (instead of MapViewOfFile - which is used in managed wrapper)
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

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

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();

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

            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 },
                Accessor        = null,          //not available since MapViewOfFileEx is used (instead of MapViewOfFile - which is used in managed wrapper)
                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 = MemoryMapNativeMethods.MapViewOfFileEx(allocationInfo.MappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle(),
                                                                                        MemoryMapNativeMethods.NativeFileMapAccessType.Read | MemoryMapNativeMethods.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));
        }