/// <summary> /// Creates a new instance of the memory block class, with a existing backing storage. /// </summary> /// <param name="size">Size of the memory block in bytes</param> /// <param name="sharedMemory">Shared memory to use as backing storage for this block</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough address space left to map the shared memory</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> private MemoryBlock(ulong size, IntPtr sharedMemory) { _pointer = MemoryManagement.MapSharedMemory(sharedMemory, size); Size = size; _usesSharedMemory = true; _isMirror = true; }
/// <summary> /// Creates a new instance of the memory block class. /// </summary> /// <param name="size">Size of the memory block in bytes</param> /// <param name="flags">Flags that controls memory block memory allocation</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough memory to allocate the requested size</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> public MemoryBlock(ulong size, MemoryAllocationFlags flags = MemoryAllocationFlags.None) { if (flags.HasFlag(MemoryAllocationFlags.Mirrorable)) { _sharedMemory = MemoryManagement.CreateSharedMemory(size, flags.HasFlag(MemoryAllocationFlags.Reserve)); _pointer = MemoryManagement.MapSharedMemory(_sharedMemory, size); _usesSharedMemory = true; } else if (flags.HasFlag(MemoryAllocationFlags.Reserve)) { _viewCompatible = flags.HasFlag(MemoryAllocationFlags.ViewCompatible); _forceWindows4KBView = flags.HasFlag(MemoryAllocationFlags.ForceWindows4KBViewMapping); _pointer = MemoryManagement.Reserve(size, _viewCompatible); } else { _pointer = MemoryManagement.Allocate(size); } Size = size; _viewStorages = new ConcurrentDictionary <MemoryBlock, byte>(); _viewStorages.TryAdd(this, 0); _viewCount = 1; }
/// <summary> /// Decrements the number of views that uses this memory block as storage. /// </summary> private void DecrementViewCount() { if (Interlocked.Decrement(ref _viewCount) == 0 && _sharedMemory != IntPtr.Zero && !_isMirror) { MemoryManagement.DestroySharedMemory(_sharedMemory); _sharedMemory = IntPtr.Zero; } }
private void FreeMemory() { IntPtr ptr = Interlocked.Exchange(ref _pointer, IntPtr.Zero); // If pointer is null, the memory was already freed or never allocated. if (ptr != IntPtr.Zero) { MemoryManagement.Free(ptr); } }
protected override void DisposeUnmanaged() { IntPtr ptr = Interlocked.Exchange(ref _pointer, IntPtr.Zero); // If pointer is null, the memory was already freed or never allocated. if (ptr != IntPtr.Zero) { MemoryManagement.Free(ptr); } }
/// <summary> /// Initializes a new instance of the memory block class. /// </summary> /// <param name="size">Size of the memory block</param> /// <param name="flags">Flags that controls memory block memory allocation</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough memory to allocate the requested size</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> public MemoryBlock(ulong size, MemoryAllocationFlags flags = MemoryAllocationFlags.None) { if (flags.HasFlag(MemoryAllocationFlags.Reserve)) { _pointer = MemoryManagement.Reserve(size); } else { _pointer = MemoryManagement.Allocate(size); } Size = size; }
/// <summary> /// Maps a view of memory from another memory block. /// </summary> /// <param name="srcBlock">Memory block from where the backing memory will be taken</param> /// <param name="srcOffset">Offset on <paramref name="srcBlock"/> of the region that should be mapped</param> /// <param name="dstOffset">Offset to map the view into on this block</param> /// <param name="size">Size of the range to be mapped</param> /// <exception cref="NotSupportedException">Throw when the source memory block does not support mirroring</exception> /// <exception cref="ObjectDisposedException">Throw when the memory block has already been disposed</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> public void MapView(MemoryBlock srcBlock, ulong srcOffset, ulong dstOffset, ulong size) { if (srcBlock._sharedMemory == IntPtr.Zero) { throw new ArgumentException("The source memory block is not mirrorable, and thus cannot be mapped on the current block."); } if (_viewStorages.TryAdd(srcBlock, 0)) { srcBlock.IncrementViewCount(); } MemoryManagement.MapView(srcBlock._sharedMemory, srcOffset, GetPointerInternal(dstOffset, size), size, _forceWindows4KBView); }
/// <summary> /// Creates a new instance of the memory block class. /// </summary> /// <param name="size">Size of the memory block in bytes</param> /// <param name="flags">Flags that controls memory block memory allocation</param> /// <exception cref="OutOfMemoryException">Throw when there's no enough memory to allocate the requested size</exception> /// <exception cref="PlatformNotSupportedException">Throw when the current platform is not supported</exception> public MemoryBlock(ulong size, MemoryAllocationFlags flags = MemoryAllocationFlags.None) { if (flags.HasFlag(MemoryAllocationFlags.Mirrorable)) { _sharedMemory = MemoryManagement.CreateSharedMemory(size, flags.HasFlag(MemoryAllocationFlags.Reserve)); _pointer = MemoryManagement.MapSharedMemory(_sharedMemory); _usesSharedMemory = true; } else if (flags.HasFlag(MemoryAllocationFlags.Reserve)) { _pointer = MemoryManagement.Reserve(size); } else { _pointer = MemoryManagement.Allocate(size); } Size = size; }
private void FreeMemory() { IntPtr ptr = Interlocked.Exchange(ref _pointer, IntPtr.Zero); // If pointer is null, the memory was already freed or never allocated. if (ptr != IntPtr.Zero) { if (_usesSharedMemory) { MemoryManagement.UnmapSharedMemory(ptr); if (_sharedMemory != IntPtr.Zero && !_isMirror) { MemoryManagement.DestroySharedMemory(_sharedMemory); _sharedMemory = IntPtr.Zero; } } else { MemoryManagement.Free(ptr); } } }
private void FreeMemory() { IntPtr ptr = Interlocked.Exchange(ref _pointer, IntPtr.Zero); // If pointer is null, the memory was already freed or never allocated. if (ptr != IntPtr.Zero) { if (_usesSharedMemory) { MemoryManagement.UnmapSharedMemory(ptr, Size); } else { MemoryManagement.Free(ptr); } foreach (MemoryBlock viewStorage in _viewStorages.Keys) { viewStorage.DecrementViewCount(); } _viewStorages.Clear(); } }
/// <summary> /// Reprotects a region of memory. /// </summary> /// <param name="offset">Starting offset of the range to be reprotected</param> /// <param name="size">Size of the range to be reprotected</param> /// <param name="permission">New memory permissions</param> /// <param name="throwOnFail">True if a failed reprotect should throw</param> /// <exception cref="ObjectDisposedException">Throw when the memory block has already been disposed</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> /// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception> public void Reprotect(ulong offset, ulong size, MemoryPermission permission, bool throwOnFail = true) { MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission, _viewCompatible, _forceWindows4KBView, throwOnFail); }
/// <summary> /// Unmaps a view of memory from another memory block. /// </summary> /// <param name="srcBlock">Memory block from where the backing memory was taken during map</param> /// <param name="offset">Offset of the view previously mapped with <see cref="MapView"/></param> /// <param name="size">Size of the range to be unmapped</param> public void UnmapView(MemoryBlock srcBlock, ulong offset, ulong size) { MemoryManagement.UnmapView(srcBlock._sharedMemory, GetPointerInternal(offset, size), size, _forceWindows4KBView); }
/// <summary> /// Decommits a region of memory that has previously been reserved and optionally comitted. /// This can be used to free previously allocated memory on demand. /// </summary> /// <param name="offset">Starting offset of the range to be decommitted</param> /// <param name="size">Size of the range to be decommitted</param> /// <returns>True if the operation was successful, false otherwise</returns> /// <exception cref="ObjectDisposedException">Throw when the memory block has already been disposed</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> public bool Decommit(ulong offset, ulong size) { return(MemoryManagement.Decommit(GetPointerInternal(offset, size), size)); }
/// <summary> /// Reprotects a region of memory. /// </summary> /// <param name="offset">Starting offset of the range to be reprotected</param> /// <param name="size">Size of the range to be reprotected</param> /// <param name="permission">New memory permissions</param> /// <exception cref="ObjectDisposedException">Throw when the memory block has already been disposed</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> /// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception> public void Reprotect(ulong offset, ulong size, MemoryPermission permission) { MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission); }
/// <summary> /// Remaps a region of memory into this memory block. /// </summary> /// <param name="offset">Starting offset of the range to be remapped into</param> /// <param name="sourceAddress">Starting offset of the range to be remapped from</param> /// <param name="size">Size of the range to be remapped</param> /// <exception cref="ObjectDisposedException">Throw when the memory block has already been disposed</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> /// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception> public void Remap(ulong offset, IntPtr sourceAddress, ulong size) { MemoryManagement.Remap(GetPointerInternal(offset, size), sourceAddress, size); }
/// <summary> /// Reprotects a region of memory. /// </summary> /// <param name="offset">Starting offset of the range to be reprotected</param> /// <param name="size">Size of the range to be reprotected</param> /// <param name="permission">New memory permissions</param> /// <param name="throwOnFail">True if a failed reprotect should throw</param> /// <exception cref="ObjectDisposedException">Throw when the memory block has already been disposed</exception> /// <exception cref="InvalidMemoryRegionException">Throw when either <paramref name="offset"/> or <paramref name="size"/> are out of range</exception> /// <exception cref="MemoryProtectionException">Throw when <paramref name="permission"/> is invalid</exception> public void Reprotect(ulong offset, ulong size, MemoryPermission permission, bool throwOnFail = true) { MemoryManagement.Reprotect(GetPointerInternal(offset, size), size, permission, throwOnFail); }