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 }); }
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); } }
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(); } }
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(); } }
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)); }