Exemple #1
0
        /////////////////////////////////////
        // PRIVATE METHODS
        /////////////////////////////////////

        //
        // Finds a contiguous block of virtual memory.
        //
        // *** CALLER MUST HOLD OUR PROTECTIVE LOCK! ***
        //
        // We don't acquire the spinlock ourselves in case the caller
        // wants to do more work within it.
        //
        // Currently, the approach is VERY simplistic; we just keep handing out
        // pages starting with the base of the virtual memory space until we
        // bump into the top, and then we become much more inefficient.
        //
        // The expectation is that higher-level components will do smarter
        // space management than this!
        //
        private unsafe UIntPtr ReserveInternal(UIntPtr numPages, Process process, uint extra, PageType type)
        {
            DebugStub.Assert(numPages >= 1);
            UIntPtr mapAddr = UIntPtr.Zero;

            uint tag =
                (process != null ? process.ProcessTag : MemoryManager.KernelPage)
                | (extra & MemoryManager.ExtraMask)
                | (uint)type;

            UIntPtr blockBytes = MemoryManager.BytesFromPages(numPages);

            if (nextAlloc + blockBytes <= rangeLimit)
            {
                mapAddr = nextAlloc;
                UIntPtr limitAddr = mapAddr + blockBytes;
                nextAlloc = limitAddr;

                SetRange(mapAddr, limitAddr, tag);
            }
            else
            {
                // slow-path allocation - just do first-fit for now...
                // TODO: Need to integrate freelist management from flatpages et al
                UIntPtr startIdx = PageFromAddr(dataStart);
                UIntPtr limitIdx = MemoryManager.PageFromAddr(rangeLimit - descrBase) - (numPages - 1);
                DebugStub.Assert(limitIdx <= PageCount);

                for (UIntPtr pageIdx = startIdx; pageIdx < limitIdx; pageIdx++)
                {
                    UIntPtr pageCount = 0;

                    while (pageCount < numPages)
                    {
                        uint pageTag = *(pageTable + pageIdx + pageCount);
                        if (pageTag != MemoryManager.PageFree)
                        {
                            break;
                        }
                        pageCount++;
                    }

                    if (pageCount == numPages)
                    {
                        mapAddr = dataStart + MemoryManager.BytesFromPages(pageIdx - startIdx);

                        SetRange(mapAddr, mapAddr + blockBytes, tag);
                        break;
                    }
                    else
                    {
                        pageIdx += pageCount;
                    }
                }
            }

            return(mapAddr);
        }
Exemple #2
0
        internal unsafe void SetRange(UIntPtr startAddr, UIntPtr limitAddr, uint tag)
        {
            DebugStub.Assert(startAddr >= descrBase);
            DebugStub.Assert(limitAddr <= descrLimit);

            UIntPtr startIdx = PageFromAddr(startAddr);
            UIntPtr limitIdx = MemoryManager.PageFromAddr(limitAddr - descrBase);

            DebugStub.Assert(limitIdx <= PageCount);

            for (UIntPtr i = startIdx; i < limitIdx; i++)
            {
                pageTable[(uint)i] = tag;
            }
        }
Exemple #3
0
 internal UIntPtr PageFromAddr(UIntPtr addr)
 {
     DebugStub.Assert(addr >= descrBase);
     DebugStub.Assert(addr < descrLimit);
     return(MemoryManager.PageFromAddr(addr - descrBase));
 }