Beispiel #1
0
        /// <summary>
        /// Init SMT (Size Map Table).
        /// </summary>
        /// <param name="aMaxItemSize">A max item size.</param>
        static void InitSMT(uint aMaxItemSize)
        {
            mMaxItemSize = aMaxItemSize;
            var page = InitSMTPage();

            SMT = page;
        }
Beispiel #2
0
        /// <summary>
        /// Add a new root block for a certain size
        /// </summary>
        /// <param name="aSize">Size must be divisible by 2 otherwise Alloc breaks</param>
        private static void AddRootSMTBlock(SMTPage *aPage, uint aSize)
        {
            RootSMTBlock *ptr = aPage->First;

            while (ptr->LargerSize != null)
            {
                ptr = ptr->LargerSize;
            }

            if (aSize < ptr->Size)
            {
                // we cant later add a block with a size smaller than an earlier block. That would break the algorithm
                Debugger.DoSendNumber(aSize);
                Debugger.DoSendNumber(ptr->Size);
                Debugger.SendKernelPanic(0x83);
                while (true)
                {
                }
            }

            if (ptr->Size == 0)
            {
                ptr->Size = aSize;
            }
            else
            {
                var block = (RootSMTBlock *)NextFreeBlock(aPage);    // we should actually check that this is not null
                                                                     //but we should also only call this code right at the beginning so it should be fine
                block->Size     = aSize;
                ptr->LargerSize = block;
            }
            CreatePage(aPage, aSize);
        }
Beispiel #3
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;
        }
Beispiel #4
0
        /// <summary>
        /// Counts how many elements are currently allocated on a certain page
        /// </summary>
        /// <param name="aSize"></param>
        /// <returns></returns>
        private static int GetAllocatedObjectCount(SMTPage *aPage)
        {
            var ptr   = aPage->First;
            int count = 0;

            while (ptr != null)
            {
                count += GetAllocatedObjectCount(aPage, ptr->Size);
                ptr    = ptr->LargerSize;
            }
            return(count);
        }
Beispiel #5
0
        /// <summary>
        /// Find the next free block in a page
        /// </summary>
        /// <returns>Pointer to the start of block in the SMT. null if all SMT pages are full</returns>
        private static SMTBlock *NextFreeBlock(SMTPage *aPage)
        {
            var ptr = (SMTBlock *)aPage->First; // since both RootSMTBlock and SMTBlock have the same size (20) it doesnt matter if cast is wrong

            while (ptr->PagePtr != null)        // this would check Size if its actually a RootSMTBlock
            {
                ptr += 1;
                if (ptr >= (byte *)aPage + RAT.PageSize - 8)
                {
                    return(null);
                }
            }
            return(ptr);
        }
Beispiel #6
0
        /// <summary>
        /// Gets the last block on a certain page for objects of this size
        /// </summary>
        /// <param name="page">Page to search</param>
        /// <param name="aSize"></param>
        /// <returns></returns>
        private static SMTBlock *GetLastBlock(SMTPage *page, uint aSize)
        {
            SMTBlock *ptr = GetFirstBlock(page, aSize)->First;

            if (ptr == null)
            {
                return(null);
            }

            while (ptr->NextBlock != null)
            {
                ptr = ptr->NextBlock;
            }
            return(ptr);
        }
Beispiel #7
0
        /// <summary>
        /// Counts how many elements are currently allocated in this category on a certain page
        /// </summary>
        /// <param name="aSize"></param>
        /// <returns></returns>
        private static int GetAllocatedObjectCount(SMTPage *aPage, uint aSize)
        {
            var root = GetFirstBlock(aPage, aSize);
            var ptr  = root->First;

            uint size  = root->Size;
            int  count = 0;

            while (ptr != null)
            {
                count += (int)(RAT.PageSize / (size + PrefixItemBytes)) - (int)ptr->SpacesLeft;
                ptr    = ptr->NextBlock;
            }

            return(count);
        }
Beispiel #8
0
        /// <summary>
        /// Gets the root block in the SMT for objects of this size
        /// </summary>
        /// <param name="aSize">Size of allocated block</param>
        /// <param name="aPage">Page to seach in</param>
        /// <returns>Pointer of block in SMT.</returns>
        private static RootSMTBlock *GetFirstBlock(SMTPage *aPage, uint aSize)
        {
            RootSMTBlock *ptr     = aPage->First;
            uint          curSize = ptr->Size;

            while (curSize < aSize)
            {
                ptr = ptr->LargerSize;
                if (ptr == null)
                {
                    return(null);
                }
                curSize = ptr->Size;
            }
            return(ptr);
        }
Beispiel #9
0
 /// <summary>
 /// Get the first block for this size, which has space left to allocate to
 /// </summary>
 /// <param name="aSize"></param>
 /// <returns></returns>
 private static SMTBlock *GetFirstWithSpace(SMTPage *aPage, uint aSize)
 {
     return(GetFirstWithSpace(aSize, GetFirstBlock(aPage, aSize)));
 }