/// <summary> /// Allocates an index which corresponds to a buffer. /// </summary> /// <returns>Allocated index. If allocation fails, returned index is negative.</returns> /// <exception cref="InvalidOperationException">Thrown when allocator is exhausted or when buffer cannot be committed.</exception> public int Allocate() { if (FreeList.IsEmpty) { #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException("Cannot allocate, allocator is exhausted."); #else return(-1); #endif } int lastFreeListIndex = FreeList.Length - 1; int index = FreeList.Ptr[lastFreeListIndex]; BaselibErrorState errorState; var range = new VMRange((IntPtr)this[index], (uint)BufferSizeInBytes, VirtualMemoryUtility.DefaultPageSizeInBytes); VirtualMemoryUtility.CommitMemory(range, out errorState); if (!errorState.Success) { #if ENABLE_UNITY_COLLECTIONS_CHECKS throw new InvalidOperationException($"Failed to commit address range {range}."); #else return(-1); #endif } FreeList.RemoveAtSwapBack(lastFreeListIndex); return(index); }
public unsafe void VirtualMemory_Allocate() { BaselibErrorState errorState = default; // Reserve 4GB var addressSpace = VirtualMemoryUtility.ReserveAddressSpace(1024ul * 1024ul, VirtualMemoryUtility.DefaultPageSizeInBytes, out errorState); { // Commit 1 page for an allocator VMRange page = new VMRange { ptr = addressSpace.ptr, log2PageSize = addressSpace.log2PageSize, pageCount = 1 }; VirtualMemoryUtility.CommitMemory(page, out errorState); // 1KB allocator var allocator = new UnsafeScratchAllocator((void *)page.ptr, 1024); var numbers0 = (int *)allocator.Allocate <int>(256); for (int i = 0; i < 256; i++) { numbers0[i] = i; } var anotherAllocator = new UnsafeScratchAllocator((void *)((IntPtr)page.ptr + 1024), 1024); var numbers1 = (int *)anotherAllocator.Allocate <int>(256); for (int i = 0; i < 256; i++) { numbers1[i] = numbers0[i]; } } VirtualMemoryUtility.FreeAddressSpace(addressSpace, out errorState); }
public unsafe void VirtualMemory_Decommit() { BaselibErrorState errorState = default; // Reserve 4GB var addressSpace = VirtualMemoryUtility.ReserveAddressSpace(1024ul * 1024ul, VirtualMemoryUtility.DefaultPageSizeInBytes, out errorState); { // Commit 4KB for an allocator VMRange page = new VMRange { ptr = addressSpace.ptr, log2PageSize = addressSpace.log2PageSize, pageCount = 1 }; VirtualMemoryUtility.CommitMemory(page, out errorState); var allocator = new UnsafeScratchAllocator((void *)page.ptr, 4096); var numbers0 = (int *)allocator.Allocate <int>(256); for (int i = 0; i < 256; i++) { numbers0[i] = i; } // Decommit and try to use VirtualMemoryUtility.DecommitMemory(page, out errorState); Assert.Throws <NullReferenceException>(() => numbers0[1] = 1); } VirtualMemoryUtility.FreeAddressSpace(addressSpace, out errorState); }
public void Execute(int index) { BaselibErrorState errorState = default; VMRange allocation = new VMRange { ptr = jobAddressRangePtr + index * (int)VirtualMemoryUtility.DefaultPageSizeInBytes, log2PageSize = jobLog2PageSize, pageCount = jobPageCount }; // Commit a page from the address range VirtualMemoryUtility.CommitMemory(allocation, out errorState); jobErrorStates[index] = errorState; // 1 page of ints var allocator = new UnsafeScratchAllocator((void *)allocation.ptr, (int)VirtualMemoryUtility.DefaultPageSizeInBytes); var numbers0 = (int *)allocator.Allocate <int>((int)VirtualMemoryUtility.DefaultPageSizeInBytes / sizeof(int)); for (int i = 0; i < (int)VirtualMemoryUtility.DefaultPageSizeInBytes / sizeof(int); i++) { numbers0[i] = i; } }
public unsafe void VirtualMemory_OvercommitReservedMemory() { BaselibErrorState errorState = default; // Reserve 1 page var addressSpace = VirtualMemoryUtility.ReserveAddressSpace(1, VirtualMemoryUtility.DefaultPageSizeInBytes, out errorState); { // Try to commit 2 pages (will fail). VMRange pages = new VMRange { ptr = addressSpace.ptr, log2PageSize = addressSpace.log2PageSize, pageCount = 2 }; VirtualMemoryUtility.CommitMemory(pages, out errorState); VirtualMemoryUtility.ReportWrappedBaselibError(errorState); LogAssert.Expect(LogType.Error, new Regex("Baselib error:*")); var coolByte = (byte *)pages.ptr; // Try to write to uncommitted memory (will fail and throw an exception). Assert.Throws <NullReferenceException>(() => *coolByte = 0); } VirtualMemoryUtility.FreeAddressSpace(addressSpace, out errorState); }