Index: /trunk/src/VBox/Devices/Audio/DevHDA.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 65003)
+++ /trunk/src/VBox/Devices/Audio/DevHDA.cpp	(revision 65004)
@@ -1020,4 +1020,6 @@
 # ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
 static DECLCALLBACK(int) hdaStreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);
+static int               hdaStreamAsyncIOCreate(PHDASTATE pThis, PHDASTREAM pStream);
+static int               hdaStreamAsyncIODestroy(PHDASTATE pThis, PHDASTREAM pStream);
 static int               hdaStreamAsyncIONotify(PHDASTATE pThis, PHDASTREAM pStream);
 static void              hdaStreamAsyncIOLock(PHDASTREAM pStream);
@@ -1703,5 +1705,6 @@
 static int hdaStreamCreate(PHDASTATE pThis, PHDASTREAM pStream, uint8_t uSD)
 {
-    AssertPtrReturn(pStream, VERR_INVALID_POINTER);
+    RT_NOREF(pThis);
+    AssertPtrReturn(pStream,             VERR_INVALID_POINTER);
     AssertReturn(uSD <= HDA_MAX_STREAMS, VERR_INVALID_PARAMETER);
 
@@ -1718,51 +1721,26 @@
         rc = RTCircBufCreate(&pStream->State.pCircBuf, _4K); /** @todo Make this configurable. */
 
+    LogFlowFunc(("uSD=%RU8\n", uSD));
+    return rc;
+}
+
+static void hdaStreamDestroy(PHDASTATE pThis, PHDASTREAM pStream)
+{
+    AssertPtrReturnVoid(pStream);
+
+    LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
+
+    hdaStreamMapDestroy(&pStream->State.Mapping);
+
+    int rc2;
+
 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
-    /*
-     * Create async I/O stuff.
-     */
-    PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
-
-    pAIO->fShutdown = false;
-
-    if (RT_SUCCESS(rc))
-    {
-        rc = RTSemEventCreate(&pAIO->Event);
-        if (RT_SUCCESS(rc))
-        {
-            rc = RTCritSectInit(&pAIO->CritSect);
-            if (RT_SUCCESS(rc))
-            {
-                HDASTREAMTHREADCTX Ctx = { pThis, pStream };
-
-                char szThreadName[64];
-                RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);
-
-                /** @todo Create threads on demand? */
-
-                rc = RTThreadCreate(&pAIO->Thread, hdaStreamAsyncIOThread, &Ctx,
-                                    0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
-                if (RT_SUCCESS(rc))
-                    rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
-            }
-        }
-    }
+    rc2 = hdaStreamAsyncIODestroy(pThis, pStream);
+    AssertRC(rc2);
 #else
     RT_NOREF(pThis);
 #endif
 
-    LogFlowFunc(("uSD=%RU8\n", uSD));
-    return rc;
-}
-
-static void hdaStreamDestroy(PHDASTATE pThis, PHDASTREAM pStream)
-{
-    AssertPtrReturnVoid(pStream);
-
-    LogFlowFunc(("[SD%RU8]: Destroying ...\n", pStream->u8SD));
-
-    hdaStreamMapDestroy(&pStream->State.Mapping);
-
-    int rc2 = RTCritSectDelete(&pStream->State.CritSect);
+    rc2 = RTCritSectDelete(&pStream->State.CritSect);
     AssertRC(rc2);
 
@@ -1772,37 +1750,4 @@
         pStream->State.pCircBuf = NULL;
     }
-
-#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
-    /*
-     * Destroy async I/O stuff.
-     */
-    PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
-
-    if (ASMAtomicReadBool(&pAIO->fStarted))
-    {
-        ASMAtomicWriteBool(&pAIO->fShutdown, true);
-
-        rc2 = hdaStreamAsyncIONotify(pThis, pStream);
-        AssertRC(rc2);
-
-        int rcThread;
-        rc2 = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
-        LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc2, rcThread));
-
-        if (RT_SUCCESS(rc2))
-        {
-            rc2 = RTCritSectDelete(&pAIO->CritSect);
-            AssertRC(rc2);
-
-            rc2 = RTSemEventDestroy(pAIO->Event);
-            AssertRC(rc2);
-
-            pAIO->fStarted  = false;
-            pAIO->fShutdown = false;
-        }
-    }
-#else
-    RT_NOREF(pThis);
-#endif
 
     LogFlowFuncLeave();
@@ -1858,8 +1803,19 @@
 
     /*
-     * Set reset state.
+     * Enter reset state.
      */
     Assert(ASMAtomicReadBool(&pStream->State.fInReset) == false); /* No nested calls. */
     ASMAtomicXchgBool(&pStream->State.fInReset, true);
+
+    int rc2;
+#ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
+    /*
+     * Make sure to destroy the async I/O thread for this stream on reset, as we
+     * can't be sure that the same stream is being used in the next cycle
+     * (and therefore would leave unused threads around).
+     */
+    rc2 = hdaStreamAsyncIODestroy(pThis, pStream);
+    AssertRC(rc2);
+#endif
 
     /*
@@ -1897,5 +1853,5 @@
     HDA_STREAM_REG(pThis, BDPL,  uSD) = 0;
 
-    int rc2 = hdaStreamInit(pThis, pStream, uSD);
+    rc2 = hdaStreamInit(pThis, pStream, uSD);
     AssertRC(rc2);
 
@@ -1914,5 +1870,8 @@
 
 #ifdef VBOX_WITH_AUDIO_HDA_ASYNC_IO
-    hdaStreamAsyncIOLock(pStream);
+    if (fEnable)
+        rc = hdaStreamAsyncIOCreate(pThis, pStream);
+    if (RT_SUCCESS(rc))
+        hdaStreamAsyncIOLock(pStream);
 #endif
 
@@ -4519,4 +4478,87 @@
 
 /**
+ * Creates the async I/O thread for a specific HDA audio stream.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA audio stream to create the async I/O thread for.
+ */
+static int hdaStreamAsyncIOCreate(PHDASTATE pThis, PHDASTREAM pStream)
+{
+    PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
+
+    int rc;
+
+    if (!ASMAtomicReadBool(&pAIO->fStarted))
+    {
+        pAIO->fShutdown = false;
+
+        rc = RTSemEventCreate(&pAIO->Event);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTCritSectInit(&pAIO->CritSect);
+            if (RT_SUCCESS(rc))
+            {
+                HDASTREAMTHREADCTX Ctx = { pThis, pStream };
+
+                char szThreadName[64];
+                RTStrPrintf2(szThreadName, sizeof(szThreadName), "hdaAIO%RU8", pStream->u8SD);
+
+                /** @todo Create threads on demand? */
+
+                rc = RTThreadCreate(&pAIO->Thread, hdaStreamAsyncIOThread, &Ctx,
+                                    0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
+                if (RT_SUCCESS(rc))
+                    rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
+            }
+        }
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
+    return rc;
+}
+
+/**
+ * Destroys the async I/O thread of a specific HDA audio stream.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               HDA state.
+ * @param   pStream             HDA audio stream to destroy the async I/O thread for.
+ */
+static int hdaStreamAsyncIODestroy(PHDASTATE pThis, PHDASTREAM pStream)
+{
+    PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
+
+    if (!ASMAtomicReadBool(&pAIO->fStarted))
+        return VINF_SUCCESS;
+
+    ASMAtomicWriteBool(&pAIO->fShutdown, true);
+
+    int rc = hdaStreamAsyncIONotify(pThis, pStream);
+    AssertRC(rc);
+
+    int rcThread;
+    rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
+    LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));
+
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTCritSectDelete(&pAIO->CritSect);
+        AssertRC(rc);
+
+        rc = RTSemEventDestroy(pAIO->Event);
+        AssertRC(rc);
+
+        pAIO->fStarted  = false;
+        pAIO->fShutdown = false;
+    }
+
+    LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8SD, rc));
+    return rc;
+}
+
+/**
  * Lets the stream's async I/O thread know that there is some data to process.
  *
@@ -4531,7 +4573,15 @@
 }
 
+/**
+ * Locks the async I/O thread of a specific HDA audio stream.
+ *
+ * @param   pStream             HDA stream to lock async I/O thread for.
+ */
 static void hdaStreamAsyncIOLock(PHDASTREAM pStream)
 {
     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
+
+    if (!ASMAtomicReadBool(&pAIO->fStarted))
+        return;
 
     int rc2 = RTCritSectEnter(&pAIO->CritSect);
@@ -4539,7 +4589,15 @@
 }
 
+/**
+ * Unlocks the async I/O thread of a specific HDA audio stream.
+ *
+ * @param   pStream             HDA stream to unlock async I/O thread for.
+ */
 static void hdaStreamAsyncIOUnlock(PHDASTREAM pStream)
 {
     PHDASTREAMSTATEAIO pAIO = &pStream->State.AIO;
+
+    if (!ASMAtomicReadBool(&pAIO->fStarted))
+        return;
 
     int rc2 = RTCritSectLeave(&pAIO->CritSect);
Index: /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp
===================================================================
--- /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 65003)
+++ /trunk/src/VBox/Devices/Audio/DevIchAc97.cpp	(revision 65004)
@@ -485,4 +485,6 @@
 #ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
 static DECLCALLBACK(int)  ichac97StreamAsyncIOThread(RTTHREAD hThreadSelf, void *pvUser);
+static int                ichac97StreamAsyncIOCreate(PAC97STATE pThis, PAC97STREAM pStream);
+static int                ichac97StreamAsyncIODestroy(PAC97STATE pThis, PAC97STREAM pStream);
 static int                ichac97StreamAsyncIONotify(PAC97STATE pThis, PAC97STREAM pStream);
 static void               ichac97StreamAsyncIOLock(PAC97STREAM pStream);
@@ -633,5 +635,8 @@
 
 #ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
-    ichac97StreamAsyncIOLock(pStream);
+    if (fEnable)
+        rc = ichac97StreamAsyncIOCreate(pThis, pStream);
+    if (RT_SUCCESS(rc))
+        ichac97StreamAsyncIOLock(pStream);
 #endif
 
@@ -708,5 +713,7 @@
 static int ichac97StreamCreate(PAC97STATE pThis, PAC97STREAM pStream, uint8_t u8Strm)
 {
+    RT_NOREF(pThis);
     AssertPtrReturn(pStream, VERR_INVALID_PARAMETER);
+    /** @todo Validate u8Strm. */
 
     LogFunc(("[SD%RU8] pStream=%p\n", u8Strm, pStream));
@@ -717,38 +724,4 @@
     if (RT_SUCCESS(rc))
         rc = RTCircBufCreate(&pStream->State.pCircBuf, _4K); /** @todo Make this configurable. */
-
-#ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
-    /*
-     * Create async I/O stuff.
-     */
-    PAC97STREAMSTATEAIO pAIO = &pStream->State.AIO;
-
-    pAIO->fShutdown = false;
-
-    if (RT_SUCCESS(rc))
-    {
-        rc = RTSemEventCreate(&pAIO->Event);
-        if (RT_SUCCESS(rc))
-        {
-            rc = RTCritSectInit(&pAIO->CritSect);
-            if (RT_SUCCESS(rc))
-            {
-                AC97STREAMTHREADCTX Ctx = { pThis, pStream };
-
-                char szThreadName[64];
-                RTStrPrintf2(szThreadName, sizeof(szThreadName), "ac97AIO%RU8", pStream->u8Strm);
-
-                /** @todo Create threads on demand? */
-
-                rc = RTThreadCreate(&pAIO->Thread, ichac97StreamAsyncIOThread, &Ctx,
-                                    0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
-                if (RT_SUCCESS(rc))
-                    rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
-            }
-        }
-    }
-#else
-    RT_NOREF(pThis);
-#endif
 
     return rc;
@@ -776,32 +749,6 @@
 
 #ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
-    /*
-     * Destroy async I/O stuff.
-     */
-    PAC97STREAMSTATEAIO pAIO = &pStream->State.AIO;
-
-    if (ASMAtomicReadBool(&pAIO->fStarted))
-    {
-        ASMAtomicWriteBool(&pAIO->fShutdown, true);
-
-        rc2 = ichac97StreamAsyncIONotify(pThis, pStream);
-        AssertRC(rc2);
-
-        int rcThread;
-        rc2 = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
-        LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc2, rcThread));
-
-        if (RT_SUCCESS(rc2))
-        {
-            rc2 = RTCritSectDelete(&pAIO->CritSect);
-            AssertRC(rc2);
-
-            rc2 = RTSemEventDestroy(pAIO->Event);
-            AssertRC(rc2);
-
-            pAIO->fStarted  = false;
-            pAIO->fShutdown = false;
-        }
-    }
+    rc2 = ichac97StreamAsyncIODestroy(pThis, pStream);
+    AssertRC(rc2);
 #else
     RT_NOREF(pThis);
@@ -1059,4 +1006,87 @@
 
     return VINF_SUCCESS;
+}
+
+/**
+ * Creates the async I/O thread for a specific AC'97 audio stream.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               AC'97 state.
+ * @param   pStream             AC'97 audio stream to create the async I/O thread for.
+ */
+static int ichac97StreamAsyncIOCreate(PAC97STATE pThis, PAC97STREAM pStream)
+{
+    PAC97STREAMSTATEAIO pAIO = &pStream->State.AIO;
+
+    int rc;
+
+    if (!ASMAtomicReadBool(&pAIO->fStarted))
+    {
+        pAIO->fShutdown = false;
+
+        rc = RTSemEventCreate(&pAIO->Event);
+        if (RT_SUCCESS(rc))
+        {
+            rc = RTCritSectInit(&pAIO->CritSect);
+            if (RT_SUCCESS(rc))
+            {
+                AC97STREAMTHREADCTX Ctx = { pThis, pStream };
+
+                char szThreadName[64];
+                RTStrPrintf2(szThreadName, sizeof(szThreadName), "ac97AIO%RU8", pStream->u8Strm);
+
+                /** @todo Create threads on demand? */
+
+                rc = RTThreadCreate(&pAIO->Thread, ichac97StreamAsyncIOThread, &Ctx,
+                                    0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, szThreadName);
+                if (RT_SUCCESS(rc))
+                    rc = RTThreadUserWait(pAIO->Thread, 10 * 1000 /* 10s timeout */);
+            }
+        }
+    }
+    else
+        rc = VINF_SUCCESS;
+
+    LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8Strm, rc));
+    return rc;
+}
+
+/**
+ * Destroys the async I/O thread of a specific AC'97 audio stream.
+ *
+ * @returns IPRT status code.
+ * @param   pThis               AC'97 state.
+ * @param   pStream             AC'97 audio stream to destroy the async I/O thread for.
+ */
+static int ichac97StreamAsyncIODestroy(PAC97STATE pThis, PAC97STREAM pStream)
+{
+    PAC97STREAMSTATEAIO pAIO = &pStream->State.AIO;
+
+    if (!ASMAtomicReadBool(&pAIO->fStarted))
+        return VINF_SUCCESS;
+
+    ASMAtomicWriteBool(&pAIO->fShutdown, true);
+
+    int rc = ichac97StreamAsyncIONotify(pThis, pStream);
+    AssertRC(rc);
+
+    int rcThread;
+    rc = RTThreadWait(pAIO->Thread, 30 * 1000 /* 30s timeout */, &rcThread);
+    LogFunc(("Async I/O thread ended with %Rrc (%Rrc)\n", rc, rcThread));
+
+    if (RT_SUCCESS(rc))
+    {
+        rc = RTCritSectDelete(&pAIO->CritSect);
+        AssertRC(rc);
+
+        rc = RTSemEventDestroy(pAIO->Event);
+        AssertRC(rc);
+
+        pAIO->fStarted  = false;
+        pAIO->fShutdown = false;
+    }
+
+    LogFunc(("[SD%RU8]: Returning %Rrc\n", pStream->u8Strm, rc));
+    return rc;
 }
 
@@ -1549,4 +1579,14 @@
 
     LogFlowFunc(("[SD%RU8]\n", pStream->u8Strm));
+
+#ifdef VBOX_WITH_AUDIO_AC97_ASYNC_IO
+    /*
+     * Make sure to destroy the async I/O thread for this stream on reset, as we
+     * can't be sure that the same stream is being used in the next cycle
+     * (and therefore would leave unused threads around).
+     */
+    int rc2 = ichac97StreamAsyncIODestroy(pThis, pStream);
+    AssertRC(rc2);
+#endif
 
     if (pStream->State.pCircBuf)
