VirtualBox

Changeset 89208 in vbox for trunk


Ignore:
Timestamp:
May 20, 2021 9:52:42 PM (4 years ago)
Author:
vboxsync
Message:

DrvAudio,pdmaudioifs.h: Reworked the DrvAudio locking. bugref:9890

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/pdmaudioifs.h

    r89184 r89208  
    231231
    232232#include <iprt/assertcompile.h>
     233#include <iprt/critsect.h>
    233234#include <iprt/circbuf.h>
    234235#include <iprt/list.h>
     
    995996typedef struct PDMAUDIOSTREAM
    996997{
     998    /** Critical section protecting the stream.
     999     *
     1000     * When not otherwise stated, DrvAudio will enter this before calling the
     1001     * backend.   The backend and device/mixer can normally safely enter it prior to
     1002     * a DrvAudio call, however not to pfnStreamDestroy, pfnStreamRelease or
     1003     * anything that may access the stream list.
     1004     *
     1005     * @note Lock ordering:
     1006     *          - After DRVAUDIO::CritSectGlobals.
     1007     *          - Before DRVAUDIO::CritSectHotPlug. */
     1008    RTCRITSECT              CritSect;
    9971009    /** Magic value (PDMAUDIOSTREAM_MAGIC). */
    9981010    uint32_t                uMagic;
     
    10171029
    10181030/** Magic value for PDMAUDIOSTREAM. */
    1019 #define PDMAUDIOSTREAM_MAGIC    PDM_VERSION_MAKE(0xa0d3, 4, 0)
     1031#define PDMAUDIOSTREAM_MAGIC    PDM_VERSION_MAKE(0xa0d3, 5, 0)
    10201032
    10211033
     
    12381250
    12391251/** PDMIAUDIOCONNECTOR interface ID. */
    1240 #define PDMIAUDIOCONNECTOR_IID                  "2c2bdfcd-7a2b-4739-9663-07ee9e8fe079"
     1252#define PDMIAUDIOCONNECTOR_IID                  "04ad443a-d860-443a-afc9-98bbad4b1341"
    12411253
    12421254
     
    14201432     *
    14211433     * @param   pInterface          Pointer to this interface.
    1422      * @param   pStream             Pointer to audio stream.
     1434     * @param   pStream             Pointer to audio stream (locked).
    14231435     * @param   pvUser              Backend specific parameter from the call to
    14241436     *                              PDMIHOSTAUDIOPORT::pfnNotifyDeviceChanged.
     
    15161528
    15171529/** PDMIHOSTAUDIO interface ID. */
    1518 #define PDMIHOSTAUDIO_IID                           "a5650399-be78-4e82-8115-e34a4450378c"
     1530#define PDMIHOSTAUDIO_IID                           "8c68a5a9-6c46-43c2-9d4e-e1bd13d2b97d"
    15191531
    15201532
     
    16011613
    16021614/** PDMIHOSTAUDIOPORT interface ID. */
    1603 #define PDMIHOSTAUDIOPORT_IID                    "c752404b-1ccb-4fc0-aa60-eb76ae130e0f"
     1615#define PDMIHOSTAUDIOPORT_IID                    "cd006383-7be1-4dbe-a69e-21236413cf30"
    16041616
    16051617/** @} */
  • trunk/src/VBox/Devices/Audio/DrvAudio.cpp

    r89191 r89208  
    318318typedef struct DRVAUDIO
    319319{
     320    /** Read/Write critical section for guarding changes to pHostDrvAudio and
     321     *  BackendCfg during deteach/attach.  Mostly taken in shared mode.
     322     * @note Locking order: Must be entered after CritSectGlobals.
     323     * @note Locking order: Must be entered after PDMAUDIOSTREAM::CritSect. */
     324    RTCRITSECTRW            CritSectHotPlug;
    320325    /** Critical section for protecting:
    321326     *      - LstStreams
     327     *      - cStreams
    322328     *      - In.fEnabled
    323329     *      - In.cStreamsFree
    324330     *      - Out.fEnabled
    325331     *      - Out.cStreamsFree
    326      */
    327     RTCRITSECT              CritSect;
     332     * @note Locking order: Must be entered before PDMAUDIOSTREAM::CritSect.
     333     * @note Locking order: Must be entered before CritSectHotPlug. */
     334    RTCRITSECTRW            CritSectGlobals;
    328335    /** List of audio streams (DRVAUDIOSTREAM). */
    329336    RTLISTANCHOR            LstStreams;
     337    /** Number of streams in the list. */
     338    size_t                  cStreams;
    330339    struct
    331340    {
     
    402411static uint32_t drvAudioStreamReleaseInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, bool fMayDestroy);
    403412static void drvAudioStreamResetInternal(PDRVAUDIOSTREAM pStreamEx);
    404 static int drvAudioStreamIterateInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx);
    405413
    406414
     
    693701static DECLCALLBACK(int) drvAudioDevicesEnumerateInternal(PDRVAUDIO pThis, bool fLog, PPDMAUDIOHOSTENUM pDevEnum)
    694702{
    695     AssertReturn(!RTCritSectIsOwner(&pThis->CritSect), VERR_WRONG_ORDER);
     703    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    696704
    697705    int rc;
     
    743751    }
    744752
     753    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    745754    LogFunc(("Returning %Rrc\n", rc));
    746755    return rc;
     
    776785     * Grab the driver wide lock and check it.  Ignore call if no change.
    777786     */
    778     int rc = RTCritSectEnter(&pThis->CritSect);
     787    int rc = RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
    779788    AssertRCReturn(rc, rc);
    780789
     
    866875    }
    867876
    868     RTCritSectLeave(&pThis->CritSect);
     877    RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
    869878    LogFlowFuncLeaveRC(rc);
    870879    return rc;
     
    879888    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    880889    AssertPtr(pThis);
    881     int rc = RTCritSectEnter(&pThis->CritSect);
     890    int rc = RTCritSectRwEnterShared(&pThis->CritSectGlobals);
    882891    AssertRCReturn(rc, false);
    883892
     
    890899        AssertFailedStmt(fEnabled = false);
    891900
    892     RTCritSectLeave(&pThis->CritSect);
     901    RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
    893902    return fEnabled;
    894903}
     
    903912    AssertPtr(pThis);
    904913    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
    905     int rc = RTCritSectEnter(&pThis->CritSect);
     914    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    906915    AssertRCReturn(rc, rc);
    907916
    908917    if (pThis->pHostDrvAudio)
    909     {
    910         if (pThis->pHostDrvAudio->pfnGetConfig)
    911             rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, pCfg);
    912         else
    913             rc = VERR_NOT_SUPPORTED;
    914     }
     918        rc = pThis->pHostDrvAudio->pfnGetConfig(pThis->pHostDrvAudio, pCfg);
    915919    else
    916920        rc = VERR_PDM_NO_ATTACHED_DRIVER;
    917921
    918     RTCritSectLeave(&pThis->CritSect);
     922    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    919923    LogFlowFuncLeaveRC(rc);
    920924    return rc;
     
    929933    PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IAudioConnector);
    930934    AssertPtr(pThis);
    931     int rc = RTCritSectEnter(&pThis->CritSect);
     935    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    932936    AssertRCReturn(rc, PDMAUDIOBACKENDSTS_UNKNOWN);
    933937
     
    943947        fBackendStatus = PDMAUDIOBACKENDSTS_NOT_ATTACHED;
    944948
    945     RTCritSectLeave(&pThis->CritSect);
     949    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    946950    LogFlowFunc(("LEAVE - %#x\n", fBackendStatus));
    947951    return fBackendStatus;
     
    966970        pStreamEx->pBackend       = NULL;
    967971        pStreamEx->uMagic         = DRVAUDIOSTREAM_MAGIC_DEAD;
     972
     973        RTCritSectDelete(&pStreamEx->Core.CritSect);
    968974
    969975        RTMemFree(pStreamEx);
     
    11291135 * PDMAUDIOBACKEND_F_ASYNC_HINT is in effect.
    11301136 */
    1131 static DECLCALLBACK(void) drvAudioStreamConfigHintWorker(PPDMIHOSTAUDIO pHostDrvAudio, PPDMAUDIOSTREAMCFG pCfg)
    1132 {
    1133     LogFlowFunc(("pHostDrvAudio=%p pCfg=%p\n", pHostDrvAudio, pCfg));
     1137static DECLCALLBACK(void) drvAudioStreamConfigHintWorker(PDRVAUDIO pThis, PPDMAUDIOSTREAMCFG pCfg)
     1138{
     1139    LogFlowFunc(("pThis=%p pCfg=%p\n", pThis, pCfg));
    11341140    AssertPtrReturnVoid(pCfg);
    1135     AssertPtrReturnVoid(pHostDrvAudio);
    1136     AssertPtrReturnVoid(pHostDrvAudio->pfnStreamConfigHint);
    1137 
    1138     pHostDrvAudio->pfnStreamConfigHint(pHostDrvAudio, pCfg);
     1141    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     1142    AssertRCReturnVoid(rc);
     1143
     1144    PPDMIHOSTAUDIO const pHostDrvAudio = pThis->pHostDrvAudio;
     1145    if (pHostDrvAudio)
     1146    {
     1147        AssertPtr(pHostDrvAudio->pfnStreamConfigHint);
     1148        if (pHostDrvAudio->pfnStreamConfigHint)
     1149            pHostDrvAudio->pfnStreamConfigHint(pHostDrvAudio, pCfg);
     1150    }
    11391151    PDMAudioStrmCfgFree(pCfg);
     1152
     1153    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    11401154    LogFlowFunc(("returns\n"));
    11411155}
     
    11501164    AssertReturnVoid(pCfg->enmDir == PDMAUDIODIR_IN || pCfg->enmDir == PDMAUDIODIR_OUT);
    11511165
    1152     int rc = RTCritSectEnter(&pThis->CritSect); /** @todo Reconsider the locking for DrvAudio */
     1166    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    11531167    AssertRCReturnVoid(rc);
    11541168
     
    11751189                    if (pDupCfg)
    11761190                    {
    1177                         rc = RTReqPoolCallVoidNoWait(pThis->hReqPool, (PFNRT)drvAudioStreamConfigHintWorker,
    1178                                                      2, pThis->pHostDrvAudio, pDupCfg);
     1191                        rc = RTReqPoolCallVoidNoWait(pThis->hReqPool, (PFNRT)drvAudioStreamConfigHintWorker, 2, pThis, pDupCfg);
    11791192                        if (RT_SUCCESS(rc))
    11801193                            LogFlowFunc(("Asynchronous call running on worker thread.\n"));
     
    11961209        LogFlowFunc(("Ignoring hint because backend has no pfnStreamConfigHint method.\n"));
    11971210
    1198     RTCritSectLeave(&pThis->CritSect);
     1211    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    11991212}
    12001213
     
    12051218 *
    12061219 * Used by async init and re-init.
     1220 *
     1221 * @note Is sometimes called w/o having entered DRVAUDIO::CritSectHotPlug.
     1222 *       Caller must however own the stream critsect.
    12071223 */
    12081224static int drvAudioStreamUpdateBackendOnStatus(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, const char *pszWhen)
     
    12381254    LogFlow(("pThis=%p pStreamEx=%p (%s)\n", pThis, pStreamEx, pStreamEx->Core.szName));
    12391255
     1256    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     1257    AssertRCReturnVoid(rc);
     1258
    12401259    /*
    12411260     * Do the init job.
    1242      *
    1243      * This critsect entering and leaving here isn't really necessary,
    1244      * but well, I'm a bit paranoid, so sue me.
    1245      */
    1246     RTCritSectEnter(&pThis->CritSect);
     1261     */
     1262    bool           fDestroyed;
    12471263    PPDMIHOSTAUDIO pIHostDrvAudio = pThis->pHostDrvAudio;
    1248     RTCritSectLeave(&pThis->CritSect);
    12491264    AssertPtr(pIHostDrvAudio);
    1250     int rc;
    1251     bool fDestroyed;
    12521265    if (pIHostDrvAudio && pIHostDrvAudio->pfnStreamInitAsync)
    12531266    {
     
    12621275    }
    12631276
     1277    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     1278    RTCritSectEnter(&pStreamEx->Core.CritSect);
     1279
    12641280    /*
    12651281     * On success, update the backend on the stream status and mark it ready for business.
    12661282     */
    1267     RTCritSectEnter(&pThis->CritSect);
    12681283    if (RT_SUCCESS(rc) && !fDestroyed)
    12691284    {
     1285        RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    12701286
    12711287        /*
     
    13101326         */
    13111327        pStreamEx->enmLastBackendState = drvAudioStreamGetBackendState(pThis, pStreamEx);
     1328
     1329        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    13121330    }
    13131331    /*
     
    13291347    }
    13301348
    1331     RTCritSectLeave(&pThis->CritSect);
     1349    RTCritSectLeave(&pStreamEx->Core.CritSect);
    13321350
    13331351    /*
     
    13861404     * Call the host driver to create the stream.
    13871405     */
    1388     AssertLogRelMsgReturn(RT_VALID_PTR(pThis->pHostDrvAudio), ("Audio: %p\n", pThis->pHostDrvAudio), VERR_PDM_NO_ATTACHED_DRIVER);
    1389     rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStreamEx->pBackend, pCfgReq, pCfgAcq);
     1406    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     1407
     1408    AssertLogRelMsgStmt(RT_VALID_PTR(pThis->pHostDrvAudio),
     1409                        ("Audio: %p\n", pThis->pHostDrvAudio), rc = VERR_PDM_NO_ATTACHED_DRIVER);
    13901410    if (RT_SUCCESS(rc))
     1411        AssertLogRelMsgStmt(pStreamEx->Core.cbBackend == pThis->BackendCfg.cbStream,
     1412                            ("Audio: Backend changed? cbBackend changed from %#x to %#x\n",
     1413                             pStreamEx->Core.cbBackend, pThis->BackendCfg.cbStream),
     1414                            rc = VERR_STATE_CHANGED);
     1415    if (RT_SUCCESS(rc))
     1416        rc = pThis->pHostDrvAudio->pfnStreamCreate(pThis->pHostDrvAudio, pStreamEx->pBackend, pCfgReq, pCfgAcq);
     1417    if (RT_SUCCESS(rc))
    13911418    {
    13921419        pStreamEx->enmLastBackendState = drvAudioStreamGetBackendState(pThis, pStreamEx);
     1420
     1421        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    13931422
    13941423        AssertLogRelReturn(pStreamEx->pBackend->uMagic  == PDMAUDIOBACKENDSTREAM_MAGIC, VERR_INTERNAL_ERROR_3);
     
    14021431    else
    14031432    {
     1433        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    14041434        if (rc == VERR_NOT_SUPPORTED)
    14051435            LogRel2(("Audio: Creating stream '%s' in backend not supported\n", pStreamEx->Core.szName));
     
    17311761
    17321762    /*
    1733      * Lock the whole driver instance.
    1734      */
    1735     int rc = RTCritSectEnter(&pThis->CritSect);
     1763     * Grab a free stream count now.
     1764     */
     1765    int rc = RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
    17361766    AssertRCReturn(rc, rc);
    17371767
    1738     /*
    1739      * Check that we have free streams in the backend and get the
    1740      * size of the backend specific stream data.
    1741      */
    1742     uint32_t *pcFreeStreams;
    1743     if (pCfgHost->enmDir == PDMAUDIODIR_IN)
    1744     {
    1745         if (!pThis->In.cStreamsFree)
    1746         {
    1747             LogFlowFunc(("Maximum number of host input streams reached\n"));
    1748             rc = VERR_AUDIO_NO_FREE_INPUT_STREAMS;
    1749         }
    1750         pcFreeStreams = &pThis->In.cStreamsFree;
    1751     }
    1752     else /* Out */
    1753     {
    1754         if (!pThis->Out.cStreamsFree)
    1755         {
    1756             LogFlowFunc(("Maximum number of host output streams reached\n"));
    1757             rc = VERR_AUDIO_NO_FREE_OUTPUT_STREAMS;
    1758         }
    1759         pcFreeStreams = &pThis->Out.cStreamsFree;
    1760     }
     1768    uint32_t * const pcFreeStreams = pCfgHost->enmDir == PDMAUDIODIR_IN ? &pThis->In.cStreamsFree : &pThis->Out.cStreamsFree;
     1769    if (*pcFreeStreams > 0)
     1770        *pcFreeStreams -= 1;
     1771    else
     1772    {
     1773        RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
     1774        LogFlowFunc(("Maximum number of host %s streams reached\n", PDMAudioDirGetName(pCfgHost->enmDir) ));
     1775        return pCfgHost->enmDir == PDMAUDIODIR_IN ? VERR_AUDIO_NO_FREE_INPUT_STREAMS : VERR_AUDIO_NO_FREE_OUTPUT_STREAMS;
     1776    }
     1777
     1778    RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
     1779
     1780    /*
     1781     * Get and check the backend size.
     1782     *
     1783     * Since we'll have to leave the hot-plug lock before we call the backend,
     1784     * we'll have revalidate the size at that time.
     1785     */
     1786    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     1787
    17611788    size_t const cbHstStrm = pThis->BackendCfg.cbStream;
    17621789    AssertStmt(cbHstStrm >= sizeof(PDMAUDIOBACKENDSTREAM), rc = VERR_OUT_OF_RANGE);
    17631790    AssertStmt(cbHstStrm < _16M, rc = VERR_OUT_OF_RANGE);
     1791
     1792    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    17641793    if (RT_SUCCESS(rc))
    17651794    {
     
    17701799        if (pStreamEx)
    17711800        {
    1772             /* Make a unqiue stream name including the host (backend) driver name. */
    1773             AssertPtr(pThis->pHostDrvAudio);
    1774             size_t cchName = RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s:0",
    1775                                          pThis->BackendCfg.szName, pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<Untitled>");
    1776             if (cchName < sizeof(pStreamEx->Core.szName))
     1801            rc = RTCritSectInit(&pStreamEx->Core.CritSect); /* (drvAudioStreamFree assumes it's initailized) */
     1802            if (RT_SUCCESS(rc))
    17771803            {
    1778                 for (uint32_t i = 0; i < 256; i++)
     1804                PPDMAUDIOBACKENDSTREAM pBackend = (PPDMAUDIOBACKENDSTREAM)(pStreamEx + 1);
     1805                pBackend->uMagic            = PDMAUDIOBACKENDSTREAM_MAGIC;
     1806                pBackend->pStream           = &pStreamEx->Core;
     1807
     1808                pStreamEx->pBackend         = pBackend;
     1809                pStreamEx->Core.enmDir      = pCfgHost->enmDir;
     1810                pStreamEx->Core.cbBackend   = (uint32_t)cbHstStrm;
     1811                pStreamEx->fNoMixBufs       = RT_BOOL(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF);
     1812                pStreamEx->hReqInitAsync    = NIL_RTREQ;
     1813                pStreamEx->uMagic           = DRVAUDIOSTREAM_MAGIC;
     1814
     1815                /* Make a unqiue stream name including the host (backend) driver name. */
     1816                AssertPtr(pThis->pHostDrvAudio);
     1817                size_t cchName = RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s:0",
     1818                                             pThis->BackendCfg.szName, pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<NoName>");
     1819                if (cchName < sizeof(pStreamEx->Core.szName))
    17791820                {
    1780                     bool fDone = true;
    1781                     PDRVAUDIOSTREAM pIt;
    1782                     RTListForEach(&pThis->LstStreams, pIt, DRVAUDIOSTREAM, ListEntry)
     1821                    RTCritSectRwEnterShared(&pThis->CritSectGlobals);
     1822                    for (uint32_t i = 0; i < 256; i++)
    17831823                    {
    1784                         if (strcmp(pIt->Core.szName, pStreamEx->Core.szName) == 0)
     1824                        bool fDone = true;
     1825                        PDRVAUDIOSTREAM pIt;
     1826                        RTListForEach(&pThis->LstStreams, pIt, DRVAUDIOSTREAM, ListEntry)
    17851827                        {
    1786                             RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s:%u",
    1787                                         pThis->BackendCfg.szName, pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<Untitled>",
    1788                                         i);
    1789                             fDone = false;
     1828                            if (strcmp(pIt->Core.szName, pStreamEx->Core.szName) == 0)
     1829                            {
     1830                                RTStrPrintf(pStreamEx->Core.szName, RT_ELEMENTS(pStreamEx->Core.szName), "[%s] %s:%u",
     1831                                            pThis->BackendCfg.szName, pCfgHost->szName[0] != '\0' ? pCfgHost->szName : "<NoName>",
     1832                                            i);
     1833                                fDone = false;
     1834                                break;
     1835                            }
     1836                        }
     1837                        if (fDone)
    17901838                            break;
     1839                    }
     1840                    RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
     1841                }
     1842
     1843                /*
     1844                 * Try to init the rest.
     1845                 */
     1846                rc = drvAudioStreamInitInternal(pThis, pStreamEx, fFlags, pCfgHost, pCfgGuest);
     1847                if (RT_SUCCESS(rc))
     1848                {
     1849                    /* Set initial reference counts. */
     1850                    pStreamEx->cRefs = pStreamEx->fNeedAsyncInit ? 2 : 1;
     1851
     1852                    /* Add it to the list. */
     1853                    RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
     1854
     1855                    RTListAppend(&pThis->LstStreams, &pStreamEx->ListEntry);
     1856                    pThis->cStreams++;
     1857                    STAM_COUNTER_INC(&pThis->Stats.TotalStreamsCreated);
     1858
     1859                    RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
     1860
     1861                    /*
     1862                     * Init debug stuff if enabled (ignore failures).
     1863                     */
     1864                    if (pCfgHost->enmDir == PDMAUDIODIR_IN)
     1865                    {
     1866                        if (pThis->CfgIn.Dbg.fEnabled)
     1867                        {
     1868                            AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileCaptureNonInterleaved, pThis->CfgIn.Dbg.szPathOut,
     1869                                                      "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
     1870                            AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileStreamRead, pThis->CfgIn.Dbg.szPathOut,
     1871                                                      "DrvAudioRead", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    17911872                        }
    17921873                    }
    1793                     if (fDone)
    1794                         break;
     1874                    else /* Out */
     1875                    {
     1876                        if (pThis->CfgOut.Dbg.fEnabled)
     1877                        {
     1878                            AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFilePlayNonInterleaved, pThis->CfgOut.Dbg.szPathOut,
     1879                                                      "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
     1880                            AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFileStreamWrite, pThis->CfgOut.Dbg.szPathOut,
     1881                                                      "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
     1882                        }
     1883                    }
     1884
     1885                    /*
     1886                     * Kick off the asynchronous init.
     1887                     */
     1888                    if (!pStreamEx->fNeedAsyncInit)
     1889                    {
     1890                        pStreamEx->fStatus |= PDMAUDIOSTREAM_STS_BACKEND_READY;
     1891                        PDMAUDIOSTREAM_STS_ASSERT_VALID(pStreamEx->fStatus);
     1892                    }
     1893                    else
     1894                    {
     1895                        int rc2 = RTReqPoolCallEx(pThis->hReqPool, 0 /*cMillies*/, &pStreamEx->hReqInitAsync,
     1896                                                  RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     1897                                                  (PFNRT)drvAudioStreamInitAsync, 2, pThis, pStreamEx);
     1898                        LogFlowFunc(("hReqInitAsync=%p rc2=%Rrc\n", pStreamEx->hReqInitAsync, rc2));
     1899                        AssertRCStmt(rc2, drvAudioStreamInitAsync(pThis, pStreamEx));
     1900                    }
     1901
     1902#ifdef VBOX_STRICT
     1903                    /*
     1904                     * Assert lock order to make sure the lock validator picks up on it.
     1905                     */
     1906                    RTCritSectRwEnterShared(&pThis->CritSectGlobals);
     1907                    RTCritSectEnter(&pStreamEx->Core.CritSect);
     1908                    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     1909                    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     1910                    RTCritSectLeave(&pStreamEx->Core.CritSect);
     1911                    RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
     1912#endif
     1913
     1914                    *ppStream = &pStreamEx->Core;
     1915                    LogFlowFunc(("returns VINF_SUCCESS (pStreamEx=%p)\n", pStreamEx));
     1916                    return VINF_SUCCESS;
    17951917                }
    1796             }
    1797 
    1798             PPDMAUDIOBACKENDSTREAM pBackend = (PPDMAUDIOBACKENDSTREAM)(pStreamEx + 1);
    1799             pBackend->uMagic            = PDMAUDIOBACKENDSTREAM_MAGIC;
    1800             pBackend->pStream           = &pStreamEx->Core;
    1801             pStreamEx->pBackend         = pBackend;
    1802             pStreamEx->Core.enmDir      = pCfgHost->enmDir;
    1803             pStreamEx->Core.cbBackend   = (uint32_t)cbHstStrm;
    1804             pStreamEx->fNoMixBufs       = RT_BOOL(fFlags & PDMAUDIOSTREAM_CREATE_F_NO_MIXBUF);
    1805             pStreamEx->hReqInitAsync    = NIL_RTREQ;
    1806             pStreamEx->uMagic           = DRVAUDIOSTREAM_MAGIC;
    1807 
    1808             /*
    1809              * Try to init the rest.
    1810              */
    1811             rc = drvAudioStreamInitInternal(pThis, pStreamEx, fFlags, pCfgHost, pCfgGuest);
    1812             if (RT_SUCCESS(rc))
    1813             {
    1814                 /* Set initial reference counts. */
    1815                 pStreamEx->cRefs = pStreamEx->fNeedAsyncInit ? 2 : 1;
    1816 
    1817                 /* Decrement the free stream counter. */
    1818                 Assert(*pcFreeStreams > 0);
    1819                 *pcFreeStreams -= 1;
    1820 
    1821                 /*
    1822                  * We're good.
    1823                  */
    1824                 RTListAppend(&pThis->LstStreams, &pStreamEx->ListEntry);
    1825                 STAM_COUNTER_INC(&pThis->Stats.TotalStreamsCreated);
    1826                 *ppStream = &pStreamEx->Core;
    1827 
    1828                 /*
    1829                  * Init debug stuff if enabled (ignore failures).
    1830                  */
    1831                 if (pCfgHost->enmDir == PDMAUDIODIR_IN)
    1832                 {
    1833                     if (pThis->CfgIn.Dbg.fEnabled)
    1834                     {
    1835                         AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileCaptureNonInterleaved, pThis->CfgIn.Dbg.szPathOut,
    1836                                                   "DrvAudioCapNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    1837                         AudioHlpFileCreateAndOpen(&pStreamEx->In.Dbg.pFileStreamRead, pThis->CfgIn.Dbg.szPathOut,
    1838                                                   "DrvAudioRead", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    1839                     }
    1840                 }
    1841                 else /* Out */
    1842                 {
    1843                     if (pThis->CfgOut.Dbg.fEnabled)
    1844                     {
    1845                         AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFilePlayNonInterleaved, pThis->CfgOut.Dbg.szPathOut,
    1846                                                   "DrvAudioPlayNonInt", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    1847                         AudioHlpFileCreateAndOpen(&pStreamEx->Out.Dbg.pFileStreamWrite, pThis->CfgOut.Dbg.szPathOut,
    1848                                                   "DrvAudioWrite", pThis->pDrvIns->iInstance, &pStreamEx->Host.Cfg.Props);
    1849                     }
    1850                 }
    1851 
    1852                 /*
    1853                  * Kick off the asynchronous init.
    1854                  */
    1855                 if (!pStreamEx->fNeedAsyncInit)
    1856                 {
    1857                     pStreamEx->fStatus |= PDMAUDIOSTREAM_STS_BACKEND_READY;
    1858                     PDMAUDIOSTREAM_STS_ASSERT_VALID(pStreamEx->fStatus);
    1859                 }
    1860                 else
    1861                 {
    1862                     int rc2 = RTReqPoolCallEx(pThis->hReqPool, 0 /*cMillies*/, &pStreamEx->hReqInitAsync,
    1863                                               RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
    1864                                               (PFNRT)drvAudioStreamInitAsync, 2, pThis, pStreamEx);
    1865                     LogFlowFunc(("hReqInitAsync=%p rc2=%Rrc\n", pStreamEx->hReqInitAsync, rc2));
    1866                     AssertRCStmt(rc2, drvAudioStreamInitAsync(pThis, pStreamEx));
    1867                 }
    1868             }
    1869             else
    1870             {
     1918
    18711919                LogFunc(("drvAudioStreamInitInternal failed: %Rrc\n", rc));
    18721920                int rc2 = drvAudioStreamUninitInternal(pThis, pStreamEx);
     
    18741922                drvAudioStreamFree(pStreamEx);
    18751923            }
     1924            else
     1925                RTMemFree(pStreamEx);
    18761926        }
    18771927        else
     
    18791929    }
    18801930
    1881     RTCritSectLeave(&pThis->CritSect);
     1931    /*
     1932     * Give back the stream count, we couldn't use it after all.
     1933     */
     1934    RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
     1935    Assert(*pcFreeStreams >= 0);
     1936    *pcFreeStreams += 1;
     1937    RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
     1938
    18821939    LogFlowFuncLeaveRC(rc);
    18831940    return rc;
     
    19131970        /* Check if the pointer to  the host audio driver is still valid.
    19141971         * It can be NULL if we were called in drvAudioDestruct, for example. */
     1972        RTCritSectRwEnterShared(&pThis->CritSectHotPlug); /** @todo needed? */
    19151973        if (pThis->pHostDrvAudio)
    19161974            rc = pThis->pHostDrvAudio->pfnStreamDestroy(pThis->pHostDrvAudio, pStreamEx->pBackend);
     1975        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    19171976
    19181977        pStreamEx->fStatus &= ~(PDMAUDIOSTREAM_STS_BACKEND_CREATED | PDMAUDIOSTREAM_STS_BACKEND_READY);
     
    19321991 * @param   pThis       Pointer to driver instance.
    19331992 * @param   pStreamEx   Pointer to audio stream to uninitialize.
    1934  *
    1935  * @note    Caller owns the critical section.
    19361993 */
    19371994static int drvAudioStreamUninitInternal(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
     
    19421999                    VERR_WRONG_ORDER);
    19432000    LogFlowFunc(("[%s] cRefs=%RU32\n", pStreamEx->Core.szName, pStreamEx->cRefs));
     2001
     2002    RTCritSectEnter(&pStreamEx->Core.CritSect);
    19442003
    19452004    /*
     
    20042063        }
    20052064    }
     2065
     2066    RTCritSectLeave(&pStreamEx->Core.CritSect);
    20062067    LogFlowFunc(("Returning %Rrc\n", rc));
    20072068    return rc;
     
    20232084    AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, UINT32_MAX);
    20242085    AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, UINT32_MAX);
     2086    Assert(!RTCritSectIsOwner(&pStreamEx->Core.CritSect));
    20252087
    20262088    uint32_t cRefs = ASMAtomicDecU32(&pStreamEx->cRefs);
     
    20352097 * doesn't) and backend implementation.  Ofc, the backend probably needs an
    20362098 * opt-out here. */
    2037         int rc = RTCritSectEnter(&pThis->CritSect);
    2038         AssertRC(rc);
    2039 
    2040         rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
     2099        int rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
    20412100        if (RT_SUCCESS(rc))
    20422101        {
     2102            RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
     2103
    20432104            if (pStreamEx->Core.enmDir == PDMAUDIODIR_IN)
    20442105                pThis->In.cStreamsFree++;
    20452106            else /* Out */
    20462107                pThis->Out.cStreamsFree++;
     2108            pThis->cStreams--;
    20472109
    20482110            RTListNodeRemove(&pStreamEx->ListEntry);
     2111
     2112            RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
    20492113
    20502114            drvAudioStreamFree(pStreamEx);
     
    20552119            /** @todo r=bird: What's the plan now? */
    20562120        }
    2057 
    2058         RTCritSectLeave(&pThis->CritSect);
    20592121    }
    20602122    else
     
    20792141static DECLCALLBACK(void) drvAudioStreamDestroyAsync(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx)
    20802142{
    2081     LogFlow(("pThis=%p pStreamEx=%p (%s)\n", pThis, pStreamEx, pStreamEx->Core.szName));
    2082 
    2083     /** @todo r=bird: This isn't doing the trick for core audio, as the big
    2084      *        simple-minded critsect is held while the often very slow
    2085      *        AudioQueueDestroy call is made, blocking creation and manipulation
    2086      *        of new streams.  Sigh^3. */
    2087 
    2088     /** @todo can we somehow drain it instead? */
     2143    LogFlowFunc(("pThis=%p pStreamEx=%p (%s)\n", pThis, pStreamEx, pStreamEx->Core.szName));
     2144#ifdef LOG_ENABLED
     2145    uint64_t const nsStart = RTTimeNanoTS();
     2146#endif
     2147
     2148    RTCritSectEnter(&pStreamEx->Core.CritSect);
     2149
     2150    /** @todo can we somehow drain it instead?
     2151     * Would need to know if the destroying is happening at runtime or when powering
     2152     * off the VM, as we don't care for draining the latter case. */
    20892153    int rc2 = drvAudioStreamControlInternal(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    2090     LogFlow(("DISABLE done: %Rrc\n", rc2));
     2154    LogFlowFunc(("DISABLE done: %Rrc\n", rc2));
    20912155    AssertRC(rc2);
    20922156
     2157    RTCritSectLeave(&pStreamEx->Core.CritSect);
     2158
    20932159    drvAudioStreamReleaseInternal(pThis, pStreamEx, true /*fMayDestroy*/);
    2094     LogFlow(("returning\n"));
     2160
     2161    LogFlowFunc(("returning (after %'RU64 ns)\n", RTTimeNanoTS() - nsStart));
    20952162}
    20962163
     
    21202187     * pfnStreamInitAsync call.
    21212188     */
    2122     int rc = RTCritSectEnter(&pThis->CritSect);
     2189    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    21232190    AssertRCReturn(rc, rc);
    21242191
     
    21542221                pStreamEx->hReqInitAsync = NIL_RTREQ;
    21552222            }
     2223
     2224            RTCritSectLeave(&pStreamEx->Core.CritSect);
    21562225
    21572226            /*
     
    21762245        }
    21772246        else
     2247        {
    21782248            AssertLogRelMsgFailedStmt(("%p cRefs=%#x\n", pStreamEx, pStreamEx->cRefs), rc = VERR_CALLER_NO_REFERENCE);
     2249            RTCritSectLeave(&pStreamEx->Core.CritSect); /*??*/
     2250        }
    21792251    }
    21802252    else
     2253    {
    21812254        AssertLogRelMsgFailedStmt(("%p uMagic=%#x\n", pStreamEx, pStreamEx->uMagic), rc = VERR_INVALID_MAGIC);
    2182 
    2183     RTCritSectLeave(&pThis->CritSect);
     2255        RTCritSectLeave(&pStreamEx->Core.CritSect); /*??*/
     2256    }
     2257
    21842258    LogFlowFuncLeaveRC(rc);
    21852259    return rc;
     
    21982272{
    21992273    LogFunc(("[%s]\n", pStreamEx->Core.szName));
     2274    Assert(RTCritSectIsOwner(&pStreamEx->Core.CritSect));
    22002275
    22012276    if (pStreamEx->fNoMixBufs)
     
    22352310    char szTmp[RT_MAX(PDMAUDIOSTRMCFGTOSTRING_MAX, DRVAUDIO_STATUS_STR_MAX)];
    22362311    LogFlowFunc(("[%s] status: %s\n", pStreamEx->Core.szName, drvAudioStreamStatusToStr(szTmp, pStreamEx->fStatus) ));
     2312    Assert(RTCritSectIsOwner(&pStreamEx->Core.CritSect));
     2313    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    22372314
    22382315    /*
     
    23232400    }
    23242401
     2402    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    23252403    LogFunc(("[%s] Returning %Rrc\n", pStreamEx->Core.szName, rc));
    23262404    return rc;
     
    23412419    LogFlowFunc(("\n"));
    23422420
    2343     int rc = RTCritSectEnter(&pThis->CritSect);
     2421    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    23442422    AssertRCReturn(rc, rc);
    23452423
     
    23982476    }
    23992477
    2400     RTCritSectLeave(&pThis->CritSect);
     2478    RTCritSectLeave(&pStreamEx->Core.CritSect);
    24012479
    24022480    LogFlowFuncLeaveRC(rc);
     
    24552533 * @param   enmStreamCmd    Control command.
    24562534 *
    2457  * @note    Caller has entered the critical section.
     2535 * @note    Caller has entered the critical section of the stream.
     2536 * @note    Can be called w/o having entered DRVAUDIO::CritSectHotPlug.
    24582537 */
    24592538static int drvAudioStreamControlInternalBackend(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx, PDMAUDIOSTREAMCMD enmStreamCmd)
     
    24612540    AssertPtr(pThis);
    24622541    AssertPtr(pStreamEx);
     2542    Assert(RTCritSectIsOwner(&pStreamEx->Core.CritSect));
     2543
     2544    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     2545    AssertRCReturn(rc, rc);
    24632546
    24642547    /*
     
    24752558     *         finish initializing the stream, we'll update it about the stream state.
    24762559     */
    2477     int                            rc              = VINF_SUCCESS;
    24782560    bool const                     fDirEnabled     = pStreamEx->Core.enmDir == PDMAUDIODIR_IN
    24792561                                                   ? pThis->In.fEnabled : pThis->Out.fEnabled;
     
    25232605
    25242606                default:
    2525                     AssertMsgFailedReturn(("Command %RU32 not implemented\n", enmStreamCmd), VERR_INTERNAL_ERROR_2);
     2607                    AssertMsgFailedBreakStmt(("Command %RU32 not implemented\n", enmStreamCmd), rc = VERR_INTERNAL_ERROR_2);
    25262608            }
    25272609            if (RT_SUCCESS(rc))
     
    25422624    else
    25432625        LogFlowFunc(("fDirEnabled=false\n"));
     2626
     2627    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    25442628    return rc;
    25452629}
     
    25912675    AssertPtr(pThis);
    25922676    AssertPtr(pStreamEx);
     2677    Assert(RTCritSectIsOwner(&pStreamEx->Core.CritSect));
    25932678
    25942679#ifdef LOG_ENABLED
     
    28002885    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    28012886
    2802     int rc = RTCritSectEnter(&pThis->CritSect);
     2887    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    28032888    AssertRCReturn(rc, rc);
    28042889
     
    28072892    rc = drvAudioStreamControlInternal(pThis, pStreamEx, enmStreamCmd);
    28082893
    2809     RTCritSectLeave(&pThis->CritSect);
     2894    RTCritSectLeave(&pStreamEx->Core.CritSect);
    28102895    return rc;
    28112896}
     
    29653050 * @param   cbBuf       Number of new bytes.  Can be zero.
    29663051 * @param   pcbWritten  Where to return the number of bytes written.
     3052 *
     3053 * @note    Locking: Stream critsect and hot-plug in shared mode.
    29673054 */
    29683055static int drvAudioStreamPreBufComitting(PDRVAUDIO pThis, PDRVAUDIOSTREAM pStreamEx,
     
    29843071        }
    29853072    }
     3073
     3074    AssertReturn(pThis->pHostDrvAudio, VERR_AUDIO_BACKEND_NOT_ATTACHED);
    29863075
    29873076    /*
     
    30853174    {
    30863175        AssertReturn(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, VINF_SUCCESS);
     3176        RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    30873177
    30883178        /*
     
    31313221            drvAudioStreamResetOnDisable(pStreamEx);
    31323222        }
     3223
     3224        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    31333225    }
    31343226
     
    31523244    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    31533245
    3154     int rc = RTCritSectEnter(&pThis->CritSect);
     3246    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    31553247    AssertRCReturn(rc, rc);
    31563248
    31573249    rc = drvAudioStreamIterateInternal(pThis, pStreamEx);
    31583250
    3159     RTCritSectLeave(&pThis->CritSect);
     3251    RTCritSectLeave(&pStreamEx->Core.CritSect);
    31603252
    31613253    if (RT_FAILURE(rc))
     
    31773269    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, 0);
    31783270    AssertMsg(pStreamEx->Core.enmDir == PDMAUDIODIR_IN, ("Can't read from a non-input stream\n"));
    3179     int rc = RTCritSectEnter(&pThis->CritSect);
     3271
     3272    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    31803273    AssertRCReturn(rc, 0);
     3274    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    31813275
    31823276    /*
     
    32393333    }
    32403334
    3241     RTCritSectLeave(&pThis->CritSect);
     3335    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     3336    RTCritSectLeave(&pStreamEx->Core.CritSect);
    32423337    Log3Func(("[%s] cbReadable=%#RX32 (%RU64ms)\n",
    32433338              pStreamEx->Core.szName, cbReadable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbReadable)));
     
    32583353    AssertReturn(pStreamEx->uMagic      == DRVAUDIOSTREAM_MAGIC, 0);
    32593354    AssertMsgReturn(pStreamEx->Core.enmDir == PDMAUDIODIR_OUT, ("Can't write to a non-output stream\n"), 0);
    3260     int rc = RTCritSectEnter(&pThis->CritSect);
     3355
     3356    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    32613357    AssertRCReturn(rc, 0);
     3358    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    32623359
    32633360    /*
     
    33433440    }
    33443441
    3345     RTCritSectLeave(&pThis->CritSect);
     3442    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     3443    RTCritSectLeave(&pStreamEx->Core.CritSect);
    33463444    Log3Func(("[%s] cbWritable=%#RX32 (%RU64ms) enmPlayMode=%s enmBackendState=%s\n",
    33473445              pStreamEx->Core.szName, cbWritable, PDMAudioPropsBytesToMilli(&pStreamEx->Host.Cfg.Props, cbWritable),
     
    33653463     * Get the status mask.
    33663464     */
    3367     int rc = RTCritSectEnter(&pThis->CritSect);
     3465    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    33683466    AssertRCReturn(rc, PDMAUDIOSTREAMSTATE_INVALID);
     3467    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    33693468
    33703469    PDMHOSTAUDIOSTREAMSTATE const enmBackendState = drvAudioStreamGetBackendStateAndProcessChanges(pThis, pStreamEx);
     
    33733472    Assert(enmDir == PDMAUDIODIR_IN || enmDir == PDMAUDIODIR_OUT);
    33743473
    3375     RTCritSectLeave(&pThis->CritSect);
     3474    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     3475    RTCritSectLeave(&pStreamEx->Core.CritSect);
    33763476
    33773477    /*
     
    34223522    LogFlowFunc(("[%s] volL=%RU32, volR=%RU32, fMute=%RTbool\n", pStreamEx->Core.szName, pVol->uLeft, pVol->uRight, pVol->fMuted));
    34233523
     3524    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
     3525    AssertRCReturn(rc, rc);
     3526
    34243527    AudioMixBufSetVolume(&pStreamEx->Guest.MixBuf, pVol);
    34253528    AudioMixBufSetVolume(&pStreamEx->Host.MixBuf,  pVol);
    34263529
     3530    RTCritSectLeave(&pStreamEx->Core.CritSect);
    34273531    return VINF_SUCCESS;
    34283532}
     
    34613565              ("Stream '%s' got a non-frame-aligned write (%#RX32 bytes)\n", pStreamEx->Core.szName, cbBuf));
    34623566
    3463     int rc = RTCritSectEnter(&pThis->CritSect);
     3567    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    34643568    AssertRCReturn(rc, rc);
    34653569
     
    34703574    if (PDMAudioStrmStatusIsReady(pStreamEx->fStatus))
    34713575    {
     3576        RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    34723577        if (   pThis->Out.fEnabled /* (see @bugref{9882}) */
    34733578            && pThis->pHostDrvAudio != NULL)
     
    35553660                      !pThis->Out.fEnabled ? "disabled" : !pThis->pHostDrvAudio ? "not attached" : "not ready yet"));
    35563661        }
     3662        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    35573663    }
    35583664    else
    35593665        rc = VERR_AUDIO_STREAM_NOT_READY;
    35603666
    3561     RTCritSectLeave(&pThis->CritSect);
     3667    RTCritSectLeave(&pStreamEx->Core.CritSect);
    35623668    return rc;
    35633669}
     
    35833689               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
    35843690
    3585     int rc = RTCritSectEnter(&pThis->CritSect);
     3691    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    35863692    AssertRCReturn(rc, rc);
    35873693
     
    36693775    } while (0);
    36703776
    3671     RTCritSectLeave(&pThis->CritSect);
     3777    RTCritSectLeave(&pStreamEx->Core.CritSect);
    36723778
    36733779    if (RT_SUCCESS(rc) && pcbRead)
     
    38643970              ("Stream '%s' is not an input stream and therefore cannot be captured (direction is 0x%x)\n",
    38653971               pStreamEx->Core.szName, pStreamEx->Core.enmDir));
    3866     int rc = RTCritSectEnter(&pThis->CritSect);
     3972    int rc = RTCritSectEnter(&pStreamEx->Core.CritSect);
    38673973    AssertRCReturn(rc, rc);
     3974    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    38683975
    38693976#ifdef LOG_ENABLED
     
    39194026    } while (0);
    39204027
    3921     RTCritSectLeave(&pThis->CritSect);
     4028    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     4029    RTCritSectLeave(&pStreamEx->Core.CritSect);
    39224030
    39234031    if (pcFramesCaptured)
     
    39454053    AssertPtrReturnVoid(pStreamEx);
    39464054    AssertReturnVoid(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC);
     4055
     4056    /*
     4057     * The CritSectHotPlug lock should not be needed here as detach will destroy
     4058     * the thread pool.  So, we'll leave taking the stream lock to the worker we're
     4059     * calling as there are no lock order concerns.
     4060     */
    39474061    PPDMIHOSTAUDIO const pIHostDrvAudio = pThis->pHostDrvAudio;
    39484062    AssertPtrReturnVoid(pIHostDrvAudio);
    39494063    AssertPtrReturnVoid(pIHostDrvAudio->pfnDoOnWorkerThread);
    3950 
    39514064    pIHostDrvAudio->pfnDoOnWorkerThread(pIHostDrvAudio, pStreamEx->pBackend, uUser, pvUser);
    39524065
     
    39674080    LogFlowFunc(("pThis=%p uUser=%#zx pvUser=%p\n", pThis, uUser, pvUser));
    39684081    AssertPtrReturnVoid(pThis);
     4082
     4083    /*
     4084     * The CritSectHotPlug lock should not be needed here as detach will destroy
     4085     * the thread pool.
     4086     */
    39694087    PPDMIHOSTAUDIO const pIHostDrvAudio = pThis->pHostDrvAudio;
    39704088    AssertPtrReturnVoid(pIHostDrvAudio);
     
    39874105
    39884106    /*
    3989      * Assert some sanity and do the work.
    3990      */
    3991     AssertReturn(pThis->pHostDrvAudio, VERR_INTERNAL_ERROR_3);
    3992     AssertReturn(pThis->pHostDrvAudio->pfnDoOnWorkerThread, VERR_INVALID_FUNCTION);
    3993     AssertReturn(pThis->hReqPool != NIL_RTREQPOOL, VERR_INVALID_FUNCTION);
    3994     int rc;
     4107     * Assert some sanity.
     4108     */
     4109    PDRVAUDIOSTREAM pStreamEx;
    39954110    if (!pStream)
    3996     {
    3997         rc = RTReqPoolCallEx(pThis->hReqPool, 0 /*cMillies*/, NULL /*phReq*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
    3998                              (PFNRT)drvAudioHostPort_DoOnWorkerThreadWorker, 3, pThis, uUser, pvUser);
    3999         AssertRC(rc);
    4000     }
     4111        pStreamEx = NULL;
    40014112    else
    40024113    {
    40034114        AssertPtrReturn(pStream, VERR_INVALID_POINTER);
    40044115        AssertReturn(pStream->uMagic == PDMAUDIOBACKENDSTREAM_MAGIC, VERR_INVALID_MAGIC);
    4005         PDRVAUDIOSTREAM pStreamEx = (PDRVAUDIOSTREAM)pStream->pStream;
     4116        pStreamEx = (PDRVAUDIOSTREAM)pStream->pStream;
    40064117        AssertPtrReturn(pStreamEx, VERR_INVALID_POINTER);
    40074118        AssertReturn(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    40084119        AssertReturn(pStreamEx->Core.uMagic == PDMAUDIOSTREAM_MAGIC, VERR_INVALID_MAGIC);
    4009 
    4010         uint32_t cRefs = drvAudioStreamRetainInternal(pStreamEx);
    4011         if (cRefs != UINT32_MAX)
    4012         {
    4013             rc = RTReqPoolCallEx(pThis->hReqPool, 0 /*cMillies*/, NULL, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
    4014                                  (PFNRT)drvAudioHostPort_DoOnWorkerThreadStreamWorker,
    4015                                  4, pThis, pStreamEx, uUser, pvUser);
    4016             AssertRC(rc);
    4017             if (RT_FAILURE(rc))
    4018                 drvAudioStreamReleaseInternal(pThis, pStreamEx, true /*fMayDestroy*/);
     4120    }
     4121
     4122    int rc = RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     4123    AssertRCReturn(rc, rc);
     4124
     4125    AssertPtr(pThis->hReqPool != NIL_RTREQPOOL);
     4126    AssertPtr(pThis->pHostDrvAudio);
     4127    if (   pThis->hReqPool != NIL_RTREQPOOL
     4128        && pThis->pHostDrvAudio != NULL)
     4129    {
     4130        Assert(pThis->pHostDrvAudio->pfnDoOnWorkerThread);
     4131        if (pThis->pHostDrvAudio->pfnDoOnWorkerThread)
     4132        {
     4133            /*
     4134             * Try do the work.
     4135             */
     4136            if (!pStreamEx)
     4137            {
     4138                rc = RTReqPoolCallEx(pThis->hReqPool, 0 /*cMillies*/, NULL /*phReq*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     4139                                     (PFNRT)drvAudioHostPort_DoOnWorkerThreadWorker, 3, pThis, uUser, pvUser);
     4140                AssertRC(rc);
     4141            }
     4142            else
     4143            {
     4144
     4145                uint32_t cRefs = drvAudioStreamRetainInternal(pStreamEx);
     4146                if (cRefs != UINT32_MAX)
     4147                {
     4148                    rc = RTReqPoolCallEx(pThis->hReqPool, 0 /*cMillies*/, NULL, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
     4149                                         (PFNRT)drvAudioHostPort_DoOnWorkerThreadStreamWorker,
     4150                                         4, pThis, pStreamEx, uUser, pvUser);
     4151                    AssertRC(rc);
     4152                    if (RT_FAILURE(rc))
     4153                    {
     4154                        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     4155                        drvAudioStreamReleaseInternal(pThis, pStreamEx, true /*fMayDestroy*/);
     4156                        RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     4157                    }
     4158                }
     4159                else
     4160                    rc = VERR_INVALID_PARAMETER;
     4161            }
    40194162        }
    40204163        else
    4021             rc = VERR_INVALID_PARAMETER;
    4022     }
     4164            rc = VERR_INVALID_FUNCTION;
     4165    }
     4166    else
     4167        rc = VERR_INVALID_STATE;
     4168
     4169    RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    40234170    LogFlowFunc(("returns %Rrc\n", rc));
    40244171    return rc;
     
    40324179{
    40334180    LogFlow((LOG_FN_FMT ": Flagging %s for re-init.\n", pszCaller, pStreamEx->Core.szName)); RT_NOREF(pszCaller);
     4181    Assert(RTCritSectIsOwner(&pStreamEx->Core.CritSect));
     4182
    40344183    pStreamEx->fStatus      |= PDMAUDIOSTREAM_STS_NEED_REINIT;
    40354184    PDMAUDIOSTREAM_STS_ASSERT_VALID(pStreamEx->fStatus);
     
    40484197    LogRel(("Audio: The %s device for %s is changing.\n", enmDir == PDMAUDIODIR_IN ? "input" : "output", pThis->BackendCfg.szName));
    40494198
    4050     RTCritSectEnter(&pThis->CritSect);
     4199    /*
     4200     * Grab the list lock in shared mode and do the work.
     4201     */
     4202    int rc = RTCritSectRwEnterShared(&pThis->CritSectGlobals);
     4203    AssertRCReturnVoid(rc);
     4204
    40514205    PDRVAUDIOSTREAM pStreamEx;
    40524206    RTListForEach(&pThis->LstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
     
    40544208        if (pStreamEx->Core.enmDir == enmDir)
    40554209        {
     4210            RTCritSectEnter(&pStreamEx->Core.CritSect);
     4211            RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
     4212
    40564213            if (pThis->pHostDrvAudio->pfnStreamNotifyDeviceChanged)
    40574214            {
     
    40644221            else
    40654222                drvAudioStreamMarkNeedReInit(pStreamEx, __PRETTY_FUNCTION__);
     4223
     4224            RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     4225            RTCritSectLeave(&pStreamEx->Core.CritSect);
    40664226        }
    40674227    }
    4068     RTCritSectLeave(&pThis->CritSect);
     4228
     4229    RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
    40694230}
    40704231
     
    40764237                                                                             PPDMAUDIOBACKENDSTREAM pStream)
    40774238{
    4078     PDRVAUDIO pThis = RT_FROM_MEMBER(pInterface, DRVAUDIO, IHostAudioPort);
     4239    RT_NOREF(pInterface);
    40794240
    40804241    /*
     
    40924253     * Grab the lock and do switch the state (only needed for output streams for now).
    40934254     */
    4094     RTCritSectEnter(&pThis->CritSect);
    4095     AssertReturnVoidStmt(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, RTCritSectLeave(&pThis->CritSect)); /* paranoia */
     4255    RTCritSectEnter(&pStreamEx->Core.CritSect);
     4256    AssertReturnVoidStmt(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, RTCritSectLeave(&pStreamEx->Core.CritSect)); /* paranoia */
    40964257
    40974258    if (pStreamEx->Core.enmDir == PDMAUDIODIR_OUT)
     
    41274288        LogFunc(("input stream, nothing to do.\n"));
    41284289
    4129     RTCritSectLeave(&pThis->CritSect);
     4290    RTCritSectLeave(&pStreamEx->Core.CritSect);
    41304291}
    41314292
     
    41524313     * Grab the lock and do the requested work.
    41534314     */
    4154     RTCritSectEnter(&pThis->CritSect);
    4155     AssertReturnVoidStmt(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, RTCritSectLeave(&pThis->CritSect)); /* paranoia */
     4315    RTCritSectEnter(&pStreamEx->Core.CritSect);
     4316    AssertReturnVoidStmt(pStreamEx->uMagic == DRVAUDIOSTREAM_MAGIC, RTCritSectLeave(&pStreamEx->Core.CritSect)); /* paranoia */
    41564317
    41574318    if (fReInit)
     
    41874348    }
    41884349
    4189     RTCritSectLeave(&pThis->CritSect);
     4350    RTCritSectLeave(&pStreamEx->Core.CritSect);
    41904351}
    41914352
     
    42054366
    42064367    /* Try push the work over to the thread-pool if we've got one. */
     4368    RTCritSectRwEnterShared(&pThis->CritSectHotPlug);
    42074369    if (pThis->hReqPool != NIL_RTREQPOOL)
    42084370    {
     
    42114373                                 3, pThis, true /*fLog*/, (PPDMAUDIOHOSTENUM)NULL /*pDevEnum*/);
    42124374        LogFunc(("RTReqPoolCallEx: %Rrc\n", rc));
     4375        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
    42134376        if (RT_SUCCESS(rc))
    42144377            return;
    42154378    }
     4379    else
     4380        RTCritSectRwLeaveShared(&pThis->CritSectHotPlug);
     4381
    42164382    LogFunc(("Calling drvAudioDevicesEnumerateInternal...\n"));
    42174383    drvAudioDevicesEnumerateInternal(pThis, true /* fLog */, NULL /* pDevEnum */);
     
    42294395
    42304396#ifdef RT_OS_DARWIN /** @todo Remove legacy behaviour: */
    4231 /** @todo r=bird: Locking?   */
    42324397    /* Mark all host streams to re-initialize. */
     4398    int rc2 = RTCritSectRwEnterShared(&pThis->CritSectGlobals);
     4399    AssertRCReturnVoid(rc2);
    42334400    PDRVAUDIOSTREAM pStreamEx;
    42344401    RTListForEach(&pThis->LstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
    42354402    {
     4403        RTCritSectEnter(&pStreamEx->Core.CritSect);
    42364404        drvAudioStreamMarkNeedReInit(pStreamEx, __PRETTY_FUNCTION__);
    4237     }
     4405        RTCritSectLeave(&pStreamEx->Core.CritSect);
     4406    }
     4407    RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
    42384408#endif
    42394409
     
    42954465         * in drvAudioDestruct().
    42964466         */
     4467        int rc = RTCritSectRwEnterShared(&pThis->CritSectGlobals);
     4468        AssertRCReturnVoid(rc);
     4469
    42974470        PDRVAUDIOSTREAM pStreamEx;
    42984471        RTListForEach(&pThis->LstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
    42994472        {
     4473            RTCritSectEnter(&pStreamEx->Core.CritSect);
    43004474            drvAudioStreamControlInternalBackend(pThis, pStreamEx, PDMAUDIOSTREAMCMD_DISABLE);
    4301 #if 0 /* This leads to double destruction. Also in the backend when we don't set pHostDrvAudio to NULL below. */
    4302             drvAudioStreamDestroyInternalBackend(pThis, pStreamEx);
    4303 #endif
     4475            RTCritSectLeave(&pStreamEx->Core.CritSect);
    43044476        }
    43054477
    4306 #if 0 /* Messes up using drvAudioHostPort_DoOnWorkerThread from the backend drivers' power off callback.  */
    4307         pThis->pHostDrvAudio = NULL;
    4308 #endif
     4478        RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
    43094479    }
    43104480
     
    43254495    RT_NOREF(fFlags);
    43264496
    4327     int rc = RTCritSectEnter(&pThis->CritSect);
    4328     AssertRC(rc);
     4497    int rc = RTCritSectRwEnterExcl(&pThis->CritSectHotPlug);
     4498    AssertLogRelRCReturnVoid(rc);
    43294499
    43304500    LogFunc(("%s (detached %p, hReqPool=%p)\n", pThis->BackendCfg.szName, pThis->pHostDrvAudio, pThis->hReqPool));
     
    43394509        RTREQPOOL hReqPool = pThis->hReqPool;
    43404510        pThis->hReqPool = NIL_RTREQPOOL;
    4341         RTCritSectLeave(&pThis->CritSect);
     4511
     4512        RTCritSectRwLeaveExcl(&pThis->CritSectHotPlug);
    43424513
    43434514        RTReqPoolRelease(hReqPool);
    43444515
    4345         RTCritSectEnter(&pThis->CritSect);
     4516        RTCritSectRwEnterExcl(&pThis->CritSectHotPlug);
    43464517    }
    43474518
     
    43514522    pThis->pHostDrvAudio = NULL;
    43524523
    4353     RTCritSectLeave(&pThis->CritSect);
     4524    RTCritSectRwLeaveExcl(&pThis->CritSectHotPlug);
    43544525}
    43554526
     
    43904561    /*
    43914562     * Get the backend configuration.
     4563     *
     4564     * Note! Limit the number of streams to max 128 in each direction to
     4565     *       prevent wasting resources.
    43924566     * Note! Take care not to wipe the DriverName config value on failure.
    43934567     */
     
    44004574            LogFunc(("BackendCfg.szName: '%s' -> '%s'\n", pThis->BackendCfg.szName, BackendCfg.szName));
    44014575        pThis->BackendCfg       = BackendCfg;
    4402         pThis->In.cStreamsFree  = BackendCfg.cMaxStreamsIn;
    4403         pThis->Out.cStreamsFree = BackendCfg.cMaxStreamsOut;
     4576        pThis->In.cStreamsFree  = RT_MIN(BackendCfg.cMaxStreamsIn,  128);
     4577        pThis->Out.cStreamsFree = RT_MIN(BackendCfg.cMaxStreamsOut, 128);
    44044578
    44054579        LogFlowFunc(("cStreamsFreeIn=%RU8, cStreamsFreeOut=%RU8\n", pThis->In.cStreamsFree, pThis->Out.cStreamsFree));
     
    45504724    LogFunc(("%s\n", pThis->BackendCfg.szName));
    45514725
    4552     int rc = RTCritSectEnter(&pThis->CritSect);
     4726    int rc = RTCritSectRwEnterExcl(&pThis->CritSectHotPlug);
    45534727    AssertRCReturn(rc, rc);
    45544728
    45554729    rc = drvAudioDoAttachInternal(pDrvIns, pThis, fFlags);
    45564730
    4557     RTCritSectLeave(&pThis->CritSect);
     4731    RTCritSectRwLeaveExcl(&pThis->CritSectHotPlug);
    45584732    return rc;
    45594733}
     
    45724746    LogFlowFunc(("enmCmd=%s\n", PDMAudioStrmCmdGetName(enmCmd)));
    45734747
    4574     int rc2 = RTCritSectEnter(&pThis->CritSect);
     4748    int rc2 = RTCritSectRwEnterShared(&pThis->CritSectGlobals);
    45754749    AssertRCReturnVoid(rc2);
    45764750
    4577     if (pThis->pHostDrvAudio)
    4578     {
    4579         PDRVAUDIOSTREAM pStreamEx;
    4580         RTListForEach(&pThis->LstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
    4581         {
    4582             drvAudioStreamControlInternal(pThis, pStreamEx, enmCmd);
    4583         }
    4584     }
    4585 
    4586     rc2 = RTCritSectLeave(&pThis->CritSect);
    4587     AssertRC(rc2);
     4751    PDRVAUDIOSTREAM pStreamEx;
     4752    RTListForEach(&pThis->LstStreams, pStreamEx, DRVAUDIOSTREAM, ListEntry)
     4753    {
     4754        RTCritSectEnter(&pStreamEx->Core.CritSect);
     4755        drvAudioStreamControlInternal(pThis, pStreamEx, enmCmd);
     4756        RTCritSectLeave(&pStreamEx->Core.CritSect);
     4757    }
     4758
     4759    RTCritSectRwLeaveShared(&pThis->CritSectGlobals);
    45884760}
    45894761
     
    46224794
    46234795    LogFlowFuncEnter();
    4624 
    4625     if (RTCritSectIsInitialized(&pThis->CritSect))
    4626     {
    4627         int rc = RTCritSectEnter(&pThis->CritSect);
    4628         AssertRC(rc);
    4629     }
    46304796
    46314797    /*
     
    46384804    /* Thus, NULL the pointer to the host audio driver first,
    46394805     * so that routines like drvAudioStreamDestroyInternal() don't call the driver(s) below us anymore. */
    4640     pThis->pHostDrvAudio = NULL;
    4641 
    4642     PDRVAUDIOSTREAM pStreamEx, pStreamExNext;
    4643     RTListForEachSafe(&pThis->LstStreams, pStreamEx, pStreamExNext, DRVAUDIOSTREAM, ListEntry)
    4644     {
    4645         int rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
    4646         if (RT_SUCCESS(rc))
    4647         {
    4648             RTListNodeRemove(&pStreamEx->ListEntry);
    4649             drvAudioStreamFree(pStreamEx);
     4806    if (RTCritSectRwIsInitialized(&pThis->CritSectHotPlug))
     4807    {
     4808        RTCritSectRwEnterExcl(&pThis->CritSectHotPlug);
     4809        pThis->pHostDrvAudio = NULL;
     4810        RTCritSectRwLeaveExcl(&pThis->CritSectHotPlug);
     4811    }
     4812    else
     4813    {
     4814        Assert(pThis->pHostDrvAudio == NULL);
     4815        pThis->pHostDrvAudio = NULL;
     4816    }
     4817
     4818    if (RTCritSectRwIsInitialized(&pThis->CritSectGlobals))
     4819    {
     4820        RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
     4821
     4822        PDRVAUDIOSTREAM pStreamEx, pStreamExNext;
     4823        RTListForEachSafe(&pThis->LstStreams, pStreamEx, pStreamExNext, DRVAUDIOSTREAM, ListEntry)
     4824        {
     4825            int rc = drvAudioStreamUninitInternal(pThis, pStreamEx);
     4826            if (RT_SUCCESS(rc))
     4827            {
     4828                RTListNodeRemove(&pStreamEx->ListEntry);
     4829                drvAudioStreamFree(pStreamEx);
     4830            }
    46504831        }
    4651     }
     4832
     4833        RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
     4834        RTCritSectRwDelete(&pThis->CritSectGlobals);
     4835    }
     4836
    46524837
    46534838    /* Sanity. */
    46544839    Assert(RTListIsEmpty(&pThis->LstStreams));
    46554840
    4656     if (RTCritSectIsInitialized(&pThis->CritSect))
    4657     {
    4658         int rc = RTCritSectLeave(&pThis->CritSect);
    4659         AssertRC(rc);
    4660 
    4661         rc = RTCritSectDelete(&pThis->CritSect);
    4662         AssertRC(rc);
    4663     }
     4841    if (RTCritSectRwIsInitialized(&pThis->CritSectHotPlug))
     4842        RTCritSectRwDelete(&pThis->CritSectHotPlug);
    46644843
    46654844#ifdef VBOX_WITH_STATISTICS
     
    48525031     * Init the rest of the driver instance data.
    48535032     */
    4854     rc = RTCritSectInit(&pThis->CritSect);
     5033    rc = RTCritSectRwInit(&pThis->CritSectHotPlug);
    48555034    AssertRCReturn(rc, rc);
     5035    rc = RTCritSectRwInit(&pThis->CritSectGlobals);
     5036    AssertRCReturn(rc, rc);
     5037#ifdef VBOX_STRICT
     5038    /* Define locking order: */
     5039    RTCritSectRwEnterExcl(&pThis->CritSectGlobals);
     5040    RTCritSectRwEnterExcl(&pThis->CritSectHotPlug);
     5041    RTCritSectRwLeaveExcl(&pThis->CritSectHotPlug);
     5042    RTCritSectRwLeaveExcl(&pThis->CritSectGlobals);
     5043#endif
    48565044
    48575045    pThis->pDrvIns                              = pDrvIns;
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