Index: trunk/src/VBox/Devices/Input/DrvKeyboardQueue.cpp
===================================================================
--- trunk/src/VBox/Devices/Input/DrvKeyboardQueue.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Input/DrvKeyboardQueue.cpp	(revision 28258)
@@ -307,5 +307,5 @@
     }
 
-    rc = PDMDrvHlpPDMQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, "Keyboard", &pDrv->pQueue);
+    rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, "Keyboard", &pDrv->pQueue);
     if (RT_FAILURE(rc))
     {
Index: trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp
===================================================================
--- trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Input/DrvMouseQueue.cpp	(revision 28258)
@@ -344,5 +344,5 @@
     }
 
-    rc = PDMDrvHlpPDMQueueCreate(pDrvIns, sizeof(DRVMOUSEQUEUEITEM), cItems, cMilliesInterval, drvMouseQueueConsumer, "Mouse", &pDrv->pQueue);
+    rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVMOUSEQUEUEITEM), cItems, cMilliesInterval, drvMouseQueueConsumer, "Mouse", &pDrv->pQueue);
     if (RT_FAILURE(rc))
     {
Index: trunk/src/VBox/Devices/Network/DevINIP.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DevINIP.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Network/DevINIP.cpp	(revision 28258)
@@ -305,5 +305,5 @@
  * @param   cMillies    Number of milliseconds to wait. 0 means return immediately.
  */
-static DECLCALLBACK(int) devINIPWaitInputAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
+static DECLCALLBACK(int) devINIPNetworkDown_WaitInputAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
 {
     LogFlow(("%s: pInterface=%p\n", __FUNCTION__, pInterface));
@@ -320,6 +320,6 @@
  * @param   cb          Frame size.
  */
-static DECLCALLBACK(int) devINIPInput(PPDMINETWORKDOWN pInterface,
-                                      const void *pvBuf, size_t cb)
+static DECLCALLBACK(int) devINIPNetworkDown_Input(PPDMINETWORKDOWN pInterface,
+                                                  const void *pvBuf, size_t cb)
 {
     const uint8_t *pbBuf = (const uint8_t *)pvBuf;
@@ -385,4 +385,13 @@
 
 /**
+ * @interface_method_impl{PDMINETWORKDOWN,pfnDoTransmitWork}
+ */
+static DECLCALLBACK(void) devINIPNetworkDown_DoTransmitWork(PPDMINETWORKDOWN pInterface)
+{
+    NOREF(pInterface);
+}
+
+
+/**
  * Signals the end of lwIP TCPIP initialization.
  *
@@ -483,6 +492,7 @@
     pThis->IBase.pfnQueryInterface          = devINIPQueryInterface;
     /* INetworkDown */
-    pThis->INetworkDown.pfnWaitReceiveAvail = devINIPWaitInputAvail;
-    pThis->INetworkDown.pfnReceive          = devINIPInput;
+    pThis->INetworkDown.pfnWaitReceiveAvail = devINIPNetworkDown_WaitInputAvail;
+    pThis->INetworkDown.pfnReceive          = devINIPNetworkDown_Input;
+    pThis->INetworkDown.pfnDoTransmitWork   = devINIPNetworkDown_DoTransmitWork;
 
     /*
Index: trunk/src/VBox/Devices/Network/DrvIntNet.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvIntNet.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Network/DrvIntNet.cpp	(revision 28258)
@@ -1,2 +1,3 @@
+#define VBOX_WITH_R0_AND_RC_DRIVERS
 /* $Id$ */
 /** @file
@@ -111,4 +112,7 @@
     /** Base interface for ring-0. */
     PDMIBASERC                      IBaseRC;
+
+    /** The transmit lock. */
+    PDMCRITSECT                     XmitLock;
 
 #ifdef LOG_ENABLED
@@ -190,5 +194,20 @@
 }
 
+
+
 /* -=-=-=-=- PDMINETWORKUP -=-=-=-=- */
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
+ */
+static DECLCALLBACK(int) drvR3IntNetUp_BeginXmit(PPDMINETWORKUP pInterface)
+{
+    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3);
+    int rc = PDMCritSectTryEnter(&pThis->XmitLock);
+    if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
+        rc = VERR_TRY_AGAIN;
+    return rc;
+}
+
 
 /**
@@ -201,4 +220,5 @@
     int         rc    = VINF_SUCCESS;
     Assert(cbMin < UINT32_MAX / 2);
+//    Assert(PDMCritSectIsOwner(&pThis->XmitLock));
 
     /*
@@ -277,4 +297,5 @@
     Assert(   pHdr->u16Type == INTNETHDR_TYPE_FRAME
            || pHdr->u16Type == INTNETHDR_TYPE_GSO);
+//    Assert(PDMCritSectIsOwner(&pThis->XmitLock));
 
     /** @todo LATER: try unalloc the frame. */
@@ -298,4 +319,5 @@
     Assert(pSgBuf->fFlags == (PDMSCATTERGATHER_FLAGS_MAGIC | PDMSCATTERGATHER_FLAGS_OWNER_1));
     Assert(pSgBuf->cbUsed <= pSgBuf->cbAvailable);
+//    Assert(PDMCritSectIsOwner(&pThis->XmitLock));
 
     if (pSgBuf->pvUser)
@@ -319,4 +341,14 @@
     STAM_PROFILE_STOP(&pThis->StatTransmit, a);
     return VINF_SUCCESS;
+}
+
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
+ */
+static DECLCALLBACK(void) drvR3IntNetUp_EndXmit(PPDMINETWORKUP pInterface)
+{
+    PDRVINTNET pThis = RT_FROM_MEMBER(pInterface, DRVINTNET, INetworkUpR3);
+    PDMCritSectLeave(&pThis->XmitLock);
 }
 
@@ -762,5 +794,5 @@
         Frame.Hdr.DstMac.au16[1] = 0xffff;
         Frame.Hdr.DstMac.au16[2] = 0xffff;
-        Frame.Hdr.EtherType      = RT_H2BE_U16(0x801e);
+        Frame.Hdr.EtherType      = RT_H2BE_U16_C(0x801e);
         int rc = pThis->pIAboveConfigR3->pfnGetMac(pThis->pIAboveConfigR3, &Frame.Hdr.SrcMac);
         if (RT_SUCCESS(rc))
@@ -805,4 +837,13 @@
         drvR3IntNetSetActive(pThis, true /* fActive */);
     }
+}
+
+
+/**
+ * @interface_method_impl{PDMDRVREG,pfnRelocate}
+ */
+static DECLCALLBACK(void) drvR3IntNetRelocate(PPDMDRVINS pDrvIns, RTGCINTPTR offDelta)
+{
+    /* nothing to do here yet */
 }
 
@@ -858,5 +899,5 @@
 
     /*
-     * Destroy the semaphore and S/G cache.
+     * Destroy the semaphore, S/G cache and xmit lock.
      */
     if (hEvtSuspended != NIL_RTSEMEVENT)
@@ -865,4 +906,7 @@
     RTMemCacheDestroy(pThis->hSgCache);
     pThis->hSgCache = NIL_RTMEMCACHE;
+
+    if (PDMCritSectIsInitialized(&pThis->XmitLock))
+        PDMR3CritSectDelete(&pThis->XmitLock);
 
     if (pThis->pBufR3)
@@ -917,7 +961,9 @@
     pThis->IBaseRC.pfnQueryInterface                = drvR3IntNetIBaseRC_QueryInterface;
     /* INetworkUp */
+    pThis->INetworkUpR3.pfnBeginXmit                = drvR3IntNetUp_BeginXmit;
     pThis->INetworkUpR3.pfnAllocBuf                 = drvR3IntNetUp_AllocBuf;
     pThis->INetworkUpR3.pfnFreeBuf                  = drvR3IntNetUp_FreeBuf;
     pThis->INetworkUpR3.pfnSendBuf                  = drvR3IntNetUp_SendBuf;
+    pThis->INetworkUpR3.pfnEndXmit                  = drvR3IntNetUp_EndXmit;
     pThis->INetworkUpR3.pfnSetPromiscuousMode       = drvR3IntNetUp_SetPromiscuousMode;
     pThis->INetworkUpR3.pfnNotifyLinkChanged        = drvR3IntNetUp_NotifyLinkChanged;
@@ -1186,5 +1232,5 @@
 
     /*
-     * Create the event semaphore and S/G cache.
+     * Create the event semaphore, S/G cache and xmit critsect.
      */
     rc = RTSemEventCreate(&pThis->hEvtSuspended);
@@ -1194,4 +1240,8 @@
     if (RT_FAILURE(rc))
         return rc;
+    rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "IntNetXmit");
+    if (RT_FAILURE(rc))
+        return rc;
+
 
     /*
@@ -1276,7 +1326,7 @@
     "IntNet",
     /* szRCMod */
-    "VBoxDD",
+    "VBoxDDRC",
     /* szR0Mod */
-    "VBoxDD",
+    "VBoxDDR0",
     /* pszDescription */
     "Internal Networking Transport Driver",
@@ -1298,5 +1348,5 @@
     drvR3IntNetDestruct,
     /* pfnRelocate */
-    NULL,
+    drvR3IntNetRelocate,
     /* pfnIOCtl */
     NULL,
Index: trunk/src/VBox/Devices/Network/DrvNAT.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 28258)
@@ -151,5 +151,5 @@
     /** tftp server name to provide in the DHCP server response. */
     char                   *pszNextServer;
-    /* polling thread */
+    /** Polling thread. */
     PPDMTHREAD              pSlirpThread;
     /** Queue for NAT-thread-external events. */
@@ -193,7 +193,12 @@
 
     /** makes access to device func RecvAvail and Recv atomical. */
-    RTCRITSECT              csDevAccess;
-    volatile uint32_t       cUrgPkt;
-    volatile uint32_t       cPkt;
+    RTCRITSECT              DevAccessLock;
+    /** Number of in-flight urgent packets. */
+    volatile uint32_t       cUrgPkts;
+    /** Number of in-flight regular packets. */
+    volatile uint32_t       cPkts;
+
+    /** Transmit lock taken by BeginXmit and released by EndXmit. */
+    RTCRITSECT              XmitLock;
 } DRVNAT;
 AssertCompileMemberAlignment(DRVNAT, StatNATRecvWakeups, 8);
@@ -235,5 +240,5 @@
     {
         RTReqProcess(pThis->pRecvReqQueue, 0);
-        if (ASMAtomicReadU32(&pThis->cPkt) == 0)
+        if (ASMAtomicReadU32(&pThis->cPkts) == 0)
             RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
     }
@@ -262,5 +267,5 @@
     {
         RTReqProcess(pThis->pUrgRecvReqQueue, 0);
-        if (ASMAtomicReadU32(&pThis->cUrgPkt) == 0)
+        if (ASMAtomicReadU32(&pThis->cUrgPkts) == 0)
         {
             int rc = RTSemEventWait(pThis->EventUrgRecv, RT_INDEFINITE_WAIT);
@@ -282,5 +287,5 @@
 static DECLCALLBACK(void) drvNATUrgRecvWorker(PDRVNAT pThis, uint8_t *pu8Buf, int cb, struct mbuf *m)
 {
-    int rc = RTCritSectEnter(&pThis->csDevAccess);
+    int rc = RTCritSectEnter(&pThis->DevAccessLock);
     AssertRC(rc);
     rc = pThis->pIAboveNet->pfnWaitReceiveAvail(pThis->pIAboveNet, RT_INDEFINITE_WAIT);
@@ -297,5 +302,5 @@
     }
 
-    rc = RTCritSectLeave(&pThis->csDevAccess);
+    rc = RTCritSectLeave(&pThis->DevAccessLock);
     AssertRC(rc);
 
@@ -304,5 +309,5 @@
     RTMemFree(pu8Buf);
 #endif
-    if (ASMAtomicDecU32(&pThis->cUrgPkt) == 0)
+    if (ASMAtomicDecU32(&pThis->cUrgPkts) == 0)
     {
         drvNATRecvWakeup(pThis->pDrvIns, pThis->pRecvThread);
@@ -319,5 +324,5 @@
     STAM_PROFILE_START(&pThis->StatNATRecvWait, b);
 
-    while (ASMAtomicReadU32(&pThis->cUrgPkt) != 0)
+    while (ASMAtomicReadU32(&pThis->cUrgPkts) != 0)
     {
         rc = RTSemEventWait(pThis->EventRecv, RT_INDEFINITE_WAIT);
@@ -328,5 +333,5 @@
     }
 
-    rc = RTCritSectEnter(&pThis->csDevAccess);
+    rc = RTCritSectEnter(&pThis->DevAccessLock);
     AssertRC(rc);
 
@@ -344,5 +349,5 @@
     }
 
-    rc = RTCritSectLeave(&pThis->csDevAccess);
+    rc = RTCritSectLeave(&pThis->DevAccessLock);
     AssertRC(rc);
 
@@ -352,5 +357,5 @@
     RTMemFree(pu8Buf);
 #endif
-    ASMAtomicDecU32(&pThis->cPkt);
+    ASMAtomicDecU32(&pThis->cPkts);
 
     drvNATNotifyNATThread(pThis, "drvNATRecvWorker");
@@ -451,4 +456,19 @@
 
 /**
+ * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
+ */
+static DECLCALLBACK(int) drvNATNetworkUp_BeginXmit(PPDMINETWORKUP pInterface)
+{
+    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
+    int rc = RTCritSectTryEnter(&pThis->XmitLock);
+    if (RT_FAILURE(rc))
+    {
+        /** @todo Kick the worker thread when we have one... */
+        rc = VERR_TRY_AGAIN;
+    }
+    return rc;
+}
+
+/**
  * @interface_method_impl{PDMINETWORKUP,pfnAllocBuf}
  */
@@ -457,4 +477,5 @@
 {
     PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
+//    Assert(RTCritSectIsOwner(&pThis->XmitLock);
 
     /*
@@ -522,4 +543,5 @@
 {
     PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
+//    Assert(RTCritSectIsOwner(&pThis->XmitLock);
     drvNATFreeSgBuf(pThis, pSgBuf);
     return VINF_SUCCESS;
@@ -533,4 +555,5 @@
     PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
     Assert((pSgBuf->fFlags & PDMSCATTERGATHER_FLAGS_OWNER_MASK) == PDMSCATTERGATHER_FLAGS_OWNER_1);
+//    Assert(RTCritSectIsOwner(&pThis->XmitLock);
 
     int rc;
@@ -556,4 +579,13 @@
     drvNATFreeSgBuf(pThis, pSgBuf);
     return rc;
+}
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
+ */
+static DECLCALLBACK(void) drvNATNetworkUp_EndXmit(PPDMINETWORKUP pInterface)
+{
+    PDRVNAT pThis = RT_FROM_MEMBER(pInterface, DRVNAT, INetworkUp);
+    RTCritSectLeave(&pThis->XmitLock);
 }
 
@@ -841,5 +873,5 @@
         return;
 
-    ASMAtomicIncU32(&pThis->cUrgPkt);
+    ASMAtomicIncU32(&pThis->cUrgPkts);
     int rc = RTReqCallEx(pThis->pUrgRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
                          (PFNRT)drvNATUrgRecvWorker, 4, pThis, pu8Buf, cb, m);
@@ -865,5 +897,5 @@
         return;
 
-    ASMAtomicIncU32(&pThis->cPkt);
+    ASMAtomicIncU32(&pThis->cPkts);
     int rc = RTReqCallEx(pThis->pRecvReqQueue, NULL /*ppReq*/, 0 /*cMillies*/, RTREQFLAGS_VOID | RTREQFLAGS_NO_WAIT,
                          (PFNRT)drvNATRecvWorker, 4, pThis, pu8Buf, cb, m);
@@ -1030,4 +1062,22 @@
         pThis->pNATState = NULL;
     }
+
+    RTReqDestroyQueue(pThis->pSlirpReqQueue);
+    pThis->pSlirpReqQueue = NULL;
+
+    RTReqDestroyQueue(pThis->pUrgRecvReqQueue);
+    pThis->pUrgRecvReqQueue = NULL;
+
+    RTSemEventDestroy(pThis->EventRecv);
+    pThis->EventRecv = NIL_RTSEMEVENT;
+
+    RTSemEventDestroy(pThis->EventUrgRecv);
+    pThis->EventUrgRecv = NIL_RTSEMEVENT;
+
+    if (RTCritSectIsInitialized(&pThis->DevAccessLock))
+        RTCritSectDelete(&pThis->DevAccessLock);
+
+    if (RTCritSectIsInitialized(&pThis->XmitLock))
+        RTCritSectDelete(&pThis->XmitLock);
 }
 
@@ -1064,10 +1114,18 @@
     pThis->pszBootFile                  = NULL;
     pThis->pszNextServer                = NULL;
+    pThis->pSlirpReqQueue               = NULL;
+    pThis->pUrgRecvReqQueue             = NULL;
+    pThis->EventRecv                    = NIL_RTSEMEVENT;
+    pThis->EventUrgRecv                 = NIL_RTSEMEVENT;
+
     /* IBase */
     pDrvIns->IBase.pfnQueryInterface    = drvNATQueryInterface;
+
     /* INetwork */
+    pThis->INetworkUp.pfnBeginXmit          = drvNATNetworkUp_BeginXmit;
     pThis->INetworkUp.pfnAllocBuf           = drvNATNetworkUp_AllocBuf;
     pThis->INetworkUp.pfnFreeBuf            = drvNATNetworkUp_FreeBuf;
     pThis->INetworkUp.pfnSendBuf            = drvNATNetworkUp_SendBuf;
+    pThis->INetworkUp.pfnEndXmit            = drvNATNetworkUp_EndXmit;
     pThis->INetworkUp.pfnSetPromiscuousMode = drvNATNetworkUp_SetPromiscuousMode;
     pThis->INetworkUp.pfnNotifyLinkChanged  = drvNATNetworkUp_NotifyLinkChanged;
@@ -1170,6 +1228,6 @@
 #endif
 
-        int rc2 = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfg, Network);
-        if (RT_SUCCESS(rc2))
+        rc = drvNATConstructRedir(pDrvIns->iInstance, pThis, pCfg, Network);
+        if (RT_SUCCESS(rc))
         {
             /*
@@ -1177,6 +1235,7 @@
              * engine after we loaded a guest state.
              */
-            rc2 = PDMDrvHlpSSMRegisterLoadDone(pDrvIns, drvNATLoadDone);
-            AssertRC(rc2);
+            rc = PDMDrvHlpSSMRegisterLoadDone(pDrvIns, drvNATLoadDone);
+            AssertRCReturn(rc, rc);
+
             rc = RTReqCreateQueue(&pThis->pSlirpReqQueue);
             if (RT_FAILURE(rc))
@@ -1193,4 +1252,5 @@
                 return rc;
             }
+
             rc = RTReqCreateQueue(&pThis->pUrgRecvReqQueue);
             if (RT_FAILURE(rc))
@@ -1199,15 +1259,27 @@
                 return rc;
             }
-            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv,
-                                          drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");
-            AssertRC(rc);
+
+            rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvNATRecv,
+                                       drvNATRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATRX");
+            AssertRCReturn(rc, rc);
+
             rc = RTSemEventCreate(&pThis->EventRecv);
-
-            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pUrgRecvThread, pThis, drvNATUrgRecv,
-                                          drvNATUrgRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATURGRX");
-            AssertRC(rc);
+            AssertRCReturn(rc, rc);
+
+            rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pUrgRecvThread, pThis, drvNATUrgRecv,
+                                       drvNATUrgRecvWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATURGRX");
+            AssertRCReturn(rc, rc);
+
             rc = RTSemEventCreate(&pThis->EventRecv);
+            AssertRCReturn(rc, rc);
+
             rc = RTSemEventCreate(&pThis->EventUrgRecv);
-            rc = RTCritSectInit(&pThis->csDevAccess);
+            AssertRCReturn(rc, rc);
+
+            rc = RTCritSectInit(&pThis->DevAccessLock);
+            AssertRCReturn(rc, rc);
+
+            rc = RTCritSectInit(&pThis->XmitLock);
+            AssertRCReturn(rc, rc);
 
 #ifndef RT_OS_WINDOWS
@@ -1230,11 +1302,11 @@
 #endif
 
-            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pSlirpThread, pThis, drvNATAsyncIoThread,
-                                          drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT");
+            rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pSlirpThread, pThis, drvNATAsyncIoThread,
+                                       drvNATAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "NAT");
             AssertRC(rc);
 
 #ifdef VBOX_WITH_SLIRP_MT
-            rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pGuestThread, pThis, drvNATAsyncIoGuest,
-                                          drvNATAsyncIoGuestWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATGUEST");
+            rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pGuestThread, pThis, drvNATAsyncIoGuest,
+                                       drvNATAsyncIoGuestWakeup, 128 * _1K, RTTHREADTYPE_IO, "NATGUEST");
             AssertRC(rc);
 #endif
@@ -1245,6 +1317,6 @@
             return rc;
         }
+
         /* failure path */
-        rc = rc2;
         slirp_term(pThis->pNATState);
         pThis->pNATState = NULL;
Index: trunk/src/VBox/Devices/Network/DrvNetSniffer.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvNetSniffer.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Network/DrvNetSniffer.cpp	(revision 28258)
@@ -77,7 +77,26 @@
     /** Pointer to the driver instance. */
     PPDMDRVINS              pDrvIns;
+    /** For when we're the leaf driver. */
+    RTCRITSECT              XmitLock;
 
 } DRVNETSNIFFER, *PDRVNETSNIFFER;
 
+
+
+/**
+ * @interface_method_impl{PDMINETWORKUP,pfnBeginXmit}
+ */
+static DECLCALLBACK(int) drvNetSnifferUp_BeginXmit(PPDMINETWORKUP pInterface)
+{
+    PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
+    if (RT_UNLIKELY(!pThis->pIBelowNet))
+    {
+        int rc = RTCritSectTryEnter(&pThis->XmitLock);
+        if (RT_UNLIKELY(rc == VERR_SEM_BUSY))
+            rc = VERR_TRY_AGAIN;
+        return rc;
+    }
+    return pThis->pIBelowNet->pfnBeginXmit(pThis->pIBelowNet);
+}
 
 
@@ -135,4 +154,18 @@
 
 /**
+ * @interface_method_impl{PDMINETWORKUP,pfnEndXmit}
+ */
+static DECLCALLBACK(void) drvNetSnifferUp_EndXmit(PPDMINETWORKUP pInterface)
+{
+    LogFlow(("drvNetSnifferUp_EndXmit:\n"));
+    PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkUp);
+    if (RT_LIKELY(pThis->pIBelowNet))
+        pThis->pIBelowNet->pfnEndXmit(pThis->pIBelowNet);
+    else
+        RTCritSectLeave(&pThis->XmitLock);
+}
+
+
+/**
  * @interface_method_impl{PDMINETWORKUP,pfnSetPromiscuousMode}
  */
@@ -159,5 +192,5 @@
 
 /**
- * @copydoc PDMINETWORKDOWN::pfnWaitReceiveAvail
+ * @interface_method_impl{PDMINETWORKDOWN,pfnWaitReceiveAvail}
  */
 static DECLCALLBACK(int) drvNetSnifferDown_WaitReceiveAvail(PPDMINETWORKDOWN pInterface, RTMSINTERVAL cMillies)
@@ -169,5 +202,5 @@
 
 /**
- * @copydoc PDMINETWORKDOWN::pfnReceive
+ * @interface_method_impl{PDMINETWORKDOWN,pfnReceive}
  */
 static DECLCALLBACK(int) drvNetSnifferDown_Receive(PPDMINETWORKDOWN pInterface, const void *pvBuf, size_t cb)
@@ -196,10 +229,10 @@
 
 /**
- * @copydoc PDMINETWORKDOWN::pfnNotifyBufAvailable
- */
-static DECLCALLBACK(void) drvNetSnifferDown_NotifyBufAvailable(PPDMINETWORKDOWN pInterface)
+ * @interface_method_impl{PDMINETWORKDOWN,pfnDoTransmitWork}
+ */
+static DECLCALLBACK(void) drvNetSnifferDown_DoTransmitWork(PPDMINETWORKDOWN pInterface)
 {
     PDRVNETSNIFFER pThis = RT_FROM_MEMBER(pInterface, DRVNETSNIFFER, INetworkDown);
-    pThis->pIAboveNet->pfnNotifyBufAvailable(pThis->pIAboveNet);
+    pThis->pIAboveNet->pfnDoTransmitWork(pThis->pIAboveNet);
 }
 
@@ -263,8 +296,5 @@
 
 /**
- * Detach a driver instance.
- *
- * @param   pDrvIns     The driver instance.
- * @param   fFlags      Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+ * @interface_method_impl{PDMDRVREG,pfnDetach}
  */
 static DECLCALLBACK(void) drvNetSnifferDetach(PPDMDRVINS pDrvIns, uint32_t fFlags)
@@ -273,21 +303,18 @@
 
     LogFlow(("drvNetSnifferDetach: pDrvIns: %p, fFlags: %u\n", pDrvIns, fFlags));
-
+    RTCritSectEnter(&pThis->XmitLock);
     pThis->pIBelowNet = NULL;
-}
-
-
-/**
- * Attach a driver instance.
- *
- * @returns VBox status code.
- * @param   pDrvIns     The driver instance.
- * @param   fFlags      Flags, combination of the PDM_TACH_FLAGS_* \#defines.
+    RTCritSectLeave(&pThis->XmitLock);
+}
+
+
+/**
+ * @interface_method_impl{PDMDRVREG,pfnAttach}
  */
 static DECLCALLBACK(int) drvNetSnifferAttach(PPDMDRVINS pDrvIns, uint32_t fFlags)
 {
     PDRVNETSNIFFER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSNIFFER);
-
-    LogFlow(("drvNetSnifferAttach: pDrvIns: %p, fFlags: %u\n", pDrvIns, fFlags));
+    LogFlow(("drvNetSnifferAttach/#%#x: fFlags=%#x\n", pDrvIns->iInstance, fFlags));
+    RTCritSectEnter(&pThis->XmitLock);
 
     /*
@@ -298,20 +325,23 @@
     if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
         || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME)
+    {
         pThis->pIBelowNet = NULL;
+        rc = VINF_SUCCESS;
+    }
     else if (RT_SUCCESS(rc))
     {
         pThis->pIBelowNet = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP);
-        if (!pThis->pIBelowNet)
+        if (pThis->pIBelowNet)
+            rc = VINF_SUCCESS;
+        else
         {
             AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n"));
-            return VERR_PDM_MISSING_INTERFACE_BELOW;
+            rc = VERR_PDM_MISSING_INTERFACE_BELOW;
         }
     }
     else
-    {
         AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc));
-        return rc;
-    }
-
+
+    RTCritSectLeave(&pThis->XmitLock);
     return VINF_SUCCESS;
 }
@@ -319,10 +349,5 @@
 
 /**
- * Destruct a driver instance.
- *
- * Most VM resources are freed by the VM. This callback is provided so that any non-VM
- * resources can be freed correctly.
- *
- * @param   pDrvIns     The driver instance data.
+ * @interface_method_impl{PDMDRVREG,pfnDestruct}
  */
 static DECLCALLBACK(void) drvNetSnifferDestruct(PPDMDRVINS pDrvIns)
@@ -334,4 +359,7 @@
         RTCritSectDelete(&pThis->Lock);
 
+    if (RTCritSectIsInitialized(&pThis->XmitLock))
+        RTCritSectDelete(&pThis->XmitLock);
+
     if (pThis->File != NIL_RTFILE)
     {
@@ -343,7 +371,6 @@
 
 /**
- * Construct a NAT network transport driver instance.
- *
- * @copydoc FNPDMDRVCONSTRUCT
+ * @interface_method_impl{Construct a NAT network transport driver instance,
+ *                       PDMDRVREG,pfnDestruct}
  */
 static DECLCALLBACK(int) drvNetSnifferConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
@@ -352,13 +379,4 @@
     LogFlow(("drvNetSnifferConstruct:\n"));
     PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
-
-    /*
-     * Validate the config.
-     */
-    if (!CFGMR3AreValuesValid(pCfg, "File\0"))
-        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
-
-    if (CFGMR3GetFirstChild(pCfg))
-        LogRel(("NetSniffer: Found child config entries -- are you trying to redirect ports?\n"));
 
     /*
@@ -372,7 +390,9 @@
     pDrvIns->IBase.pfnQueryInterface                = drvNetSnifferQueryInterface;
     /* INetworkUp */
+    pThis->INetworkUp.pfnBeginXmit                  = drvNetSnifferUp_BeginXmit;
     pThis->INetworkUp.pfnAllocBuf                   = drvNetSnifferUp_AllocBuf;
     pThis->INetworkUp.pfnFreeBuf                    = drvNetSnifferUp_FreeBuf;
     pThis->INetworkUp.pfnSendBuf                    = drvNetSnifferUp_SendBuf;
+    pThis->INetworkUp.pfnEndXmit                    = drvNetSnifferUp_EndXmit;
     pThis->INetworkUp.pfnSetPromiscuousMode         = drvNetSnifferUp_SetPromiscuousMode;
     pThis->INetworkUp.pfnNotifyLinkChanged          = drvNetSnifferUp_NotifyLinkChanged;
@@ -380,5 +400,5 @@
     pThis->INetworkDown.pfnWaitReceiveAvail         = drvNetSnifferDown_WaitReceiveAvail;
     pThis->INetworkDown.pfnReceive                  = drvNetSnifferDown_Receive;
-    pThis->INetworkDown.pfnNotifyBufAvailable       = drvNetSnifferDown_NotifyBufAvailable;
+    pThis->INetworkDown.pfnDoTransmitWork           = drvNetSnifferDown_DoTransmitWork;
     /* INetworkConfig */
     pThis->INetworkConfig.pfnGetMac                 = drvNetSnifferDownCfg_GetMac;
@@ -387,7 +407,24 @@
 
     /*
+     * Create the locks.
+     */
+    int rc = RTCritSectInit(&pThis->Lock);
+    AssertRCReturn(rc, rc);
+    rc = RTCritSectInit(&pThis->XmitLock);
+    AssertRCReturn(rc, rc);
+
+    /*
+     * Validate the config.
+     */
+    if (!CFGMR3AreValuesValid(pCfg, "File\0"))
+        return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
+
+    if (CFGMR3GetFirstChild(pCfg))
+        LogRel(("NetSniffer: Found child config entries -- are you trying to redirect ports?\n"));
+
+    /*
      * Get the filename.
      */
-    int rc = CFGMR3QueryString(pCfg, "File", pThis->szFilename, sizeof(pThis->szFilename));
+    rc = CFGMR3QueryString(pCfg, "File", pThis->szFilename, sizeof(pThis->szFilename));
     if (rc == VERR_CFGM_VALUE_NOT_FOUND)
     {
@@ -446,11 +483,4 @@
         return rc;
     }
-
-    /*
-     * Create the lock.
-     */
-    rc = RTCritSectInit(&pThis->Lock);
-    if (RT_FAILURE(rc))
-        return rc;
 
     /*
Index: trunk/src/VBox/Devices/Network/DrvTAP.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvTAP.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Network/DrvTAP.cpp	(revision 28258)
@@ -1116,5 +1116,5 @@
      * Create the async I/O thread.
      */
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPAsyncIoThread, drvTapAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "TAP");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPAsyncIoThread, drvTapAsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "TAP");
     AssertRCReturn(rc, rc);
 
Index: trunk/src/VBox/Devices/PC/DrvACPI.cpp
===================================================================
--- trunk/src/VBox/Devices/PC/DrvACPI.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/PC/DrvACPI.cpp	(revision 28258)
@@ -982,6 +982,6 @@
      * Start the poller thread.
      */
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pPollerThread, pThis, drvACPIPoller,
-                                  drvACPIPollerWakeup, 0, RTTHREADTYPE_INFREQUENT_POLLER, "ACPI Poller");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pPollerThread, pThis, drvACPIPoller,
+                               drvACPIPollerWakeup, 0, RTTHREADTYPE_INFREQUENT_POLLER, "ACPI Poller");
     if (RT_FAILURE(rc))
         return rc;
Index: trunk/src/VBox/Devices/Parallel/DrvHostParallel.cpp
===================================================================
--- trunk/src/VBox/Devices/Parallel/DrvHostParallel.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Parallel/DrvHostParallel.cpp	(revision 28258)
@@ -379,6 +379,6 @@
      * Start waiting for interrupts.
      */
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0,
-                                  RTTHREADTYPE_IO, "ParMon");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostParallelMonitorThread, drvHostParallelWakeupMonitorThread, 0,
+                               RTTHREADTYPE_IO, "ParMon");
     if (RT_FAILURE(rc))
         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostParallel#%d cannot create monitor thread"), pDrvIns->iInstance);
Index: trunk/src/VBox/Devices/Serial/DrvHostSerial.cpp
===================================================================
--- trunk/src/VBox/Devices/Serial/DrvHostSerial.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Serial/DrvHostSerial.cpp	(revision 28258)
@@ -1435,5 +1435,5 @@
      * Create the receive, send and monitor threads pluss the related send semaphore.
      */
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvHostSerialRecvThread, drvHostSerialWakeupRecvThread, 0, RTTHREADTYPE_IO, "SerRecv");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pRecvThread, pThis, drvHostSerialRecvThread, drvHostSerialWakeupRecvThread, 0, RTTHREADTYPE_IO, "SerRecv");
     if (RT_FAILURE(rc))
         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostSerial#%d cannot create receive thread"), pDrvIns->iInstance);
@@ -1442,5 +1442,5 @@
     AssertRC(rc);
 
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pSendThread, pThis, drvHostSerialSendThread, drvHostSerialWakeupSendThread, 0, RTTHREADTYPE_IO, "SerSend");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pSendThread, pThis, drvHostSerialSendThread, drvHostSerialWakeupSendThread, 0, RTTHREADTYPE_IO, "SerSend");
     if (RT_FAILURE(rc))
         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostSerial#%d cannot create send thread"), pDrvIns->iInstance);
@@ -1451,5 +1451,5 @@
     ioctl(pThis->DeviceFile, TIOCMGET, &pThis->fStatusLines);
 # endif
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostSerialMonitorThread, drvHostSerialWakeupMonitorThread, 0, RTTHREADTYPE_IO, "SerMon");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pMonitorThread, pThis, drvHostSerialMonitorThread, drvHostSerialWakeupMonitorThread, 0, RTTHREADTYPE_IO, "SerMon");
     if (RT_FAILURE(rc))
         return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("HostSerial#%d cannot create monitor thread"), pDrvIns->iInstance);
Index: trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/DrvSCSI.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Storage/DrvSCSI.cpp	(revision 28258)
@@ -697,6 +697,6 @@
 
     /* Create I/O thread. */
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsiAsyncIOLoop,
-                                  drvscsiAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsiAsyncIOLoop,
+                               drvscsiAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
     AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n"), rc);
 
Index: trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Storage/DrvSCSIHost.cpp	(revision 28258)
@@ -484,6 +484,6 @@
 
     /* Create I/O thread. */
-    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsihostAsyncIOLoop,
-                                  drvscsihostAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
+    rc = PDMDrvHlpThreadCreate(pDrvIns, &pThis->pAsyncIOThread, pThis, drvscsihostAsyncIOLoop,
+                               drvscsihostAsyncIOLoopWakeup, 0, RTTHREADTYPE_IO, "SCSI async IO");
     AssertMsgReturn(RT_SUCCESS(rc), ("Failed to create async I/O thread rc=%Rrc\n"), rc);
 
Index: trunk/src/VBox/Devices/Storage/DrvVD.cpp
===================================================================
--- trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 28257)
+++ trunk/src/VBox/Devices/Storage/DrvVD.cpp	(revision 28258)
@@ -344,6 +344,6 @@
         if (RT_SUCCESS(rc))
         {
-            rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pThis->pDrvIns, &pStorageBackend->pTemplate,
-                                                           drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
+            rc = PDMDrvHlpAsyncCompletionTemplateCreate(pThis->pDrvIns, &pStorageBackend->pTemplate,
+                                                        drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
             if (RT_SUCCESS(rc))
             {
Index: trunk/src/VBox/VMM/PDM.cpp
===================================================================
--- trunk/src/VBox/VMM/PDM.cpp	(revision 28257)
+++ trunk/src/VBox/VMM/PDM.cpp	(revision 28258)
@@ -307,6 +307,7 @@
     AssertCompile(sizeof(pUVM->pdm.s) <= sizeof(pUVM->pdm.padding));
     AssertRelease(sizeof(pUVM->pdm.s) <= sizeof(pUVM->pdm.padding));
-    pUVM->pdm.s.pModules = NULL;
-    return VINF_SUCCESS;
+    pUVM->pdm.s.pModules   = NULL;
+    pUVM->pdm.s.pCritSects = NULL;
+    return RTCritSectInit(&pUVM->pdm.s.ListCritSect);
 }
 
@@ -337,7 +338,5 @@
      * Initialize sub compontents.
      */
-    int rc = RTCritSectInit(&pVM->pdm.s.MiscCritSect);
-    if (RT_SUCCESS(rc))
-        rc = pdmR3CritSectInit(pVM);
+    int rc = pdmR3CritSectInitStats(pVM);
     if (RT_SUCCESS(rc))
         rc = PDMR3CritSectInit(pVM, &pVM->pdm.s.CritSect, RT_SRC_POS, "PDM");
@@ -649,4 +648,7 @@
      */
     pdmR3LdrTermU(pUVM);
+
+    Assert(pUVM->pdm.s.pCritSects == NULL);
+    RTCritSectDelete(&pUVM->pdm.s.ListCritSect);
 }
 
Index: trunk/src/VBox/VMM/PDMCritSect.cpp
===================================================================
--- trunk/src/VBox/VMM/PDMCritSect.cpp	(revision 28257)
+++ trunk/src/VBox/VMM/PDMCritSect.cpp	(revision 28258)
@@ -29,4 +29,5 @@
 #include <VBox/mm.h>
 #include <VBox/vm.h>
+#include <VBox/uvm.h>
 
 #include <VBox/err.h>
@@ -43,17 +44,15 @@
 *   Internal Functions                                                         *
 *******************************************************************************/
-static int pdmR3CritSectDeleteOne(PVM pVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal);
-
-
-
-/**
- * Initializes the critical section subcomponent.
+static int pdmR3CritSectDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal);
+
+
+
+/**
+ * Register statistics related to the critical sections.
  *
  * @returns VBox status code.
  * @param   pVM         The VM handle.
- * @remark  Not to be confused with PDMR3CritSectInit and pdmR3CritSectInitDevice which are
- *          for initializing a critical section.
- */
-int pdmR3CritSectInit(PVM pVM)
+ */
+int pdmR3CritSectInitStats(PVM pVM)
 {
     STAM_REG(pVM, &pVM->pdm.s.StatQueuedCritSectLeaves, STAMTYPE_COUNTER, "/PDM/QueuedCritSectLeaves", STAMUNIT_OCCURENCES,
@@ -70,10 +69,13 @@
 void pdmR3CritSectRelocate(PVM pVM)
 {
-    RTCritSectEnter(&pVM->pdm.s.MiscCritSect);
-    for (PPDMCRITSECTINT pCur = pVM->pdm.s.pCritSects;
+    PUVM pUVM = pVM->pUVM;
+    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
+
+    for (PPDMCRITSECTINT pCur = pUVM->pdm.s.pCritSects;
          pCur;
          pCur = pCur->pNext)
         pCur->pVMRC = pVM->pVMRC;
-    RTCritSectLeave(&pVM->pdm.s.MiscCritSect);
+
+    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
 }
 
@@ -82,27 +84,32 @@
  * Deletes all remaining critical sections.
  *
- * This is called at the end of the termination process.
+ * This is called at the very end of the termination process.  It is also called
+ * at the end of vmR3CreateU failure cleanup, which may cause it to be called
+ * twice depending on hwere vmR3CreateU actually failed.  We have to do the
+ * latter call because other components expect the critical sections to be
+ * automatically deleted.
  *
  * @returns VBox status.
  *          First error code, rest is lost.
- * @param   pVM         The VM handle.
+ * @param   pVMU        The user mode VM handle.
  * @remark  Don't confuse this with PDMR3CritSectDelete.
  */
 VMMDECL(int) PDMR3CritSectTerm(PVM pVM)
 {
-    int rc = VINF_SUCCESS;
-    RTCritSectEnter(&pVM->pdm.s.MiscCritSect);
-    while (pVM->pdm.s.pCritSects)
-    {
-        int rc2 = pdmR3CritSectDeleteOne(pVM, pVM->pdm.s.pCritSects, NULL, true /* final */);
+    PUVM    pUVM = pVM->pUVM;
+    int     rc   = VINF_SUCCESS;
+    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
+
+    while (pUVM->pdm.s.pCritSects)
+    {
+        int rc2 = pdmR3CritSectDeleteOne(pVM, pUVM, pUVM->pdm.s.pCritSects, NULL, true /* final */);
         AssertRC(rc2);
         if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
             rc = rc2;
     }
-    RTCritSectLeave(&pVM->pdm.s.MiscCritSect);
-    RTCritSectDelete(&pVM->pdm.s.MiscCritSect);
+
+    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     return rc;
 }
-
 
 
@@ -162,7 +169,7 @@
                 pCritSect->pvKey                     = pvKey;
                 pCritSect->EventToSignal             = NIL_RTSEMEVENT;
-                pCritSect->pNext                     = pVM->pdm.s.pCritSects;
+                pCritSect->pNext                     = pVM->pUVM->pdm.s.pCritSects;
                 pCritSect->pszName                   = pszName;
-                pVM->pdm.s.pCritSects = pCritSect;
+                pVM->pUVM->pdm.s.pCritSects = pCritSect;
                 STAMR3RegisterF(pVM, &pCritSect->StatContentionRZLock,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZLock", pCritSect->pszName);
                 STAMR3RegisterF(pVM, &pCritSect->StatContentionRZUnlock,STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,          NULL, "/PDM/CritSects/%s/ContentionRZUnlock", pCritSect->pszName);
@@ -215,5 +222,5 @@
 
 /**
- * Initializes a PDM critical section.
+ * Initializes a PDM critical section for a device.
  *
  * The PDM critical sections are derived from the IPRT critical sections, but
@@ -224,5 +231,5 @@
  * @param   pDevIns         Device instance.
  * @param   pCritSect       Pointer to the critical section.
- * @param   pszNameFmt      Format string for namging the critical section.  For
+ * @param   pszNameFmt      Format string for naming the critical section.  For
  *                          statistics and lock validation.
  * @param   va              Arguments for the format string.
@@ -232,4 +239,26 @@
 {
     return pdmR3CritSectInitOne(pVM, &pCritSect->s, pDevIns, RT_SRC_POS_ARGS, pszNameFmt, va);
+}
+
+
+/**
+ * Initializes a PDM critical section for a driver.
+ *
+ * @returns VBox status code.
+ * @param   pVM             The VM handle.
+ * @param   pDrvIns         Driver instance.
+ * @param   pCritSect       Pointer to the critical section.
+ * @param   pszNameFmt      Format string for naming the critical section.  For
+ *                          statistics and lock validation.
+ * @param   ...             Arguments for the format string.
+ */
+int pdmR3CritSectInitDriver(PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL,
+                            const char *pszNameFmt, ...)
+{
+    va_list va;
+    va_start(va, pszNameFmt);
+    int rc = pdmR3CritSectInitOne(pVM, &pCritSect->s, pDrvIns, RT_SRC_POS_ARGS, pszNameFmt, va);
+    va_end(va);
+    return rc;
 }
 
@@ -245,7 +274,7 @@
  * @param   fFinal      Set if this is the final call and statistics shouldn't be deregistered.
  *
- * @remarks Caller must've entered the MiscCritSect.
- */
-static int pdmR3CritSectDeleteOne(PVM pVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal)
+ * @remarks Caller must've entered the ListCritSect.
+ */
+static int pdmR3CritSectDeleteOne(PVM pVM, PUVM pUVM, PPDMCRITSECTINT pCritSect, PPDMCRITSECTINT pPrev, bool fFinal)
 {
     /*
@@ -256,5 +285,5 @@
     Assert(pCritSect->Core.cLockers == -1);
     Assert(pCritSect->Core.NativeThreadOwner == NIL_RTNATIVETHREAD);
-    Assert(RTCritSectIsOwner(&pVM->pdm.s.MiscCritSect));
+    Assert(RTCritSectIsOwner(&pUVM->pdm.s.ListCritSect));
 
     /*
@@ -264,5 +293,5 @@
         pPrev->pNext = pCritSect->pNext;
     else
-        pVM->pdm.s.pCritSects = pCritSect->pNext;
+        pUVM->pdm.s.pCritSects = pCritSect->pNext;
 
     /*
@@ -314,13 +343,14 @@
      * Iterate the list and match key.
      */
+    PUVM            pUVM  = pVM->pUVM;
     int             rc    = VINF_SUCCESS;
     PPDMCRITSECTINT pPrev = NULL;
-    RTCritSectEnter(&pVM->pdm.s.MiscCritSect);
-    PPDMCRITSECTINT pCur  = pVM->pdm.s.pCritSects;
+    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
+    PPDMCRITSECTINT pCur  = pUVM->pdm.s.pCritSects;
     while (pCur)
     {
         if (pCur->pvKey == pvKey)
         {
-            int rc2 = pdmR3CritSectDeleteOne(pVM, pCur, pPrev, false /* not final */);
+            int rc2 = pdmR3CritSectDeleteOne(pVM, pUVM, pCur, pPrev, false /* not final */);
             AssertRC(rc2);
             if (RT_FAILURE(rc2) && RT_SUCCESS(rc))
@@ -332,5 +362,5 @@
         pCur = pCur->pNext;
     }
-    RTCritSectLeave(&pVM->pdm.s.MiscCritSect);
+    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     return rc;
 }
@@ -351,4 +381,17 @@
 
 /**
+ * Deletes all undeleted critical sections initalized by a given driver.
+ *
+ * @returns VBox status code.
+ * @param   pVM         The VM handle.
+ * @param   pDrvIns     The driver handle.
+ */
+int pdmR3CritSectDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns)
+{
+    return pdmR3CritSectDeleteByKey(pVM, pDrvIns);
+}
+
+
+/**
  * Deletes the critical section.
  *
@@ -365,14 +408,15 @@
      */
     PVM             pVM   = pCritSect->s.pVMR3;
+    PUVM            pUVM  = pVM->pUVM;
     AssertReleaseReturn(pVM, VERR_INTERNAL_ERROR);
     PPDMCRITSECTINT pPrev = NULL;
-    RTCritSectEnter(&pVM->pdm.s.MiscCritSect);
-    PPDMCRITSECTINT pCur  = pVM->pdm.s.pCritSects;
+    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
+    PPDMCRITSECTINT pCur  = pUVM->pdm.s.pCritSects;
     while (pCur)
     {
         if (pCur == &pCritSect->s)
         {
-            int rc = pdmR3CritSectDeleteOne(pVM, pCur, pPrev, false /* not final */);
-            RTCritSectLeave(&pVM->pdm.s.MiscCritSect);
+            int rc = pdmR3CritSectDeleteOne(pVM, pUVM, pCur, pPrev, false /* not final */);
+            RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
             return rc;
         }
@@ -382,5 +426,5 @@
         pCur = pCur->pNext;
     }
-    RTCritSectLeave(&pVM->pdm.s.MiscCritSect);
+    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
     AssertReleaseMsgFailed(("pCritSect=%p wasn't found!\n", pCritSect));
     return VERR_INTERNAL_ERROR;
@@ -519,5 +563,5 @@
     RTNATIVETHREAD const    hNativeThread = RTThreadNativeSelf();
     uint32_t                cCritSects = 0;
-    for (PPDMCRITSECTINT pCur = pVM->pdm.s.pCritSects;
+    for (PPDMCRITSECTINT pCur = pVM->pUVM->pdm.s.pCritSects;
          pCur;
          pCur = pCur->pNext)
@@ -583,7 +627,8 @@
 {
     RTNATIVETHREAD const hNativeSelf = RTThreadNativeSelf();
-
-    RTCritSectEnter(&pVM->pdm.s.MiscCritSect);
-    for (PPDMCRITSECTINT pCur = pVM->pdm.s.pCritSects;
+    PUVM                 pUVM        = pVM->pUVM;
+
+    RTCritSectEnter(&pUVM->pdm.s.ListCritSect);
+    for (PPDMCRITSECTINT pCur = pUVM->pdm.s.pCritSects;
          pCur;
          pCur = pCur->pNext)
@@ -593,5 +638,5 @@
             PDMCritSectLeave((PPDMCRITSECT)pCur);
     }
-    RTCritSectLeave(&pVM->pdm.s.MiscCritSect);
-}
-
+    RTCritSectLeave(&pUVM->pdm.s.ListCritSect);
+}
+
Index: trunk/src/VBox/VMM/PDMDriver.cpp
===================================================================
--- trunk/src/VBox/VMM/PDMDriver.cpp	(revision 28257)
+++ trunk/src/VBox/VMM/PDMDriver.cpp	(revision 28258)
@@ -5,5 +5,5 @@
 
 /*
- * Copyright (C) 2006-2007 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2010 Sun Microsystems, Inc.
  *
  * This file is part of VirtualBox Open Source Edition (OSE), as
@@ -654,4 +654,8 @@
         AssertRC(rc);
 
+        /* PDM critsects. */
+        rc = pdmR3CritSectDeleteDriver(pVM, pCur);
+        AssertRC(rc);
+
         /* Finally, the driver it self. */
         bool fHyperHeap = pCur->Internal.s.fHyperHeap;
@@ -925,7 +929,7 @@
 
 
-/** @interface_method_impl{PDMDRVHLP,pfnPDMQueueCreate} */
-static DECLCALLBACK(int) pdmR3DrvHlp_PDMQueueCreate(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
-                                                    PFNPDMQUEUEDRV pfnCallback, const char *pszName, PPDMQUEUE *ppQueue)
+/** @interface_method_impl{PDMDRVHLP,pfnQueueCreate} */
+static DECLCALLBACK(int) pdmR3DrvHlp_QueueCreate(PPDMDRVINS pDrvIns, uint32_t cbItem, uint32_t cItems, uint32_t cMilliesInterval,
+                                                 PFNPDMQUEUEDRV pfnCallback, const char *pszName, PPDMQUEUE *ppQueue)
 {
     PDMDRV_ASSERT_DRVINS(pDrvIns);
@@ -1164,16 +1168,16 @@
 
 
-/** @interface_method_impl{PDMDRVHLP,pfnPDMThreadCreate} */
-static DECLCALLBACK(int) pdmR3DrvHlp_PDMThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
-                                                     PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
-{
-    PDMDRV_ASSERT_DRVINS(pDrvIns);
-    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
-    LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
+/** @interface_method_impl{PDMDRVHLP,pfnThreadCreate} */
+static DECLCALLBACK(int) pdmR3DrvHlp_ThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
+                                                  PFNPDMTHREADWAKEUPDRV pfnWakeup, size_t cbStack, RTTHREADTYPE enmType, const char *pszName)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
+    LogFlow(("pdmR3DrvHlp_ThreadCreate: caller='%s'/%d: ppThread=%p pvUser=%p pfnThread=%p pfnWakeup=%p cbStack=%#zx enmType=%d pszName=%p:{%s}\n",
              pDrvIns->pReg->szName, pDrvIns->iInstance, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName, pszName));
 
     int rc = pdmR3ThreadCreateDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, ppThread, pvUser, pfnThread, pfnWakeup, cbStack, enmType, pszName);
 
-    LogFlow(("pdmR3DrvHlp_PDMThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDrvIns->pReg->szName, pDrvIns->iInstance,
+    LogFlow(("pdmR3DrvHlp_ThreadCreate: caller='%s'/%d: returns %Rrc *ppThread=%RTthrd\n", pDrvIns->pReg->szName, pDrvIns->iInstance,
             rc, *ppThread));
     return rc;
@@ -1181,17 +1185,17 @@
 
 
-/** @interface_method_impl{PDMDRVHLP,pfnPDMAsyncCompletionTemplateCreate} */
-static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
-                                                                      PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser,
-                                                                      const char *pszDesc)
-{
-    PDMDRV_ASSERT_DRVINS(pDrvIns);
-    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
-    LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: ppTemplate=%p pfnCompleted=%p pszDesc=%p:{%s}\n",
+/** @interface_method_impl{PDMDRVHLP,pfnAsyncCompletionTemplateCreate} */
+static DECLCALLBACK(int) pdmR3DrvHlp_AsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
+                                                                   PFNPDMASYNCCOMPLETEDRV pfnCompleted, void *pvTemplateUser,
+                                                                   const char *pszDesc)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
+    LogFlow(("pdmR3DrvHlp_AsyncCompletionTemplateCreate: caller='%s'/%d: ppTemplate=%p pfnCompleted=%p pszDesc=%p:{%s}\n",
              pDrvIns->pReg->szName, pDrvIns->iInstance, ppTemplate, pfnCompleted, pszDesc, pszDesc));
 
     int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVMR3, pDrvIns, ppTemplate, pfnCompleted, pvTemplateUser, pszDesc);
 
-    LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Rrc *ppThread=%p\n", pDrvIns->pReg->szName,
+    LogFlow(("pdmR3DrvHlp_AsyncCompletionTemplateCreate: caller='%s'/%d: returns %Rrc *ppThread=%p\n", pDrvIns->pReg->szName,
              pDrvIns->iInstance, rc, *ppTemplate));
     return rc;
@@ -1199,11 +1203,11 @@
 
 
-/** @interface_method_impl{PDMDRVHLP,pfnPDMLdrGetRCInterfaceSymbols} */
-static DECLCALLBACK(int) pdmR3DrvHlp_PDMLdrGetRCInterfaceSymbols(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
-                                                                 const char *pszSymPrefix, const char *pszSymList)
-{
-    PDMDRV_ASSERT_DRVINS(pDrvIns);
-    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
-    LogFlow(("pdmR3DrvHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
+/** @interface_method_impl{PDMDRVHLP,pfnLdrGetRCInterfaceSymbols} */
+static DECLCALLBACK(int) pdmR3DrvHlp_LdrGetRCInterfaceSymbols(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
+                                                              const char *pszSymPrefix, const char *pszSymList)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
+    LogFlow(("pdmR3DrvHlp_LdrGetRCInterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
              pDrvIns->pReg->szName, pDrvIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
 
@@ -1229,5 +1233,5 @@
     }
 
-    LogFlow(("pdmR3DrvHlp_PDMLdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
+    LogFlow(("pdmR3DrvHlp_LdrGetRCInterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
              pDrvIns->iInstance, rc));
     return rc;
@@ -1235,11 +1239,11 @@
 
 
-/** @interface_method_impl{PDMDRVHLP,pfnPDMLdrGetR0InterfaceSymbols} */
-static DECLCALLBACK(int) pdmR3DrvHlp_PDMLdrGetR0InterfaceSymbols(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
-                                                                 const char *pszSymPrefix, const char *pszSymList)
-{
-    PDMDRV_ASSERT_DRVINS(pDrvIns);
-    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
-    LogFlow(("pdmR3DrvHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
+/** @interface_method_impl{PDMDRVHLP,pfnLdrGetR0InterfaceSymbols} */
+static DECLCALLBACK(int) pdmR3DrvHlp_LdrGetR0InterfaceSymbols(PPDMDRVINS pDrvIns, void *pvInterface, size_t cbInterface,
+                                                              const char *pszSymPrefix, const char *pszSymList)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    VM_ASSERT_EMT(pDrvIns->Internal.s.pVMR3);
+    LogFlow(("pdmR3DrvHlp_LdrGetR0InterfaceSymbols: caller='%s'/%d: pvInterface=%p cbInterface=%zu pszSymPrefix=%p:{%s} pszSymList=%p:{%s}\n",
              pDrvIns->pReg->szName, pDrvIns->iInstance, pvInterface, cbInterface, pszSymPrefix, pszSymPrefix, pszSymList, pszSymList));
 
@@ -1265,5 +1269,23 @@
     }
 
-    LogFlow(("pdmR3DrvHlp_PDMLdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
+    LogFlow(("pdmR3DrvHlp_LdrGetR0InterfaceSymbols: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
+             pDrvIns->iInstance, rc));
+    return rc;
+}
+
+
+/** @interface_method_impl{PDMDRVHLP,pfnCritSectInit} */
+static DECLCALLBACK(int) pdmR3DrvHlp_CritSectInit(PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect,
+                                                  RT_SRC_POS_DECL, const char *pszName)
+{
+    PDMDRV_ASSERT_DRVINS(pDrvIns);
+    PVM pVM = pDrvIns->Internal.s.pVMR3;
+    VM_ASSERT_EMT(pVM);
+    LogFlow(("pdmR3DrvHlp_CritSectInit: caller='%s'/%d: pCritSect=%p pszName=%s\n",
+             pDrvIns->pReg->szName, pDrvIns->iInstance, pCritSect, pszName));
+
+    int rc = pdmR3CritSectInitDriver(pVM, pDrvIns, pCritSect, RT_SRC_POS_ARGS, "%s_%u", pszName, pDrvIns->iInstance);
+
+    LogFlow(("pdmR3DrvHlp_CritSectInit: caller='%s'/%d: returns %Rrc\n", pDrvIns->pReg->szName,
              pDrvIns->iInstance, rc));
     return rc;
@@ -1289,5 +1311,5 @@
     pdmR3DrvHlp_VMState,
     pdmR3DrvHlp_VMTeleportedAndNotFullyResumedYet,
-    pdmR3DrvHlp_PDMQueueCreate,
+    pdmR3DrvHlp_QueueCreate,
     pdmR3DrvHlp_TMGetVirtualFreq,
     pdmR3DrvHlp_TMGetVirtualTime,
@@ -1303,8 +1325,9 @@
     pdmR3DrvHlp_SetAsyncNotification,
     pdmR3DrvHlp_AsyncNotificationCompleted,
-    pdmR3DrvHlp_PDMThreadCreate,
-    pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate,
-    pdmR3DrvHlp_PDMLdrGetRCInterfaceSymbols,
-    pdmR3DrvHlp_PDMLdrGetR0InterfaceSymbols,
+    pdmR3DrvHlp_ThreadCreate,
+    pdmR3DrvHlp_AsyncCompletionTemplateCreate,
+    pdmR3DrvHlp_LdrGetRCInterfaceSymbols,
+    pdmR3DrvHlp_LdrGetR0InterfaceSymbols,
+    pdmR3DrvHlp_CritSectInit,
     PDM_DRVHLPR3_VERSION /* u32TheEnd */
 };
Index: trunk/src/VBox/VMM/PDMInternal.h
===================================================================
--- trunk/src/VBox/VMM/PDMInternal.h	(revision 28257)
+++ trunk/src/VBox/VMM/PDMInternal.h	(revision 28258)
@@ -940,6 +940,4 @@
     /** List of registered drivers. (FIFO) */
     R3PTRTYPE(PPDMDRV)              pDrvs;
-    /** List of initialized critical sections. (LIFO) */
-    R3PTRTYPE(PPDMCRITSECTINT)      pCritSects;
     /** PCI Buses. */
     PDMPCIBUS                       aPciBuses[PDM_PCI_BUSSES_MAX];
@@ -965,4 +963,7 @@
     RTRCPTR                         uPadding1; /**< Alignment padding. */
 
+/** @name Move to PDMUSERPERVM
+ * @{
+ */
     /** Linked list of timer driven PDM queues. */
     R3PTRTYPE(struct PDMQUEUE *)    pQueuesTimer;
@@ -983,6 +984,8 @@
     /** Tail of the PDM Thread list. (singly linked) */
     R3PTRTYPE(PPDMTHREAD)           pThreadsTail;
+/** @}  */
 
     /** @name   PDM Async Completion
+     * @todo Move to PDMUSERPERVM
      * @{ */
     /** Pointer to the array of supported endpoint classes. */
@@ -1012,9 +1015,4 @@
      * the PIC, APIC, IOAPIC and PCI devices pluss some PDM functions. */
     PDMCRITSECT                     CritSect;
-    /** The PDM miscellancous lock.
-     * This is used to protect things like critsect init/delete that formerly was
-     * serialized by there only being one EMT.
-     */
-    RTCRITSECT                      MiscCritSect;
 
     /** Number of times a critical section leave requesed needed to be queued for ring-3 execution. */
@@ -1033,7 +1031,13 @@
 typedef struct PDMUSERPERVM
 {
+    /** @todo move more stuff over here. */
+
+    /** Lock protecting the lists below it. */
+    RTCRITSECT                      ListCritSect;
     /** Pointer to list of loaded modules. */
     PPDMMOD                         pModules;
-    /** @todo move more stuff over here. */
+    /** List of initialized critical sections. (LIFO) */
+    R3PTRTYPE(PPDMCRITSECTINT)      pCritSects;
+
 } PDMUSERPERVM;
 /** Pointer to the PDM data kept in the UVM. */
@@ -1095,9 +1099,10 @@
 *******************************************************************************/
 #ifdef IN_RING3
-int         pdmR3CritSectInit(PVM pVM);
-int         pdmR3CritSectTerm(PVM pVM);
+int         pdmR3CritSectInitStats(PVM pVM);
 void        pdmR3CritSectRelocate(PVM pVM);
 int         pdmR3CritSectInitDevice(PVM pVM, PPDMDEVINS pDevIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, va_list va);
 int         pdmR3CritSectDeleteDevice(PVM pVM, PPDMDEVINS pDevIns);
+int         pdmR3CritSectInitDriver(PVM pVM, PPDMDRVINS pDrvIns, PPDMCRITSECT pCritSect, RT_SRC_POS_DECL, const char *pszNameFmt, ...);
+int         pdmR3CritSectDeleteDriver(PVM pVM, PPDMDRVINS pDrvIns);
 
 int         pdmR3DevInit(PVM pVM);
Index: trunk/src/VBox/VMM/VM.cpp
===================================================================
--- trunk/src/VBox/VMM/VM.cpp	(revision 28257)
+++ trunk/src/VBox/VMM/VM.cpp	(revision 28258)
@@ -707,4 +707,10 @@
             AssertRC(rc2);
         }
+
+        /*
+         * Do automatic cleanups while the VM structure is still alive and all
+         * references to it are still working.
+         */
+        PDMR3CritSectTerm(pVM);
 
         /*
Index: trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp
===================================================================
--- trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp	(revision 28257)
+++ trunk/src/VBox/VMM/testcase/tstVMStructRC.cpp	(revision 28258)
@@ -274,5 +274,4 @@
     GEN_CHECK_OFF(PDM, pUsbInstances);
     GEN_CHECK_OFF(PDM, pDrvs);
-    GEN_CHECK_OFF(PDM, pCritSects);
     GEN_CHECK_OFF(PDM, aPciBuses);
     GEN_CHECK_OFF(PDM, aPciBuses[0].iBus);
