private LoadedPage MapPages(TransactionState state, long startPage, long size) { _globalMemory.EnterReadLock(); try { var addresses = _globalMapping.GetOrAdd(startPage, _ => new ConcurrentSet <MappedAddresses>()); foreach (var addr in addresses) { if (addr.Size < size) { continue; } Interlocked.Increment(ref addr.Usages); return(AddMappingToTransaction(state, startPage, size, addr)); } var offset = startPage * Constants.Storage.PageSize; if (offset + size > _totalAllocationSize) { ThrowInvalidMappingRequested(startPage, size); } var mmflags = _copyOnWriteMode ? MmapFlags.MAP_PRIVATE : MmapFlags.MAP_SHARED; var startingBaseAddressPtr = Syscall.mmap64(IntPtr.Zero, (UIntPtr)size, MmapProts.PROT_READ | MmapProts.PROT_WRITE, mmflags, _fd, offset); if (startingBaseAddressPtr.ToInt64() == -1) //system didn't succeed in mapping the address where we wanted { var err = Marshal.GetLastWin32Error(); Syscall.ThrowLastError(err, $"Unable to map {size / Constants.Size.Kilobyte:#,#0} kb starting at {startPage} on {FileName}"); } NativeMemory.RegisterFileMapping(FileName.FullPath, startingBaseAddressPtr, size, GetAllocatedInBytes); Interlocked.Add(ref _totalMapped, size); var mappedAddresses = new MappedAddresses { Address = startingBaseAddressPtr, File = FileName.FullPath, Size = size, StartPage = startPage, Usages = 1 }; addresses.Add(mappedAddresses); return(AddMappingToTransaction(state, startPage, size, mappedAddresses)); } finally { _globalMemory.ExitReadLock(); } }
private LoadedPage AddMappingToTransaction(TransactionState state, long startPage, long size, MappedAddresses mappedAddresses) { state.TotalLoadedSize += size; state.AddressesToUnload.Add(mappedAddresses); var loadedPage = new LoadedPage { Pointer = (byte *)mappedAddresses.Address, NumberOfPages = (int)(size / Constants.Storage.PageSize), StartPage = startPage }; state.LoadedPages[startPage] = loadedPage; return(loadedPage); }