private void ProtectInternal(int startPage, int numPages, MemoryBlockBase.Protection prot, bool wasUsed) { for (var i = startPage; i < startPage + numPages; i++) { _pages[i] = prot; } ulong start = GetStartAddr(startPage); ulong length = ((ulong)numPages) << WaterboxUtils.PageShift; if (prot == FREE) { Memory.Protect(start, length, MemoryBlockBase.Protection.RW); WaterboxUtils.ZeroMemory(Z.US(start), (long)length); Memory.Protect(start, length, MemoryBlockBase.Protection.None); Used -= length; Console.WriteLine($"Freed {length} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)"); } else { Memory.Protect(start, length, prot); if (wasUsed) { Console.WriteLine($"Set protection for {length} bytes on {Name} to {prot}"); } else { Used += length; Console.WriteLine($"Allocated {length} bytes on {Name}, utilization {Used}/{Memory.Size} ({100.0 * Used / Memory.Size:0.#}%)"); } } }
public bool Protect(ulong start, ulong size, MemoryBlockBase.Protection prot) { if (start < Memory.Start || start + size > Memory.End || size == 0) { return(false); } var startPage = GetPage(start); var numPages = WaterboxUtils.PagesNeeded(size); if (!EnsureMapped(startPage, numPages)) { return(false); } ProtectInternal(startPage, numPages, prot, true); return(true); }
public ulong Map(ulong size, MemoryBlockBase.Protection prot) { if (size == 0) { return(0); } int numPages = WaterboxUtils.PagesNeeded(size); int startPage = FindConsecutiveFreePages(numPages); if (startPage == -1) { return(0); } var ret = GetStartAddr(startPage); ProtectInternal(startPage, numPages, prot, false); return(ret); }
public ulong Remap(ulong start, ulong oldSize, ulong newSize, bool canMove) { // TODO: what is the expected behavior when everything requested for remap is allocated, // but with different protections? if (start < Memory.Start || start + oldSize > Memory.End || oldSize == 0 || newSize == 0) { return(0); } var oldStartPage = GetPage(start); var oldNumPages = WaterboxUtils.PagesNeeded(oldSize); if (!EnsureMapped(oldStartPage, oldNumPages)) { return(0); } var oldProt = _pages[oldStartPage]; int newNumPages = WaterboxUtils.PagesNeeded(newSize); if (!canMove) { if (newNumPages <= oldNumPages) { if (newNumPages < oldNumPages) { ProtectInternal(oldStartPage + newNumPages, oldNumPages - newNumPages, FREE, true); } return(start); } else if (newNumPages > oldNumPages) { for (var i = oldStartPage + oldNumPages; i < oldStartPage + newNumPages; i++) { if (_pages[i] != FREE) { return(0); } } ProtectInternal(oldStartPage + oldNumPages, newNumPages - oldNumPages, oldProt, false); return(start); } } // if moving is allowed, we always move to simplify and defragment when possible int newStartPage = FindConsecutiveFreePagesAssumingFreed(newNumPages, oldStartPage, oldNumPages); if (newStartPage == -1) { return(0); } var copyDataLen = Math.Min(oldSize, newSize); var copyPageLen = Math.Min(oldNumPages, newNumPages); var data = new byte[copyDataLen]; Memory.Protect(start, copyDataLen, MemoryBlockBase.Protection.RW); Marshal.Copy(Z.US(start), data, 0, (int)copyDataLen); var pages = new MemoryBlockBase.Protection[copyPageLen]; Array.Copy(_pages, oldStartPage, pages, 0, copyPageLen); ProtectInternal(oldStartPage, oldNumPages, FREE, true); ProtectInternal(newStartPage, newNumPages, MemoryBlockBase.Protection.RW, false); var ret = GetStartAddr(newStartPage); Marshal.Copy(data, 0, Z.US(ret), (int)copyDataLen); Array.Copy(pages, 0, _pages, newStartPage, copyPageLen); RefreshProtections(newStartPage, copyPageLen); if (newNumPages > oldNumPages) { ProtectInternal(newStartPage + oldNumPages, newNumPages - oldNumPages, oldProt, true); } return(ret); }