Ejemplo n.º 1
0
        /// <summary>
        /// Create a page with the size of an item and add it to the SMT at a certain page
        /// </summary>
        /// <param name="aItemSize">Object size in bytes</param>
        /// <exception cref="Exception">Thrown if:
        /// <list type="bullet">
        /// <item>aItemSize is 0.</item>
        /// <item>aItemSize is not word aligned.</item>
        /// <item>SMT is not initialized.</item>
        /// <item>The item size is bigger then a small heap size.</item>
        /// </list>
        /// </exception>
        static void CreatePage(SMTPage *aPage, uint aItemSize)
        {
            var xPtr = (byte *)RAT.AllocPages(RAT.PageType.HeapSmall, 1);

            if (xPtr == null)
            {
                return; // we failed to create the page, Alloc should still handle this case
            }
            uint xSlotSize  = aItemSize + PrefixItemBytes;
            uint xItemCount = RAT.PageSize / xSlotSize;

            for (uint i = 0; i < xItemCount; i++)
            {
                byte *  xSlotPtr     = xPtr + i * xSlotSize;
                ushort *xMetaDataPtr = (ushort *)xSlotPtr;
                xMetaDataPtr[0] = 0; // Actual data size. 0 is empty.
                xMetaDataPtr[1] = 0; // Ref count
            }

            //now add it to the smt
            var parent   = GetLastBlock(aPage, aItemSize);
            var smtBlock = NextFreeBlock(aPage); //get the next free block in the smt

            if (smtBlock == null)                // we could not allocate a new block since the SMT table is all full
            {
                // we need to expand the SMT table by a page
                var last = SMT;
                while (last->Next != null)
                {
                    last = last->Next;
                }
                last->Next = InitSMTPage();
                parent     = GetLastBlock(last->Next, aItemSize);
                smtBlock   = NextFreeBlock();
                if (smtBlock == null)
                {
                    Debugger.SendKernelPanic(0x93);
                    while (true)
                    {
                    }
                    ;
                }
            }

            if (parent != null)
            {
                // there is already a block for the same size on the same page
                parent->NextBlock = smtBlock;
            }
            else
            {
                // in this case this is the first block of the size, so we can link it to root
                var root = GetFirstBlock(aPage, aItemSize);
                root->First = smtBlock;
            }

            smtBlock->SpacesLeft = xItemCount;
            smtBlock->PagePtr    = xPtr;
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Alloc memory block, of a given size.
        /// </summary>
        /// <param name="aSize">A size of block to alloc, in bytes.</param>
        /// <returns>Byte pointer to the start of the block.</returns>
        static public byte *Alloc(Native aSize)
        {
            Native xPages = (Native)((aSize + PrefixBytes) / RAT.PageSize) + 1;
            var    xPtr   = (Native *)RAT.AllocPages(RAT.PageType.HeapLarge, xPages);

            xPtr[0] = xPages * RAT.PageSize - PrefixBytes; // Allocated data size
            xPtr[1] = aSize;                               // Actual data size
            xPtr[2] = 0;                                   // Ref count
            xPtr[3] = 0;                                   // Ptr to first

            return((byte *)xPtr + PrefixBytes);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Create a page with the size of an item.
        /// </summary>
        /// <param name="aItemSize">Item size.</param>
        /// <exception cref="Exception">Thrown if:
        /// <list type="bullet">
        /// <item>aItemSize is 0.</item>
        /// <item>aItemSize is not word aligned.</item>
        /// <item>SMT is not initialized.</item>
        /// <item>The item size is bigger then a small heap size.</item>
        /// </list>
        /// </exception>
        static void CreatePage(Native aItemSize)
        {
            if (aItemSize == 0)
            {
                throw new Exception("aItemSize cannot be 0.");
            }
            else if (aItemSize % sizeof(Native) != 0)
            {
                throw new Exception("aItemSize must be word aligned.");
            }
            else if (mMaxItemSize == 0)
            {
                throw new Exception("SMT is not initialized.");
            }
            else if (aItemSize > mMaxItemSize)
            {
                throw new Exception("Cannot allocate more than MaxItemSize in SmallHeap.");
            }

            // Limit to one page so they are allocated low and easy to move around.
            // In future may put some up top and be larger as well.
            Native xPages = 1;
            var    xPtr   = (Native *)RAT.AllocPages(RAT.PageType.HeapSmall, xPages);

            // Ptr to next page of same size
            xPtr[0] = 0;
            //
            // # of slots. Necessary for future use when more than one page, but used currently as well.
            Native xSlotSize  = aItemSize + PrefixItemBytes;
            Native xItemCount = RAT.PageSize * xPages / xSlotSize;

            xPtr[1] = xItemCount;
            //
            // # of free slots
            xPtr[2] = xItemCount;
            //
            xPtr = xPtr + 3;

            for (Native i = 0; i < xItemCount; i++)
            {
                byte *  xSlotPtr     = (byte *)xPtr + i * xSlotSize;
                Native *xMetaDataPtr = (Native *)xSlotPtr;
                xMetaDataPtr[0] = 0; // Actual data size. 0 is empty.
                xMetaDataPtr[1] = 0; // Ref count
                xMetaDataPtr[2] = 0; // Ptr to first
            }
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Alloc memory block, of a given size.
        /// </summary>
        /// <param name="aSize">A size of block to alloc, in bytes.</param>
        /// <returns>Byte pointer to the start of the block.</returns>
        public static byte *Alloc(uint aSize, byte aType = RAT.PageType.HeapLarge)
        {
            uint xPages = ((aSize + PrefixBytes) / RAT.PageSize) + 1;
            var  xPtr   = (uint *)RAT.AllocPages(aType, xPages);

            if (xPtr == null)
            {
                Debugger.SendKernelPanic(0x67); // out of pages
                while (true)
                {
                }
            }
            xPtr[0] = xPages * RAT.PageSize - PrefixBytes; // Allocated data size
            xPtr[1] = aSize;                               // Actual data size
            xPtr[3] = 0;                                   // padding for now?,
            xPtr[2] = 0;                                   // padding + GC object status
            return((byte *)xPtr + PrefixBytes);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Allocates and initialise a page for the SMT table
        /// </summary>
        /// <returns></returns>
        private static SMTPage *InitSMTPage()
        {
            var page = (SMTPage *)RAT.AllocPages(RAT.PageType.SMT, 1);

            page->First = (RootSMTBlock *)(page + 1);

            // TODO Change these sizes after further study and also when page size changes.
            // SMT can be grown as needed. Also can adjust and create new ones dynamicaly as it runs.
            // The current algorithm only works if we create the inital pages in increasing order
            AddRootSMTBlock(page, 16);
            AddRootSMTBlock(page, 24);
            AddRootSMTBlock(page, 48);
            AddRootSMTBlock(page, 64);
            AddRootSMTBlock(page, 128);
            AddRootSMTBlock(page, 256);
            AddRootSMTBlock(page, 512);
            AddRootSMTBlock(page, mMaxItemSize);
            return(page);
        }