VirtualBox

Changeset 23615 in vbox


Ignore:
Timestamp:
Oct 8, 2009 11:36:04 AM (15 years ago)
Author:
vboxsync
Message:

AsyncCompletion/FileCache: Improve memory usage for read sizes not aligned to a page boundary. Fixes out of memory error on Darwin

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/PDMAsyncCompletionFileCache.cpp

    r23604 r23615  
    818818
    819819/**
     820 * Allocates and initializes a new entry for the cache.
     821 * The entry has a reference count of 1.
     822 *
     823 * @returns Pointer to the new cache entry or NULL if out of memory.
     824 * @param   pCache    The cache the entry belongs to.
     825 * @param   pEndoint  The endpoint the entry holds data for.
     826 * @param   off       Start offset.
     827 * @param   cbData    Size of the cache entry.
     828 */
     829static PPDMACFILECACHEENTRY pdmacFileCacheEntryAlloc(PPDMACFILECACHEGLOBAL pCache,
     830                                                     PPDMASYNCCOMPLETIONENDPOINTFILE pEndpoint,
     831                                                     RTFOFF off, size_t cbData)
     832{
     833    PPDMACFILECACHEENTRY pEntryNew = (PPDMACFILECACHEENTRY)RTMemAllocZ(sizeof(PDMACFILECACHEENTRY));
     834
     835    if (RT_UNLIKELY(!pEntryNew))
     836        return NULL;
     837
     838    pEntryNew->Core.Key     = off;
     839    pEntryNew->Core.KeyLast = off + cbData - 1;
     840    pEntryNew->pEndpoint    = pEndpoint;
     841    pEntryNew->pCache       = pCache;
     842    pEntryNew->fFlags       = 0;
     843    pEntryNew->cRefs        = 1; /* We are using it now. */
     844    pEntryNew->pList        = NULL;
     845    pEntryNew->cbData       = cbData;
     846    pEntryNew->pHead        = NULL;
     847    pEntryNew->pbData       = (uint8_t *)RTMemPageAlloc(cbData);
     848
     849    if (RT_UNLIKELY(!pEntryNew->pbData))
     850    {
     851        RTMemFree(pEntryNew);
     852        return NULL;
     853    }
     854
     855    return pEntryNew;
     856}
     857
     858/**
    820859 * Advances the current segment buffer by the number of bytes transfered
    821860 * or gets the next segment.
     
    10271066        {
    10281067            /* No entry found for this offset. Get best fit entry and fetch the data to the cache. */
     1068            size_t cbToReadAligned;
    10291069            PPDMACFILECACHEENTRY pEntryBestFit = pdmacFileEpCacheGetCacheBestFitEntryByOffset(pEndpointCache, off);
    10301070
     
    10401080                cbToRead = pEntryBestFit->Core.Key - off;
    10411081                pdmacFileEpCacheEntryRelease(pEntryBestFit);
     1082                cbToReadAligned = cbToRead;
    10421083            }
    10431084            else
    1044                 cbToRead = cbRead;
     1085            {
     1086                /*
     1087                 * Align the size to a 4KB boundary.
     1088                 * Memory size is aligned to a page boundary
     1089                 * and memory is wasted if the size is rahter small.
     1090                 * (For example reads with a size of 512 bytes.
     1091                 */
     1092                cbToRead = cbRead;
     1093                cbToReadAligned = RT_ALIGN_Z(cbRead, PAGE_SIZE);
     1094
     1095                /* Clip read to file size */
     1096                cbToReadAligned = RT_MIN(pEndpoint->cbFile - off, cbToReadAligned);
     1097                if (pEntryBestFit)
     1098                    cbToReadAligned = RT_MIN(cbToReadAligned, pEntryBestFit->Core.Key - off);
     1099            }
    10451100
    10461101            cbRead -= cbToRead;
     
    10521107
    10531108            RTCritSectEnter(&pCache->CritSect);
    1054             size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToRead);
     1109            size_t cbRemoved = pdmacFileCacheEvict(pCache, cbToReadAligned);
    10551110            RTCritSectLeave(&pCache->CritSect);
    10561111
    10571112            if (cbRemoved >= cbToRead)
    10581113            {
    1059                 LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToRead));
    1060                 PPDMACFILECACHEENTRY pEntryNew = (PPDMACFILECACHEENTRY)RTMemAllocZ(sizeof(PDMACFILECACHEENTRY));
     1114                LogFlow(("Evicted %u bytes (%u requested). Creating new cache entry\n", cbRemoved, cbToReadAligned));
     1115                PPDMACFILECACHEENTRY pEntryNew = pdmacFileCacheEntryAlloc(pCache, pEndpoint, off, cbToReadAligned);
    10611116                AssertPtr(pEntryNew);
    1062 
    1063                 pEntryNew->Core.Key     = off;
    1064                 pEntryNew->Core.KeyLast = off + cbToRead - 1;
    1065                 pEntryNew->pEndpoint    = pEndpoint;
    1066                 pEntryNew->pCache       = pCache;
    1067                 pEntryNew->fFlags       = 0;
    1068                 pEntryNew->cRefs        = 1; /* We are using it now. */
    1069                 pEntryNew->pList        = NULL;
    1070                 pEntryNew->cbData       = cbToRead;
    1071                 pEntryNew->pHead        = NULL;
    1072                 pEntryNew->pbData       = (uint8_t *)RTMemPageAlloc(cbToRead);
    1073                 AssertPtr(pEntryNew->pbData);
    10741117
    10751118                RTCritSectEnter(&pCache->CritSect);
     
    10801123                uint32_t uBufOffset = 0;
    10811124
    1082                 pCache->cbCached += cbToRead;
     1125                pCache->cbCached += cbToReadAligned;
    10831126
    10841127                while (cbToRead)
Note: See TracChangeset for help on using the changeset viewer.

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