VirtualBox

Changeset 77063 in vbox for trunk/src/VBox/Additions


Ignore:
Timestamp:
Jan 30, 2019 8:03:23 PM (6 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
128509
Message:

VbglR0PhysHeapAlloc: Tweaked the free block matching algorithm for allocations 3/4 page size or smaller to increase the likelyhood that the allocation is entirely within a single page. Keeping it within a page allows the HGCM host code to make some optimizations using page locks, reducing PGM lock contention and unnecessary copying. bugref:9172

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/common/VBoxGuest/lib/VBoxGuestR0LibPhysHeap.cpp

    r76553 r77063  
    404404DECLR0VBGL(void *) VbglR0PhysHeapAlloc (uint32_t cbSize)
    405405{
    406     VBGLPHYSHEAPBLOCK *pBlock, *iter;
     406    VBGLPHYSHEAPBLOCK *pBlock, *pIter;
    407407    int rc = vbglPhysHeapEnter ();
    408408
     
    412412    dumpheap ("pre alloc");
    413413
     414    /*
     415     * Search the free list.  We do this in linear fashion as we don't expect
     416     * there to be many blocks in the heap.
     417     */
     418
    414419    pBlock = NULL;
    415 
    416     /* If there are free blocks in the heap, look at them. */
    417     iter = g_vbgldata.pFreeBlocksHead;
    418 
    419     /* There will be not many blocks in the heap, so
    420      * linear search would be fast enough.
    421      */
    422 
    423     while (iter)
    424     {
    425         if (iter->cbDataSize == cbSize)
    426         {
    427             /* exact match */
    428             pBlock = iter;
    429             break;
    430         }
    431 
    432         /* Looking for a free block with nearest size */
    433         if (iter->cbDataSize > cbSize)
    434         {
    435             if (pBlock)
     420    if (cbSize <= PAGE_SIZE / 4 * 3)
     421    {
     422        /* Smaller than 3/4 page:  Prefer a free block that can keep the request within a single page,
     423           so HGCM processing in VMMDev can use page locks instead of several reads and writes. */
     424
     425        VBGLPHYSHEAPBLOCK *pFallback = NULL;
     426        for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext)
     427            if (pIter->cbDataSize >= cbSize)
    436428            {
    437                 if (iter->cbDataSize < pBlock->cbDataSize)
     429                if (pIter->cbDataSize == cbSize)
    438430                {
    439                     pBlock = iter;
     431                    if (PAGE_SIZE - ((uintptr_t)vbglPhysHeapBlock2Data(pIter) & PAGE_OFFSET_MASK) >= cbSize)
     432                    {
     433                        pBlock = pIter;
     434                        break;
     435                    }
     436                    pFallback = pIter;
     437                }
     438                else
     439                {
     440                    if (!pFallback || pIter->cbDataSize < pFallback->cbDataSize)
     441                        pFallback = pIter;
     442                    if (PAGE_SIZE - ((uintptr_t)vbglPhysHeapBlock2Data(pIter) & PAGE_OFFSET_MASK) >= cbSize)
     443                        if (!pBlock || pIter->cbDataSize < pBlock->cbDataSize)
     444                            pBlock = pIter;
    440445                }
    441446            }
    442             else
     447
     448        if (!pBlock)
     449            pBlock = pFallback;
     450    }
     451    else
     452    {
     453        /* Large than 3/4 page:  Find smallest free list match. */
     454
     455        for (pIter = g_vbgldata.pFreeBlocksHead; pIter != NULL; pIter = pIter->pNext)
     456            if (pIter->cbDataSize >= cbSize)
    443457            {
    444                 pBlock = iter;
     458                if (pIter->cbDataSize == cbSize)
     459                {
     460                    /* Exact match - we're done! */
     461                    pBlock = pIter;
     462                    break;
     463                }
     464
     465                /* Looking for a free block with nearest size. */
     466                if (!pBlock || pIter->cbDataSize < pBlock->cbDataSize)
     467                    pBlock = pIter;
    445468            }
    446         }
    447 
    448         iter = iter->pNext;
    449469    }
    450470
     
    470490        {
    471491            /* Data will occupy less than a half of the block,
    472              * the block should be split.
     492             * split off the tail end into a new free list entry.
    473493             */
    474             iter = (VBGLPHYSHEAPBLOCK *)((char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK) + cbSize);
    475 
    476             /* Init the new 'iter' block, initialized blocks are always marked as free. */
    477             vbglPhysHeapInitBlock (iter, pBlock->pChunk, pBlock->cbDataSize - cbSize - sizeof (VBGLPHYSHEAPBLOCK));
     494            pIter = (VBGLPHYSHEAPBLOCK *)((char *)pBlock + sizeof (VBGLPHYSHEAPBLOCK) + cbSize);
     495
     496            /* Init the new 'pIter' block, initialized blocks are always marked as free. */
     497            vbglPhysHeapInitBlock (pIter, pBlock->pChunk, pBlock->cbDataSize - cbSize - sizeof (VBGLPHYSHEAPBLOCK));
    478498
    479499            pBlock->cbDataSize = cbSize;
    480500
    481             /* Insert the new 'iter' block after the 'pBlock' in the free list */
    482             vbglPhysHeapInsertBlock (pBlock, iter);
     501            /* Insert the new 'pIter' block after the 'pBlock' in the free list */
     502            vbglPhysHeapInsertBlock (pBlock, pIter);
    483503        }
    484504
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette