Пример #1
0
        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.#}%)");
                }
            }
        }
Пример #2
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);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
        }