Changeset 107925 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Jan 23, 2025 5:19:50 PM (4 months ago)
- svn:sync-xref-src-repo-rev:
- 167156
- Location:
- trunk/src/VBox/Devices/Audio
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Audio/DrvAudio.cpp
r107735 r107925 4777 4777 "InputEnabled|" 4778 4778 "OutputEnabled|" 4779 "CacheEnabled|" 4779 4780 "DebugEnabled|" 4780 4781 "DebugPathOut|" -
trunk/src/VBox/Devices/Audio/DrvHostAudioWasApi.cpp
r107911 r107925 266 266 RTCRITSECTRW CritSectStreamList; 267 267 268 /** Whether the device cache (\a CacheHead and friends) is being used or not. 269 * Enabled by default, can be disabled via CFGM. */ 270 bool fCacheEnabled; 268 271 /** List of cached devices (DRVHOSTAUDIOWASCACHEDEV). 269 272 * Protected by CritSectCache */ … … 850 853 static void drvHostAudioWasCachePrune(PDRVHOSTAUDIOWAS pThis) 851 854 { 855 AssertReturnVoid(pThis->fCacheEnabled); 856 852 857 /* 853 858 * Prune each direction separately. … … 898 903 static void drvHostAudioWasCachePurge(PDRVHOSTAUDIOWAS pThis, bool fOnWorker) 899 904 { 905 AssertReturnVoid(pThis->fCacheEnabled); 906 900 907 for (;;) 901 908 { … … 1117 1124 * If lookup fails, a new entry will be created. 1118 1125 * 1119 * @note Called holding the lock, returning without holding it!1126 * @note Called holding the cache's lock, returning without holding it! 1120 1127 */ 1121 1128 static int drvHostAudioWasCacheLookupOrCreateConfig(PDRVHOSTAUDIOWAS pThis, PDRVHOSTAUDIOWASCACHEDEV pDevEntry, … … 1123 1130 PDRVHOSTAUDIOWASCACHEDEVCFG *ppDevCfg) 1124 1131 { 1132 PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg; 1133 1125 1134 /* 1126 1135 * Check if we've got a matching config. 1127 1136 */ 1128 PDRVHOSTAUDIOWASCACHEDEVCFG pDevCfg = drvHostAudioWasCacheLookupLocked(pDevEntry, &pCfgReq->Props); 1129 if (pDevCfg) 1130 { 1131 *ppDevCfg = pDevCfg; 1137 if (pThis->fCacheEnabled) 1138 { 1139 pDevCfg = drvHostAudioWasCacheLookupLocked(pDevEntry, &pCfgReq->Props); 1140 if (pDevCfg) 1141 { 1142 *ppDevCfg = pDevCfg; 1143 RTCritSectLeave(&pThis->CritSectCache); 1144 Log8Func(("Config cache hit '%s' on '%ls': %p\n", pDevCfg->szProps, pDevEntry->wszDevId, pDevCfg)); 1145 return VINF_SUCCESS; 1146 } 1147 1132 1148 RTCritSectLeave(&pThis->CritSectCache); 1133 Log8Func(("Config cache hit '%s' on '%ls': %p\n", pDevCfg->szProps, pDevEntry->wszDevId, pDevCfg)); 1134 return VINF_SUCCESS; 1135 } 1136 1137 RTCritSectLeave(&pThis->CritSectCache); 1149 } 1138 1150 1139 1151 /* … … 1142 1154 */ 1143 1155 pDevCfg = (PDRVHOSTAUDIOWASCACHEDEVCFG)RTMemAllocZ(sizeof(*pDevCfg)); 1144 Assert Return(pDevCfg, VERR_NO_MEMORY);1156 AssertPtrReturn(pDevCfg, VERR_NO_MEMORY); 1145 1157 RTListInit(&pDevCfg->ListEntry); 1146 1158 pDevCfg->pDevEntry = pDevEntry; … … 1152 1164 pDevCfg->nsLastUsed = pDevCfg->nsCreated; 1153 1165 1154 uint32_t cCacheEntries; 1155 if (pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN) 1156 cCacheEntries = ASMAtomicIncU32(&pThis->cCacheEntriesIn); 1157 else 1158 cCacheEntries = ASMAtomicIncU32(&pThis->cCacheEntriesOut); 1159 if (cCacheEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES) 1160 { 1161 LogFlowFunc(("Trigger cache pruning.\n")); 1162 int rc2 = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL /*pStream*/, 1163 DRVHOSTAUDIOWAS_DO_PRUNE_CACHE, NULL /*pvUser*/); 1164 AssertRCStmt(rc2, drvHostAudioWasCachePrune(pThis)); 1166 if (pThis->fCacheEnabled) 1167 { 1168 uint32_t cCacheEntries; 1169 if (pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN) 1170 cCacheEntries = ASMAtomicIncU32(&pThis->cCacheEntriesIn); 1171 else 1172 cCacheEntries = ASMAtomicIncU32(&pThis->cCacheEntriesOut); 1173 if (cCacheEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES) 1174 { 1175 LogFlowFunc(("Trigger cache pruning.\n")); 1176 int rc2 = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL /*pStream*/, 1177 DRVHOSTAUDIOWAS_DO_PRUNE_CACHE, NULL /*pvUser*/); 1178 AssertRCStmt(rc2, drvHostAudioWasCachePrune(pThis)); 1179 } 1165 1180 } 1166 1181 … … 1221 1236 if (SUCCEEDED(hrc)) 1222 1237 { 1223 LogRel2(("WasAPI: Checking for cached device '%ls' ...\n", pwszDevId)); 1224 1225 size_t cwcDevId = RTUtf16Len(pwszDevId); 1226 1227 /* 1228 * The cache has two levels, so first the device entry. 1229 */ 1230 PDRVHOSTAUDIOWASCACHEDEV pDevEntry, pDevEntryNext; 1231 RTCritSectEnter(&pThis->CritSectCache); 1232 RTListForEachSafe(&pThis->CacheHead, pDevEntry, pDevEntryNext, DRVHOSTAUDIOWASCACHEDEV, ListEntry) 1233 { 1234 if ( pDevEntry->cwcDevId == cwcDevId 1235 && pDevEntry->enmDir == pCfgReq->enmDir 1236 && RTUtf16Cmp(pDevEntry->wszDevId, pwszDevId) == 0) 1238 PDRVHOSTAUDIOWASCACHEDEV pDevEntry; 1239 size_t cwcDevId = RTUtf16Len(pwszDevId); 1240 1241 if (pThis->fCacheEnabled) 1242 { 1243 LogRel2(("WasAPI: Checking for cached device '%ls' ...\n", pwszDevId)); 1244 1245 /* 1246 * The cache has two levels, so first the device entry. 1247 */ 1248 PDRVHOSTAUDIOWASCACHEDEV pDevEntryNext; 1249 RTCritSectEnter(&pThis->CritSectCache); 1250 RTListForEachSafe(&pThis->CacheHead, pDevEntry, pDevEntryNext, DRVHOSTAUDIOWASCACHEDEV, ListEntry) 1237 1251 { 1238 /* 1239 * Cache hit -- here we now need to also check if the device interface we want to look up 1240 * actually matches the one we have in the cache entry. 1241 * 1242 * If it doesn't, bail out and add a new device entry to the cache with the new interface below then. 1243 * 1244 * This is needed when switching audio interfaces and the device interface becomes invalid via 1245 * AUDCLNT_E_DEVICE_INVALIDATED. See @bugref{10503} 1246 */ 1247 if (pDevEntry->pIDevice != pIDevice) 1252 if ( pDevEntry->cwcDevId == cwcDevId 1253 && pDevEntry->enmDir == pCfgReq->enmDir 1254 && RTUtf16Cmp(pDevEntry->wszDevId, pwszDevId) == 0) 1248 1255 { 1249 LogRel2(("WasAPI: Cache hit for device '%ls': Stale interface (new: %p, old: %p)\n", 1250 pDevEntry->wszDevId, pIDevice, pDevEntry->pIDevice)); 1251 1252 LogRel(("WasAPI: Stale audio interface '%ls' detected!\n", pDevEntry->wszDevId)); 1253 break; 1256 /* 1257 * Cache hit -- here we now need to also check if the device interface we want to look up 1258 * actually matches the one we have in the cache entry. 1259 * 1260 * If it doesn't, bail out and add a new device entry to the cache with the new interface below then. 1261 * 1262 * This is needed when switching audio interfaces and the device interface becomes invalid via 1263 * AUDCLNT_E_DEVICE_INVALIDATED. See @bugref{10503} 1264 */ 1265 if (pDevEntry->pIDevice != pIDevice) 1266 { 1267 LogRel2(("WasAPI: Cache hit for device '%ls': Stale interface (new: %p, old: %p)\n", 1268 pDevEntry->wszDevId, pIDevice, pDevEntry->pIDevice)); 1269 1270 LogRel(("WasAPI: Stale audio interface '%ls' detected!\n", pDevEntry->wszDevId)); 1271 break; 1272 } 1273 1274 LogRel2(("WasAPI: Cache hit for device '%ls' (%p)\n", pwszDevId, pIDevice)); 1275 1276 CoTaskMemFree(pwszDevId); 1277 pwszDevId = NULL; 1278 1279 return drvHostAudioWasCacheLookupOrCreateConfig(pThis, pDevEntry, pCfgReq, fOnWorker, ppDevCfg); 1254 1280 } 1255 1256 LogRel2(("WasAPI: Cache hit for device '%ls' (%p)\n", pwszDevId, pIDevice));1257 1258 CoTaskMemFree(pwszDevId);1259 pwszDevId = NULL;1260 1261 return drvHostAudioWasCacheLookupOrCreateConfig(pThis, pDevEntry, pCfgReq, fOnWorker, ppDevCfg);1262 1281 } 1263 } 1264 RTCritSectLeave(&pThis->CritSectCache); 1265 1266 LogRel2(("WasAPI: Cache miss for device '%ls' (%p)\n", pwszDevId, pIDevice)); 1282 RTCritSectLeave(&pThis->CritSectCache); 1283 1284 LogRel2(("WasAPI: Cache miss for device '%ls' (%p)\n", pwszDevId, pIDevice)); 1285 } 1286 else 1287 LogRel2(("WasAPI: Cache disabled for device '%ls' (%p)\n", pwszDevId, pIDevice)); 1267 1288 1268 1289 /* … … 1272 1293 if (pDevEntry) 1273 1294 { 1274 pIDevice->AddRef(); 1295 if (pThis->fCacheEnabled) 1296 pIDevice->AddRef(); 1275 1297 pDevEntry->pIDevice = pIDevice; 1276 1298 pDevEntry->enmDir = pCfgReq->enmDir; … … 1287 1309 pwszDevId = NULL; 1288 1310 1289 /* 1290 * Before adding the device, check that someone didn't race us adding it. 1291 */ 1292 RTCritSectEnter(&pThis->CritSectCache); 1293 PDRVHOSTAUDIOWASCACHEDEV pDevEntry2; 1294 RTListForEach(&pThis->CacheHead, pDevEntry2, DRVHOSTAUDIOWASCACHEDEV, ListEntry) 1311 if (pThis->fCacheEnabled) 1295 1312 { 1296 if ( pDevEntry2->cwcDevId == cwcDevId1297 /* Note: We have to compare the device interface here as well, as a cached device entry might1298 * have a stale audio interface for the same device. In such a case a new device entry will be created below.*/1299 && pDevEntry2->pIDevice == pIDevice1300 && pDevEntry2->enmDir == pCfgReq->enmDir1301 && RTUtf16Cmp(pDevEntry2->wszDevId, pDevEntry->wszDevId) == 0)1313 /* 1314 * Before adding the device to the cache, check that someone didn't race us adding it. 1315 */ 1316 RTCritSectEnter(&pThis->CritSectCache); 1317 PDRVHOSTAUDIOWASCACHEDEV pDevEntry2; 1318 RTListForEach(&pThis->CacheHead, pDevEntry2, DRVHOSTAUDIOWASCACHEDEV, ListEntry) 1302 1319 { 1303 pIDevice->Release(); 1304 RTMemFree(pDevEntry); 1305 pDevEntry = NULL; 1306 1307 LogRel2(("WasAPI: Lost race adding device '%ls': %p\n", pDevEntry2->wszDevId, pDevEntry2)); 1308 return drvHostAudioWasCacheLookupOrCreateConfig(pThis, pDevEntry2, pCfgReq, fOnWorker, ppDevCfg); 1320 if ( pDevEntry2->cwcDevId == cwcDevId 1321 /* Note: We have to compare the device interface here as well, as a cached device entry might 1322 * have a stale audio interface for the same device. In such a case a new device entry will be created below. */ 1323 && pDevEntry2->pIDevice == pIDevice 1324 && pDevEntry2->enmDir == pCfgReq->enmDir 1325 && RTUtf16Cmp(pDevEntry2->wszDevId, pDevEntry->wszDevId) == 0) 1326 { 1327 pIDevice->Release(); 1328 RTMemFree(pDevEntry); 1329 pDevEntry = NULL; 1330 1331 LogRel2(("WasAPI: Lost race adding device '%ls': %p\n", pDevEntry2->wszDevId, pDevEntry2)); 1332 return drvHostAudioWasCacheLookupOrCreateConfig(pThis, pDevEntry2, pCfgReq, fOnWorker, ppDevCfg); 1333 } 1309 1334 } 1335 RTListPrepend(&pThis->CacheHead, &pDevEntry->ListEntry); 1336 1337 LogRel2(("WasAPI: Added device '%ls' to cache: %p\n", pDevEntry->wszDevId, pDevEntry)); 1310 1338 } 1311 RTListPrepend(&pThis->CacheHead, &pDevEntry->ListEntry); 1312 1313 LogRel2(("WasAPI: Added device '%ls' to cache: %p\n", pDevEntry->wszDevId, pDevEntry)); 1339 1314 1340 return drvHostAudioWasCacheLookupOrCreateConfig(pThis, pDevEntry, pCfgReq, fOnWorker, ppDevCfg); 1315 1341 } … … 1337 1363 if (SUCCEEDED(hrc)) 1338 1364 { 1339 Log8Func(("Putting %p/'%s' back\n", pDevCfg, pDevCfg->szProps)); 1340 RTCritSectEnter(&pThis->CritSectCache); 1341 RTListAppend(&pDevCfg->pDevEntry->ConfigList, &pDevCfg->ListEntry); 1342 uint32_t const cEntries = pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN ? pThis->cCacheEntriesIn : pThis->cCacheEntriesOut; 1343 RTCritSectLeave(&pThis->CritSectCache); 1344 1345 /* Trigger pruning if we're over the threshold. */ 1346 if (cEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES) 1347 { 1348 LogFlowFunc(("Trigger cache pruning.\n")); 1349 int rc2 = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL /*pStream*/, 1350 DRVHOSTAUDIOWAS_DO_PRUNE_CACHE, NULL /*pvUser*/); 1351 AssertRCStmt(rc2, drvHostAudioWasCachePrune(pThis)); 1365 if (pThis->fCacheEnabled) 1366 { 1367 Log8Func(("Putting %p/'%s' back\n", pDevCfg, pDevCfg->szProps)); 1368 RTCritSectEnter(&pThis->CritSectCache); 1369 RTListAppend(&pDevCfg->pDevEntry->ConfigList, &pDevCfg->ListEntry); 1370 uint32_t const cEntries = pDevCfg->pDevEntry->enmDir == PDMAUDIODIR_IN ? pThis->cCacheEntriesIn : pThis->cCacheEntriesOut; 1371 RTCritSectLeave(&pThis->CritSectCache); 1372 1373 /* Trigger pruning if we're over the threshold. */ 1374 if (cEntries > VBOX_WASAPI_MAX_TOTAL_CONFIG_ENTRIES) 1375 { 1376 LogFlowFunc(("Trigger cache pruning.\n")); 1377 int rc2 = pThis->pIHostAudioPort->pfnDoOnWorkerThread(pThis->pIHostAudioPort, NULL /*pStream*/, 1378 DRVHOSTAUDIOWAS_DO_PRUNE_CACHE, NULL /*pvUser*/); 1379 AssertRCStmt(rc2, drvHostAudioWasCachePrune(pThis)); 1380 } 1352 1381 } 1353 1382 } … … 1915 1944 Assert(pStream == NULL); 1916 1945 Assert(pvUser == NULL); 1946 Assert(pThis->fCacheEnabled); 1917 1947 drvHostAudioWasCachePurge(pThis, true /*fOnWorker*/); 1918 1948 break; … … 1921 1951 Assert(pStream == NULL); 1922 1952 Assert(pvUser == NULL); 1953 Assert(pThis->fCacheEnabled); 1923 1954 drvHostAudioWasCachePrune(pThis); 1924 1955 break; … … 3030 3061 } 3031 3062 #else 3032 if (!RTListIsEmpty(&pThis->CacheHead) && pThis->pIHostAudioPort) 3063 if ( pThis->fCacheEnabled 3064 && !RTListIsEmpty(&pThis->CacheHead) && pThis->pIHostAudioPort) 3033 3065 { 3034 3066 int rc = RTSemEventMultiCreate(&pThis->hEvtCachePurge); … … 3092 3124 #endif 3093 3125 3094 if (RTCritSectIsInitialized(&pThis->CritSectCache)) 3095 { 3096 drvHostAudioWasCachePurge(pThis, false /*fOnWorker*/); 3126 if (pThis->fCacheEnabled) 3127 { 3128 if (RTCritSectIsInitialized(&pThis->CritSectCache)) 3129 { 3130 drvHostAudioWasCachePurge(pThis, false /*fOnWorker*/); 3131 if (pThis->hEvtCachePurge != NIL_RTSEMEVENTMULTI) 3132 RTSemEventMultiWait(pThis->hEvtCachePurge, RT_MS_30SEC); 3133 RTCritSectDelete(&pThis->CritSectCache); 3134 } 3135 3097 3136 if (pThis->hEvtCachePurge != NIL_RTSEMEVENTMULTI) 3098 RTSemEventMultiWait(pThis->hEvtCachePurge, RT_MS_30SEC); 3099 RTCritSectDelete(&pThis->CritSectCache); 3100 } 3101 3102 if (pThis->hEvtCachePurge != NIL_RTSEMEVENTMULTI) 3103 { 3104 RTSemEventMultiDestroy(pThis->hEvtCachePurge); 3105 pThis->hEvtCachePurge = NIL_RTSEMEVENTMULTI; 3137 { 3138 RTSemEventMultiDestroy(pThis->hEvtCachePurge); 3139 pThis->hEvtCachePurge = NIL_RTSEMEVENTMULTI; 3140 } 3141 } 3142 else 3143 { 3144 Assert(pThis->cCacheEntriesIn == 0); 3145 Assert(pThis->cCacheEntriesOut == 0); 3106 3146 } 3107 3147 … … 3181 3221 * Validate and read the configuration. 3182 3222 */ 3183 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "VmName|VmUuid|InputDeviceID|OutputDeviceID ", "");3223 PDMDRV_VALIDATE_CONFIG_RETURN(pDrvIns, "VmName|VmUuid|InputDeviceID|OutputDeviceID|CacheEnabled", ""); 3184 3224 3185 3225 char szTmp[1024]; … … 3200 3240 } 3201 3241 3242 /* Caching is enabled by default. */ 3243 rc = pHlp->pfnCFGMQueryBoolDef(pCfg, "CacheEnabled", &pThis->fCacheEnabled, true); 3244 AssertMsgRCReturn(rc, ("Confguration error: Failed to read \"CacheEnabled\" as boolean: rc=%Rrc\n", rc), rc); 3245 3202 3246 AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER, 3203 3247 ("Configuration error: Not possible to attach anything to this driver!\n"), 3204 3248 VERR_PDM_DRVINS_NO_ATTACH); 3205 3249 3250 LogRel2(("WasAPI: Caching device configuration entries is %s\n", pThis->fCacheEnabled ? "enabled" : "disabled")); 3251 3206 3252 /* 3207 3253 * Initialize the critical sections early. … … 3210 3256 AssertRCReturn(rc, rc); 3211 3257 3212 rc = RTCritSectInit(&pThis->CritSectCache); 3213 AssertRCReturn(rc, rc); 3258 if (pThis->fCacheEnabled) 3259 { 3260 rc = RTCritSectInit(&pThis->CritSectCache); 3261 AssertRCReturn(rc, rc); 3262 } 3214 3263 3215 3264 /* … … 3322 3371 * Prime the cache. 3323 3372 */ 3324 drvHostAudioWasCacheFill(pThis); 3373 if (pThis->fCacheEnabled) 3374 drvHostAudioWasCacheFill(pThis); 3325 3375 3326 3376 return VINF_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.