VirtualBox

Changeset 88864 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
May 4, 2021 4:40:24 PM (4 years ago)
Author:
vboxsync
Message:

DrvHostAudioWasApi: Limit the number of audio clients in the cache to 4 in each direction. Do pruning on work thread. bugref:9890

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Audio/DrvHostAudioWasApi.cpp

    r88861 r88864  
    5252*********************************************************************************************************************************/
    5353/** Max GetCurrentPadding value we accept (to make sure it's safe to convert to bytes). */
    54 #define VBOX_WASAPI_MAX_PADDING         UINT32_C(0x007fffff)
     54#define VBOX_WASAPI_MAX_PADDING                 UINT32_C(0x007fffff)
     55
     56/** Maximum number of cached device configs in each direction.
     57 * The number 4 was picked at random.  */
     58#define VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES    4
    5559
    5660#if 0
    5761/** @name WM_DRVHOSTAUDIOWAS_XXX - Worker thread messages.
    5862 * @{ */
    59 #define WM_DRVHOSTAUDIOWAS_PURGE_CACHE  (WM_APP + 3)
     63#define WM_DRVHOSTAUDIOWAS_PURGE_CACHE          (WM_APP + 3)
    6064/** @} */
    6165#endif
     
    6569 * @{ */
    6670#define DRVHOSTAUDIOWAS_DO_PURGE_CACHE          ((uintptr_t)0x49f37300 + 1)
    67 #define DRVHOSTAUDIOWAS_DO_STREAM_DEV_SWITCH    ((uintptr_t)0x49f37300 + 2)
     71#define DRVHOSTAUDIOWAS_DO_PRUNE_CACHE          ((uintptr_t)0x49f37300 + 2)
     72#define DRVHOSTAUDIOWAS_DO_STREAM_DEV_SWITCH    ((uintptr_t)0x49f37300 + 3)
    6873/** @} */
    6974
     
    114119    /** Init complete timestamp (just for reference). */
    115120    uint64_t                    nsInited;
     121    /** When it was last used. */
     122    uint64_t                    nsLastUsed;
    116123    /** The stringified properties. */
    117124    char                        szProps[32];
     
    258265     *  can do cleanups. */
    259266    RTSEMEVENTMULTI                 hEvtCachePurge;
     267    /** Total number of device config entire for capturing.
     268     * This includes in-use ones. */
     269    uint32_t volatile               cCacheEntriesIn;
     270    /** Total number of device config entire for playback.
     271     * This includes in-use ones. */
     272    uint32_t volatile               cCacheEntriesOut;
    260273
    261274#if 0
     
    720733 * @param   pDevCfg     Device config entry.  Must not be in the list.
    721734 */
    722 static void drvHostAudioWasCacheDestroyDevConfig(PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg)
    723 {
     735static void drvHostAudioWasCacheDestroyDevConfig(PDRVHOSTAUDIOWAS pThis, PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg)
     736{
     737    if (pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN)
     738        ASMAtomicDecU32(&pThis->cCacheEntriesIn);
     739    else
     740        ASMAtomicDecU32(&pThis->cCacheEntriesOut);
     741
    724742    uint32_t cTypeClientRefs = 0;
    725743    if (pDevCfg->pIAudioCaptureClient)
     
    756774 * @param   pDevEntry   The device entry. Must not be in the cache!
    757775 */
    758 static void drvHostAudioWasCacheDestroyDevEntry(PDRVHOSTAUDIOWASCACHEDEV pDevEntry)
     776static void drvHostAudioWasCacheDestroyDevEntry(PDRVHOSTAUDIOWAS pThis, PDRVHOSTAUDIOWASCACHEDEV pDevEntry)
    759777{
    760778    Log8Func(("Destroying cache entry: %p - '%ls'\n", pDevEntry, pDevEntry->wszDevId));
     
    763781    RTListForEachSafe(&pDevEntry->ConfigList, pDevCfg, pDevCfgNext, DRVHOSTAUDIOWASCACHEDEVCFG, ListEntry)
    764782    {
    765         drvHostAudioWasCacheDestroyDevConfig(pDevCfg);
     783        drvHostAudioWasCacheDestroyDevConfig(pThis, pDevCfg);
    766784    }
    767785
     
    777795    RTMemFree(pDevEntry);
    778796    Log8Func(("Destroyed cache entry: %p cDevRefs=%u\n", pDevEntry, cDevRefs));
     797}
     798
     799
     800/**
     801 * Prunes the cache.
     802 */
     803static void drvHostAudioWasCachePrune(PDRVHOSTAUDIOWAS pThis)
     804{
     805    /*
     806     * Prune each direction separately.
     807     */
     808    struct
     809    {
     810        PDMAUDIODIR        enmDir;
     811        uint32_t volatile *pcEntries;
     812    } aWork[] = { { PDMAUDIODIR_IN, &pThis->cCacheEntriesIn }, { PDMAUDIODIR_OUT, &pThis->cCacheEntriesOut }, };
     813    for (uint32_t iWork = 0; iWork < RT_ELEMENTS(aWork); iWork++)
     814    {
     815        /*
     816         * Remove the least recently used entry till we're below the threshold
     817         * or there are no more inactive entries.
     818         */
     819        LogFlowFunc(("iWork=%u cEntries=%u\n", iWork, *aWork[iWork].pcEntries));
     820        while (*aWork[iWork].pcEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES)
     821        {
     822            RTCritSectEnter(&pThis->CritSectCache);
     823            PDRVHOSTAUDIOWASCACHEDEVCFG pLeastRecentlyUsed = NULL;
     824            PDRVHOSTAUDIOWASCACHEDEV    pDevEntry;
     825            RTListForEach(&pThis->CacheHead, pDevEntry, DRVHOSTAUDIOWASCACHEDEV, ListEntry)
     826            {
     827                if (pDevEntry->enmDir == aWork[iWork].enmDir)
     828                {
     829                    PDRVHOSTAUDIOWASCACHEDEVCFG pHeadCfg = RTListGetFirst(&pDevEntry->ConfigList,
     830                                                                          DRVHOSTAUDIOWASCACHEDEVCFG, ListEntry);
     831                    if (   pHeadCfg
     832                        && (!pLeastRecentlyUsed || pHeadCfg->nsLastUsed < pLeastRecentlyUsed->nsLastUsed))
     833                        pLeastRecentlyUsed = pHeadCfg;
     834                }
     835            }
     836            if (pLeastRecentlyUsed)
     837                RTListNodeRemove(&pLeastRecentlyUsed->ListEntry);
     838            RTCritSectLeave(&pThis->CritSectCache);
     839
     840            if (!pLeastRecentlyUsed)
     841                break;
     842            drvHostAudioWasCacheDestroyDevConfig(pThis, pLeastRecentlyUsed);
     843        }
     844    }
    779845}
    780846
     
    792858        if (!pDevEntry)
    793859            break;
    794         drvHostAudioWasCacheDestroyDevEntry(pDevEntry);
     860        drvHostAudioWasCacheDestroyDevEntry(pThis, pDevEntry);
    795861    }
    796862
     
    820886        {
    821887            RTListNodeRemove(&pDevCfg->ListEntry);
     888            pDevCfg->nsLastUsed = RTTimeNanoTS();
    822889            return pDevCfg;
    823890        }
     
    874941    {
    875942        LogRelMax(64, ("WasAPI: Activate(%ls, IAudioClient) failed: %Rhrc\n", pDevEntry->wszDevId, hrc));
    876         pDevCfg->nsInited = RTTimeNanoTS();
     943        pDevCfg->nsInited   = RTTimeNanoTS();
     944        pDevCfg->nsLastUsed = pDevCfg->nsInited;
    877945        return pDevCfg->rcSetup = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
    878946    }
     
    9441012                                                                                    cDefaultPeriodInNtTicks * 100);
    9451013                            pDevCfg->nsInited           = RTTimeNanoTS();
     1014                            pDevCfg->nsLastUsed         = pDevCfg->nsInited;
    9461015                            pDevCfg->rcSetup            = VINF_SUCCESS;
    9471016
     
    9841053    if (pClosestMatch)
    9851054        CoTaskMemFree(pClosestMatch);
    986     pDevCfg->nsInited = RTTimeNanoTS();
     1055    pDevCfg->nsInited   = RTTimeNanoTS();
     1056    pDevCfg->nsLastUsed = 0;
    9871057    Log8Func(("returns VERR_AUDIO_STREAM_COULD_NOT_CREATE (inited in %'RU64 ns)\n", pDevCfg->nsInited - pDevCfg->nsCreated));
    9881058    return pDevCfg->rcSetup = VERR_AUDIO_STREAM_COULD_NOT_CREATE;
     
    10281098    PDMAudioPropsToString(&pDevCfg->Props, pDevCfg->szProps, sizeof(pDevCfg->szProps));
    10291099    pDevCfg->nsCreated         = RTTimeNanoTS();
     1100    pDevCfg->nsLastUsed        = pDevCfg->nsCreated;
     1101
     1102    uint32_t cCacheEntries;
     1103    if (pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN)
     1104        cCacheEntries = ASMAtomicIncU32(&pThis->cCacheEntriesIn);
     1105    else
     1106        cCacheEntries = ASMAtomicIncU32(&pThis->cCacheEntriesOut);
     1107    if (cCacheEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES)
     1108    {
     1109        LogFlowFunc(("Trigger cache pruning.\n"));
     1110        int rc2 = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL /*pStream*/,
     1111                                                              DRVHOSTAUDIOWAS_DO_PRUNE_CACHE, NULL /*pvUser*/);
     1112        AssertRCStmt(rc2, drvHostAudioWasCachePrune(pThis));
     1113    }
    10301114
    10311115    if (!fOnWorker)
     
    11761260        RTCritSectEnter(&pThis->CritSectCache);
    11771261        RTListAppend(&pDevCfg->pDevEntry->ConfigList, &pDevCfg->ListEntry);
     1262        uint32_t const cEntries = pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN ? pThis->cCacheEntriesIn : pThis->cCacheEntriesOut;
    11781263        RTCritSectLeave(&pThis->CritSectCache);
     1264
     1265        /* Trigger pruning if we're over the threshold. */
     1266        if (cEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES)
     1267        {
     1268            LogFlowFunc(("Trigger cache pruning.\n"));
     1269            int rc2 = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL /*pStream*/,
     1270                                                                  DRVHOSTAUDIOWAS_DO_PRUNE_CACHE, NULL /*pvUser*/);
     1271            AssertRCStmt(rc2, drvHostAudioWasCachePrune(pThis));
     1272        }
    11791273    }
    11801274    else
    11811275    {
    11821276        Log8Func(("IAudioClient::Reset failed (%Rhrc) on %p/'%s', destroying it.\n", hrc, pDevCfg, pDevCfg->szProps));
    1183         drvHostAudioWasCacheDestroyDevConfig(pDevCfg);
     1277        drvHostAudioWasCacheDestroyDevConfig(pThis, pDevCfg);
    11841278    }
    11851279}
     
    15991693        LogRelMax(64, ("WasAPI: Failed to set up new device config '%ls:%s' for stream '%s': %Rrc\n",
    16001694                       pDevCfg->pDevEntry->wszDevId, pDevCfg->szProps, pStreamWas->Cfg.szName, rc));
    1601         drvHostAudioWasCacheDestroyDevConfig(pDevCfg);
     1695        drvHostAudioWasCacheDestroyDevConfig(pThis, pDevCfg);
    16021696        pThis->pIHostAudioPort->pfnStreamNotifyDeviceChanged(pThis->pIHostAudioPort, &pStreamWas->Core, true /*fReInit*/);
    16031697    }
     
    16201714            Assert(pvUser == NULL);
    16211715            drvHostAudioWasCachePurge(pThis, true /*fOnWorker*/);
     1716            break;
     1717
     1718        case DRVHOSTAUDIOWAS_DO_PRUNE_CACHE:
     1719            Assert(pStream == NULL);
     1720            Assert(pvUser == NULL);
     1721            drvHostAudioWasCachePrune(pThis);
    16221722            break;
    16231723
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