Index: /trunk/src/VBox/Devices/Network/DevPCNet.cpp
===================================================================
--- /trunk/src/VBox/Devices/Network/DevPCNet.cpp	(revision 591)
+++ /trunk/src/VBox/Devices/Network/DevPCNet.cpp	(revision 592)
@@ -69,5 +69,5 @@
 #ifdef IN_RING3
 #include <iprt/mem.h>
-#include <iprt/semaphore.h>
+#include <iprt/req.h>
 #endif
 
@@ -231,5 +231,5 @@
 #ifdef PCNET_ASYNC_SEND
     /** Async send thread */
-    RTSEMEVENT                          hEventSemSend;
+    PRTREQQUEUE                         pSendQueue;
     RTTHREAD                            hSendThread;
 #endif
@@ -296,8 +296,4 @@
     STAMCOUNTER                         StatRingWriteOutsideRangeR0;
     STAMCOUNTER                         StatRingWriteOutsideRangeGC;
-# endif
-# ifdef PCNET_ASYNC_SEND
-    STAMCOUNTER                         StatSyncSend;
-    STAMCOUNTER                         StatAsyncSend;
 # endif
 #endif /* VBOX_WITH_STATISTICS */
@@ -1787,4 +1783,17 @@
 
 #ifdef IN_RING3
+
+# ifdef PCNET_ASYNC_SEND
+/**
+ *  Send packet to the network driver.
+ */
+DECLCALLBACK(void) pcnetSendAsyncPacket(PCNetState *pData, const void *pvBuf, unsigned cb)
+{
+    Assert(pData && pData->pDrv && pData->pDrv->pfnSend);
+
+    pData->pDrv->pfnSend(pData->pDrv, pvBuf, cb);
+}
+# endif
+
 /**
  * Transmit queue consumer
@@ -1801,18 +1810,4 @@
     int         rc;
 
-#ifdef PCNET_ASYNC_SEND
-    /* If the calling threads isn't the async send thread and our queue isn't yet full, then kick off async sending. */
-    if (    pData->iFrame  != ELEMENTS(pData->aFrames)
-        &&  RTThreadSelf() != pData->hSendThread)
-    {
-        STAM_COUNTER_INC(&pData->StatAsyncSend);
-        rc = RTSemEventSignal(pData->hEventSemSend);
-        AssertRC(rc);
-        return VINF_SUCCESS;
-    }
-    if (RTThreadSelf() != pData->hSendThread)
-        STAM_COUNTER_INC(&pData->StatSyncSend);
-#endif /* PCNET_ASYNC_SEND */
-
     STAM_PROFILE_START(&pData->StatXmitQueue, a);
     STAM_COUNTER_INC(&pData->aStatFlushCounts[pData->iFrame]);
@@ -1832,5 +1827,14 @@
         if (pcnetIsLinkUp(pData))
         {
+#ifdef PCNET_ASYNC_SEND
+
+            /** @note we make a copy here as we don't wish to have to enter the critical section in the async send thread during the lengthy send process. */
+            uint8_t *pPacket = RTMemTmpAlloc(pData->aFrames[i].cb);
+            memcpy(pPacket, pv, pData->aFrames[i].cb);
+            rc = RTReqCallEx(pData->pSendQueue, NULL, 0, RTREQFLAGS_NO_WAIT, pcnetSendAsyncPacket, pData, pPacket, (unsigned)pData->aFrames[i].cb);
+            AssertRC(rc);
+#else
             pData->pDrv->pfnSend(pData->pDrv, pv, pData->aFrames[i].cb);
+#endif /* PCNET_ASYNC_SEND */
             LOG_PACKET("xmit", pv, pData->aFrames[i].cb);
         }
@@ -1868,13 +1872,10 @@
 {
     PCNetState *pData = (PCNetState *)pvUser;
-    RTSEMEVENT  hEventSemSend = pData->hEventSemSend;
 
     while(1)
     {
-        int rc = RTSemEventWait(pData->hEventSemSend, RT_INDEFINITE_WAIT);
+        int rc = RTReqProcess(pQueue);
         if (VBOX_FAILURE(rc))
             break;
-
-        pcnetXmitQueueConsumer(PCNETSTATE_2_DEVINS(pData), NULL);
     }
     return VINF_SUCCESS;
@@ -3944,4 +3945,8 @@
 {
     PCNetState *pData = PDMINS2DATA(pDevIns, PCNetState *);
+#ifdef PCNET_ASYNC_SEND
+    if (pData->pSendQueue)
+        RTReqDestroyQueue(pData->pSendQueue);
+#endif
     PDMR3CritSectDelete(&pData->CritSect);
     return VINF_SUCCESS;
@@ -4203,6 +4208,6 @@
 
 #ifdef PCNET_ASYNC_SEND
-    /* Create event semaphore for the async send thread. */
-    rc = RTSemEventCreate(&pData->hEventSemSend);
+    /* Create send queue for the async send thread. */
+    rc = RTReqCreateQueue(&pData->pSendQueue);
     AssertRC(rc);
 
@@ -4211,8 +4216,5 @@
     AssertRC(rc);
 
-    Assert(pData->hSendThread != NIL_RTTHREAD && pData->hEventSemSend != NIL_RTSEMEVENT);
-
-    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatAsyncSend,          STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of async send operations",        "/Devices/PCNet%d/Send/Async", iInstance);
-    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatSyncSend,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of sync send operations",         "/Devices/PCNet%d/Send/Sync", iInstance);
+    Assert(pData->hSendThread != NIL_RTTHREAD && pData->pSendQueue);
 #endif
 
