Index: /trunk/include/VBox/vmm/pdmaudioifs.h
===================================================================
--- /trunk/include/VBox/vmm/pdmaudioifs.h	(revision 59419)
+++ /trunk/include/VBox/vmm/pdmaudioifs.h	(revision 59420)
@@ -28,4 +28,5 @@
 
 #include <VBox/types.h>
+#include <iprt/critsect.h>
 #include <iprt/list.h>
 
@@ -339,4 +340,6 @@
     /** Stream status flag. */
     PDMAUDIOSTRMSTS        fStatus;
+    /** Critical section for serializing access. */
+    RTCRITSECT             CritSect;
     /** This stream's mixing buffer. */
     PDMAUDIOMIXBUF         MixBuf;
@@ -360,4 +363,6 @@
     /** Stream status flag. */
     PDMAUDIOSTRMSTS        fStatus;
+    /** Critical section for serializing access. */
+    RTCRITSECT             CritSect;
     /** This stream's mixing buffer. */
     PDMAUDIOMIXBUF         MixBuf;
Index: /trunk/src/VBox/Devices/Audio/DrvAudio.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 59419)
+++ /trunk/src/VBox/Devices/Audio/DrvAudio.cpp	(revision 59420)
@@ -3,6 +3,6 @@
  * Intermediate audio driver header.
  *
- * @remarks Intermediate audio driver having audio device as one of the sink and
- *          host backend as other.
+ * @remarks Intermediate audio driver for connecting the audio device emulation
+ *          with the host backend.
  */
 
@@ -388,5 +388,7 @@
     AssertPtrReturn(pHstStrmIn, VERR_INVALID_POINTER);
 
-    int rc;
+    int rc = RTCritSectEnter(&pHstStrmIn->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
 
     switch (enmStreamCmd)
@@ -475,4 +477,8 @@
     }
 
+    int rc2 = RTCritSectLeave(&pHstStrmIn->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     return rc;
 }
@@ -483,5 +489,7 @@
     AssertPtrReturn(pHstStrmOut, VERR_INVALID_POINTER);
 
-    int rc;
+    int rc = RTCritSectEnter(&pHstStrmOut->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
 
     switch (enmStreamCmd)
@@ -575,4 +583,8 @@
     }
 
+    int rc2 = RTCritSectLeave(&pHstStrmOut->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     return rc;
 }
@@ -595,4 +607,10 @@
             /* Remove from driver instance list. */
             RTListNodeRemove(&pHstStrmOut->Node);
+
+            if (RTCritSectIsInitialized(&pHstStrmOut->CritSect))
+            {
+                int rc2 = RTCritSectDelete(&pHstStrmOut->CritSect);
+                AssertRC(rc2);
+            }
 
             RTMemFree(pHstStrmOut);
@@ -777,4 +795,7 @@
 
         rc = AudioMixBufInit(&pHstStrmOut->MixBuf, pszTemp, &pHstStrmOut->Props, cSamples);
+        if (RT_SUCCESS(rc))
+            rc = RTCritSectInit(&pHstStrmOut->CritSect);
+
         if (RT_SUCCESS(rc))
         {
@@ -1030,4 +1051,7 @@
 
         rc = AudioMixBufInit(&pHstStrmIn->MixBuf, pszTemp, &pHstStrmIn->Props, cSamples);
+        if (RT_SUCCESS(rc))
+            rc = RTCritSectInit(&pHstStrmIn->CritSect);
+
         if (RT_SUCCESS(rc))
         {
@@ -1079,10 +1103,19 @@
 
     AssertPtrReturn(pGstStrmOut, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
-    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvBuf,       VERR_INVALID_POINTER);
+    AssertReturn(cbBuf,          VERR_INVALID_PARAMETER);
     /* pcbWritten is optional. */
 
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
+
     if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_OUT))
+    {
+        rc = RTCritSectLeave(&pThis->CritSect);
+        AssertRC(rc);
+
         return VERR_NOT_AVAILABLE;
+    }
 
     PPDMAUDIOHSTSTRMOUT pHstStrmOut = pGstStrmOut->pHstStrmOut;
@@ -1097,5 +1130,6 @@
         if (pcbWritten)
             *pcbWritten = 0;
-        return VINF_SUCCESS;
+
+        return RTCritSectLeave(&pThis->CritSect);
     }
 
@@ -1105,5 +1139,5 @@
      */
     uint32_t cWritten;
-    int rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten);
+    rc = AudioMixBufWriteAt(&pGstStrmOut->MixBuf, 0 /* Offset in samples */, pvBuf, cbBuf, &cWritten);
 
     /*
@@ -1134,4 +1168,9 @@
                  pGstStrmOut->MixBuf.pszName, pHstStrmOut->MixBuf.pszName, pvBuf, cbBuf, cWritten,
                  AUDIOMIXBUF_S2B(&pGstStrmOut->MixBuf, cWritten), cMixed, rc));
+
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     return rc;
 }
@@ -1187,4 +1226,10 @@
         {
             drvAudioHstInFreeRes(pHstStrmIn);
+
+            if (RTCritSectIsInitialized(&pHstStrmIn->CritSect))
+            {
+                int rc2 = RTCritSectDelete(&pHstStrmIn->CritSect);
+                AssertRC(rc2);
+            }
 
             /* Remove from driver instance list. */
@@ -1245,11 +1290,13 @@
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
 
-    int rc = VINF_SUCCESS;
-    uint32_t cSamplesLive = 0;
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
 
     /*
      * Playback.
      */
-    uint32_t cbFreeOut = UINT32_MAX;
+    uint32_t cSamplesLive = 0;
+    uint32_t cbFreeOut    = UINT32_MAX;
 
     PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
@@ -1348,4 +1395,8 @@
     }
 
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     return rc;
 }
@@ -1358,11 +1409,13 @@
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
 
-    int rc = VINF_SUCCESS;
-    uint32_t cSamplesPlayedMax = 0;
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
 
     /*
      * Process all enabled host output streams.
      */
-    PPDMAUDIOHSTSTRMOUT pHstStrmOut = NULL;
+    uint32_t            cSamplesPlayedMax = 0;
+    PPDMAUDIOHSTSTRMOUT pHstStrmOut       = NULL;
     while ((pHstStrmOut = drvAudioHstFindAnyEnabledOut(pThis, pHstStrmOut)))
     {
@@ -1437,4 +1490,8 @@
     }
 
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     return rc;
 }
@@ -1484,5 +1541,8 @@
 
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
-    int          rc = VINF_SUCCESS;
+
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
 
     for (size_t i = 0; i < cCallbacks; i++)
@@ -1512,4 +1572,8 @@
 
     /** @todo Undo allocations on error. */
+
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
 
     return rc;
@@ -1696,9 +1760,10 @@
 #endif
 
-    int rc = VINF_SUCCESS;
+    int rc = RTCritSectInit(&pThis->CritSect);
 
     /* Get the configuration data from the selected backend (if available). */
     AssertPtr(pThis->pHostDrvAudio);
-    if (RT_LIKELY(pThis->pHostDrvAudio->pfnGetConf))
+    if (   RT_SUCCESS(rc)
+        && RT_LIKELY(pThis->pHostDrvAudio->pfnGetConf))
         rc = pThis->pHostDrvAudio->pfnGetConf(pThis->pHostDrvAudio, &pThis->BackendCfg);
 
@@ -1735,7 +1800,11 @@
 
     AssertPtrReturn(pGstStrmIn, VERR_INVALID_POINTER);
-    AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
-    AssertReturn(cbBuf, VERR_INVALID_PARAMETER);
+    AssertPtrReturn(pvBuf,      VERR_INVALID_POINTER);
+    AssertReturn(cbBuf,         VERR_INVALID_PARAMETER);
     /* pcbWritten is optional. */
+
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
 
     if (!pThis->pHostDrvAudio->pfnIsEnabled(pThis->pHostDrvAudio, PDMAUDIODIR_IN))
@@ -1743,5 +1812,6 @@
         if (pcbRead)
             *pcbRead = 0;
-        return VINF_SUCCESS;
+
+        return RTCritSectLeave(&pThis->CritSect);
     }
 
@@ -1757,6 +1827,5 @@
      */
     uint32_t cRead;
-    int rc = AudioMixBufReadCirc(&pGstStrmIn->MixBuf,
-                                 pvBuf, cbBuf, &cRead);
+    rc = AudioMixBufReadCirc(&pGstStrmIn->MixBuf, pvBuf, cbBuf, &cRead);
     if (RT_SUCCESS(rc))
     {
@@ -1769,4 +1838,9 @@
     LogFlowFunc(("cRead=%RU32 (%RU32 bytes), rc=%Rrc\n",
                  cRead, AUDIOMIXBUF_S2B(&pGstStrmIn->MixBuf, cRead), rc));
+
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     return rc;
 }
@@ -1887,12 +1961,16 @@
                                           PPDMAUDIOGSTSTRMIN *ppGstStrmIn)
 {
-    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
+    AssertPtrReturn(pInterface,  VERR_INVALID_POINTER);
     AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
+    AssertPtrReturn(pszName,     VERR_INVALID_POINTER);
+    AssertPtrReturn(pCfg,        VERR_INVALID_POINTER);
     AssertPtrReturn(ppGstStrmIn, VERR_INVALID_POINTER);
 
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
 
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
+
     LogFlowFunc(("pszName=%s, pCfg=%p\n", pszName, pCfg));
 
@@ -1900,14 +1978,23 @@
     {
         LogFunc(("Input stream configuration is not valid, bailing out\n"));
-        return VERR_INVALID_PARAMETER;
+        rc = VERR_INVALID_PARAMETER;
     }
 
     PPDMAUDIOGSTSTRMIN pGstStrmIn = *ppGstStrmIn;
-    if (   pGstStrmIn
+    if (   RT_SUCCESS(rc)
+        && pGstStrmIn
         && drvAudioPCMPropsAreEqual(&pGstStrmIn->Props, pCfg))
     {
         LogFunc(("[%s] Exists and matches required configuration, skipping creation\n",
                  pGstStrmIn->MixBuf.pszName));
-        return VWRN_ALREADY_EXISTS;
+        rc = VWRN_ALREADY_EXISTS;
+    }
+
+    if (rc != VINF_SUCCESS) /* Note: Can be VWRN_ALREADY_EXISTS, so don't use VINF_SUCCESS here. */
+    {
+        int rc2 = RTCritSectLeave(&pThis->CritSect);
+        AssertRC(rc2);
+
+        return rc;
     }
 
@@ -1919,6 +2006,4 @@
     }
 
-    int rc;
-
     if (pGstStrmIn)
     {
@@ -1932,4 +2017,8 @@
         {
             RTMemFree(pGstStrmIn);
+
+            int rc2 = RTCritSectLeave(&pThis->CritSect);
+            AssertRC(rc2);
+
             return VERR_NO_MEMORY;
         }
@@ -1945,4 +2034,8 @@
         *ppGstStrmIn = pGstStrmIn;
 
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -1952,11 +2045,15 @@
                                            PPDMAUDIOSTREAMCFG pCfg, PPDMAUDIOGSTSTRMOUT *ppGstStrmOut)
 {
-    AssertPtrReturn(pInterface, VERR_INVALID_POINTER);
-    AssertPtrReturn(pszName, VERR_INVALID_POINTER);
-    AssertPtrReturn(pCfg, VERR_INVALID_POINTER);
+    AssertPtrReturn(pInterface,   VERR_INVALID_POINTER);
+    AssertPtrReturn(pszName,      VERR_INVALID_POINTER);
+    AssertPtrReturn(pCfg,         VERR_INVALID_POINTER);
     AssertPtrReturn(ppGstStrmOut, VERR_INVALID_POINTER);
 
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
 
+    int rc = RTCritSectEnter(&pThis->CritSect);
+    if (RT_FAILURE(rc))
+        return rc;
+
     LogFlowFunc(("pszName=%s, pCfg=%p\n", pszName, pCfg));
 
@@ -1964,14 +2061,24 @@
     {
         LogFunc(("Output stream configuration is not valid, bailing out\n"));
-        return VERR_INVALID_PARAMETER;
+        rc = VERR_INVALID_PARAMETER;
     }
 
     PPDMAUDIOGSTSTRMOUT pGstStrmOut = *ppGstStrmOut;
-    if (   pGstStrmOut
+    if (   RT_SUCCESS(rc)
+        && pGstStrmOut
         && drvAudioPCMPropsAreEqual(&pGstStrmOut->Props, pCfg))
     {
         LogFunc(("[%s] Exists and matches required configuration, skipping creation\n",
                  pGstStrmOut->MixBuf.pszName));
-        return VWRN_ALREADY_EXISTS;
+
+        rc = VWRN_ALREADY_EXISTS;
+    }
+
+    if (rc != VINF_SUCCESS) /* Note: Can be VWRN_ALREADY_EXISTS, so don't use VINF_SUCCESS here. */
+    {
+        int rc2 = RTCritSectLeave(&pThis->CritSect);
+        AssertRC(rc2);
+
+        return rc;
     }
 
@@ -2003,5 +2110,4 @@
     }
 
-    int rc;
     if (pGstStrmOut)
     {
@@ -2040,4 +2146,8 @@
     }
 
+    int rc2 = RTCritSectLeave(&pThis->CritSect);
+    if (RT_SUCCESS(rc))
+        rc = rc2;
+
     LogFlowFuncLeaveRC(rc);
     return rc;
@@ -2046,24 +2156,70 @@
 static DECLCALLBACK(bool) drvAudioIsActiveIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn)
 {
-    return pGstStrmIn ? pGstStrmIn->State.fActive : false;
+    AssertPtrReturn(pInterface, false);
+    /* pGstStrmIn is optional. */
+
+    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
+
+    int rc2 = RTCritSectEnter(&pThis->CritSect);
+    AssertRC(rc2);
+
+    bool fRet = pGstStrmIn ? pGstStrmIn->State.fActive : false;
+
+    rc2 = RTCritSectLeave(&pThis->CritSect);
+    AssertRC(rc2);
+
+    return fRet;
 }
 
 static DECLCALLBACK(bool) drvAudioIsActiveOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
 {
-    return pGstStrmOut ? pGstStrmOut->State.fActive : false;
+    AssertPtrReturn(pInterface,  false);
+    /* pGstStrmOut is optional. */
+
+    PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
+
+    int rc2 = RTCritSectEnter(&pThis->CritSect);
+    AssertRC(rc2);
+
+    bool fRet = pGstStrmOut ? pGstStrmOut->State.fActive : false;
+
+    rc2 = RTCritSectLeave(&pThis->CritSect);
+    AssertRC(rc2);
+
+    return fRet;
 }
 
 static DECLCALLBACK(void) drvAudioDestroyIn(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMIN pGstStrmIn)
 {
+    AssertPtrReturnVoid(pInterface);
+    /* pGstStrmIn is optional. */
+
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
+
+    int rc2 = RTCritSectEnter(&pThis->CritSect);
+    AssertRC(rc2);
+
     if (pGstStrmIn)
         drvAudioDestroyGstIn(pThis, pGstStrmIn);
+
+    rc2 = RTCritSectLeave(&pThis->CritSect);
+    AssertRC(rc2);
 }
 
 static DECLCALLBACK(void) drvAudioDestroyOut(PPDMIAUDIOCONNECTOR pInterface, PPDMAUDIOGSTSTRMOUT pGstStrmOut)
 {
+    AssertPtrReturnVoid(pInterface);
+    /* pGstStrmOut is optional. */
+
     PDRVAUDIO pThis = PDMIAUDIOCONNECTOR_2_DRVAUDIO(pInterface);
+
+    int rc2 = RTCritSectEnter(&pThis->CritSect);
+    AssertRC(rc2);
+
     if (pGstStrmOut)
         drvAudioDestroyGstOut(pThis, pGstStrmOut);
+
+    rc2 = RTCritSectLeave(&pThis->CritSect);
+    AssertRC(rc2);
 }
 
@@ -2206,4 +2362,23 @@
 
 /**
+ * Destructs an audio driver instance.
+ *
+ * @copydoc FNPDMDRVDESTRUCT
+ */
+static DECLCALLBACK(void) drvAudioDestruct(PPDMDRVINS pDrvIns)
+{
+    LogFlowFuncEnter();
+
+    PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
+    PDRVAUDIO pThis = PDMINS_2_DATA(pDrvIns, PDRVAUDIO);
+
+    if (RTCritSectIsInitialized(&pThis->CritSect))
+    {
+        int rc2 = RTCritSectDelete(&pThis->CritSect);
+        AssertRC(rc2);
+    }
+}
+
+/**
  * Suspend notification.
  *
@@ -2242,5 +2417,5 @@
     /* fFlags */
     PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
-    /* fClass. */
+    /* fClass */
     PDM_DRVREG_CLASS_AUDIO,
     /* cMaxInstances */
@@ -2251,5 +2426,5 @@
     drvAudioConstruct,
     /* pfnDestruct */
-    NULL,
+    drvAudioDestruct,
     /* pfnRelocate */
     NULL,
Index: /trunk/src/VBox/Devices/Audio/DrvAudio.h
===================================================================
--- /trunk/src/VBox/Devices/Audio/DrvAudio.h	(revision 59419)
+++ /trunk/src/VBox/Devices/Audio/DrvAudio.h	(revision 59420)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2015 Oracle Corporation
+ * Copyright (C) 2006-2016 Oracle Corporation
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -47,4 +47,5 @@
 
 #include <iprt/circbuf.h>
+#include <iprt/critsect.h>
 
 #include <VBox/vmm/pdmdev.h>
@@ -79,6 +80,6 @@
     /** Input/output processing thread. */
     RTTHREAD                hThread;
-    /** Event for input/ouput processing. */
-    RTSEMEVENT              hEvent;
+    /** Critical section for serializing access. */
+    RTCRITSECT              CritSect;
     /** Shutdown indicator. */
     bool                    fTerminate;
@@ -89,5 +90,7 @@
     /** Pointer to audio driver below us. */
     PPDMIHOSTAUDIO          pHostDrvAudio;
+    /** List of host input streams. */
     RTLISTANCHOR            lstHstStrmIn;
+    /** List of host output streams. */
     RTLISTANCHOR            lstHstStrmOut;
     /** Max. number of free input streams. */
@@ -95,6 +98,5 @@
     /** Max. number of free output streams. */
     uint8_t                 cFreeOutputStreams;
-    /** Audio configuration settings retrieved
-     *  from the backend. */
+    /** Audio configuration settings retrieved from the backend. */
     PDMAUDIOBACKENDCFG      BackendCfg;
 #ifdef VBOX_WITH_AUDIO_CALLBACKS
