Index: trunk/src/VBox/Devices/Network/DrvNAT.cpp
===================================================================
--- trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 16303)
+++ trunk/src/VBox/Devices/Network/DrvNAT.cpp	(revision 16443)
@@ -53,5 +53,5 @@
  *        activity. This needs to be fixed properly.
  */
-#define VBOX_NAT_DELAY_HACK
+/*#define VBOX_NAT_DELAY_HACK*/
 
 
@@ -148,5 +148,5 @@
     Log2(("drvNATSend: pvBuf=%p cb=%#x\n%.*Rhxd\n", pvBuf, cb, cb, pvBuf));
 
-#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
+#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC 
 
     PRTREQ pReq = NULL;
@@ -155,5 +155,9 @@
     if (pThis->pThread->enmState != PDMTHREADSTATE_RUNNING)
         return VINF_SUCCESS;
+#ifndef VBOX_WITH_SLIRP_MT
     rc = RTReqAlloc(pThis->pReqQueue, &pReq, RTREQTYPE_INTERNAL);
+#else
+    rc = RTReqAlloc((PRTREQQUEUE)slirp_get_queue(pThis->pNATState), &pReq, RTREQTYPE_INTERNAL);
+#endif
     AssertReleaseRC(rc);
     pReq->u.Internal.pfn      = (PFNRT)drvNATSendWorker;
@@ -163,4 +167,5 @@
     pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
     pReq->fFlags              = RTREQFLAGS_VOID;
+
     rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */
     if (RT_LIKELY(rc == VERR_TIMEOUT))
@@ -181,4 +186,7 @@
         AssertReleaseRC(rc);
     RTReqFree(pReq);
+
+    rc = WSASetEvent(pThis->hWakeupEvent);
+    AssertRelease(rc == TRUE);
 
 #else /* !VBOX_WITH_SIMPLIFIED_SLIRP_SYNC */
@@ -397,8 +405,10 @@
             /* only check for slow/fast timers */
             slirp_select_poll(pThis->pNATState, /* fTimeout=*/true, /*fIcmp=*/false);
+            Log2(("%s: timeout\n", __FUNCTION__));
             continue;
         }
 
         /* poll the sockets in any case */
+        Log2(("%s: poll\n", __FUNCTION__));
         slirp_select_poll(pThis->pNATState, /* fTimeout=*/false, /* fIcmp=*/(event == WSA_WAIT_EVENT_0));
         /* process _all_ outstanding requests but don't wait */
@@ -444,7 +454,11 @@
 {
     PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
-	while (1) 
+    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
+        return VINF_SUCCESS;
+    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
 	{
+        slirp_process_queue(pThis->pNATState);
 	}
+    return VINF_SUCCESS;
 }
 
Index: trunk/src/VBox/Devices/Network/slirp/debug.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/debug.c	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/debug.c	(revision 16443)
@@ -185,5 +185,5 @@
     char buff[256];
     int n;
-    struct socket *so;
+    struct socket *so, *so_next;
 
     lprint(" \n");
@@ -192,6 +192,6 @@
            "Proto[state]     Sock     Local Address, Port  Remote Address, Port RecvQ SendQ\n");
 
-    for (so = tcb.so_next; so != &tcb; so = so->so_next)
-    {
+    QSOCKET_FOREACH(so, so_next, tcp)
+    /* { */
         n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
         while (n < 17)
@@ -203,8 +203,9 @@
                 inet_ntoa(so->so_faddr), ntohs(so->so_fport),
                 so->so_rcv.sb_cc, so->so_snd.sb_cc);
+    LOOP_LABEL(tcp, so, so_next);
     }
 
-    for (so = udb.so_next; so != &udb; so = so->so_next)
-    {
+    QSOCKET_FOREACH(so, so_next, udp)
+    /* { */
         n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
         while (n < 17)
@@ -216,4 +217,5 @@
                 inet_ntoa(so->so_faddr), ntohs(so->so_fport),
                 so->so_rcv.sb_cc, so->so_snd.sb_cc);
+    LOOP_LABEL(udp, so, so_next);
     }
 }
@@ -248,5 +250,6 @@
 
     AssertReturn(strcmp(pszType, "natsock") == 0, 0);
-
+    if (so->so_state == SS_NOFDREF || so->s == -1) 
+        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "socket SS_NODREF");
     status = getsockname(so->s, &addr, &socklen);
 
@@ -257,5 +260,5 @@
             "state=%04x ip=" IP4_ADDR_PRINTF_FORMAT ":%d name=" IP4_ADDR_PRINTF_FORMAT ":%d",
             so->s, so->so_type, so->so_state, IP4_ADDR_PRINTF_DECOMP(ip), ntohs(so->so_fport),
-            IP4_ADDR_PRINTF_DECOMP(((struct sockaddr_in *)&addr)->sin_addr.s_addr),
+            IP4_ADDR_PRINTF_DECOMP(ntohl(((struct sockaddr_in *)&addr)->sin_addr.s_addr)),
             ntohs(((struct sockaddr_in *)&addr)->sin_port));
 }
Index: trunk/src/VBox/Devices/Network/slirp/libslirp.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/libslirp.h	(revision 16443)
@@ -89,4 +89,8 @@
 void slirp_register_external_event(PNATState pData, HANDLE hEvent, int index);
 #endif
+#ifdef VBOX_WITH_SLIRP_MT
+void slirp_process_queue(PNATState pData);
+void *slirp_get_queue(PNATState pData);
+#endif
 
 /*
Index: trunk/src/VBox/Devices/Network/slirp/slirp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/slirp.c	(revision 16443)
@@ -8,15 +8,4 @@
 #include <iprt/assert.h>
 
-#ifdef VBOX_WITH_SLIRP_MT
-# define CONTINUE(label) goto loop_end_ ## label ## _mt
-/* @todo replace queue parameter with macrodinition */
-# define LOOP_LABEL(label, so, sonext) loop_end_ ## label ## _mt:    \
-    SOCKET_UNLOCK(so);                                               \
-    QSOCKET_LOCK(_X(queue_ ## label ## _label));                     \
-    (so) = (sonext)
-#else
-#define CONTINUE(label) continue;
-# define LOOP_LABEL(label, so, sonext) /* empty*/
-#endif
 #if !defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) || !defined(RT_OS_WINDOWS)
 
@@ -387,4 +376,5 @@
 {
     int fNATfailed = 0;
+    int rc;
     PNATState pData = RTMemAlloc(sizeof(NATState));
     *ppData = pData;
@@ -409,4 +399,10 @@
     pData->phEvents[VBOX_SOCKET_EVENT_INDEX] = CreateEvent(NULL, FALSE, FALSE, NULL);
 # endif
+#endif
+#ifdef VBOX_WITH_SLIRP_MT
+    QSOCKET_LOCK_CREATE(tcb);
+    QSOCKET_LOCK_CREATE(udb);
+    rc = RTReqCreateQueue(&pData->pReqQueue);
+    AssertReleaseRC(rc);
 #endif
 
@@ -686,5 +682,4 @@
         QSOCKET_FOREACH(so, so_next, udp)
         /* { */
-            so_next = so->so_next;
 
             STAM_COUNTER_INC(&pData->StatUDP);
@@ -698,5 +693,5 @@
                 {
                     udp_detach(pData, so);
-                    CONTINUE(udp);
+                    CONTINUE_NO_UNLOCK(udp);
                 }
                 else
@@ -796,7 +791,6 @@
          * Check TCP sockets
          */
-        for (so = tcb.so_next; so != &tcb; so = so_next)
-        {
-            so_next = so->so_next;
+        QSOCKET_FOREACH(so, so_next, tcp)
+        /* { */
 
             /*
@@ -834,5 +828,5 @@
                 if (so->so_state & SS_FACCEPTCONN)
                 {
-                    tcp_connect(pData, so);
+                    TCP_CONNECT(pData, so);
 #if defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS)
                     if (!(NetworkEvents.lNetworkEvents & FD_CLOSE))
@@ -841,8 +835,8 @@
                 }
 
-                ret = soread(pData, so, /*fCloseIfNothingRead=*/false);
+                SOREAD(ret, pData, so, /*fCloseIfNothingRead=*/false);
                 /* Output it if we read something */
                 if (ret > 0)
-                    tcp_output(pData, sototcpcb(so));
+                    TCP_OUTPUT(pData, sototcpcb(so));
             }
 
@@ -858,7 +852,7 @@
                 for (;;)
                 {
-                    ret = soread(pData, so, /*fCloseIfNothingRead=*/true);
+                    SOREAD(ret, pData, so, /*fCloseIfNothingRead=*/true);
                     if (ret > 0)
-                        tcp_output(pData, sototcpcb(so));
+                        TCP_OUTPUT(pData, sototcpcb(so));
                     else
                         break;
@@ -907,9 +901,9 @@
                      * Continue tcp_input
                      */
-                    tcp_input(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
+                    TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
                     /* continue; */
                 }
                 else
-                    ret = sowrite(pData, so);
+                    SOWRITE(ret, pData, so);
                 /*
                  * XXX If we wrote something (a lot), there could be the need
@@ -964,5 +958,5 @@
 
                 }
-                tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
+                TCP_INPUT((struct mbuf *)NULL, sizeof(struct ip),so);
             } /* SS_ISFCONNECTING */
 #endif
@@ -975,8 +969,6 @@
          * Incoming UDP data isn't buffered either.
          */
-        for (so = udb.so_next; so != &udb; so = so_next)
-        {
-            so_next = so->so_next;
-
+         QSOCKET_FOREACH(so, so_next, udp)
+         /* { */
             POLL_UDP_EVENTS(rc, error, so, &NetworkEvents);
 
@@ -985,5 +977,5 @@
             if (so->s != -1 && CHECK_FD_SET(so, NetworkEvents, readfds))
             {
-                sorecvfrom(pData, so);
+                SORECVFROM(pData, so);
             }
             LOOP_LABEL(udp, so, so_next);
@@ -1290,2 +1282,12 @@
     m_free(pData, m);
 }
+#ifdef VBOX_WITH_SLIRP_MT
+void slirp_process_queue(PNATState pData)
+{
+     RTReqProcess(pData->pReqQueue, RT_INDEFINITE_WAIT);
+}
+void *slirp_get_queue(PNATState pData)
+{
+    return pData->pReqQueue;
+}
+#endif
Index: trunk/src/VBox/Devices/Network/slirp/slirp_state.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/slirp_state.h	(revision 16443)
@@ -21,4 +21,5 @@
 #ifndef _slirp_state_h_
 #define _slirp_state_h_
+#include <iprt/req.h>
 #include "ip_icmp.h"
 
@@ -100,4 +101,7 @@
     struct in_addr alias_addr;
     struct in_addr special_addr;
+#ifdef VBOX_WITH_SLIRP_MT
+    PRTREQQUEUE pReqQueue;
+#endif
 #ifndef VBOX_WITH_MULTI_DNS
     struct in_addr dns_addr;
@@ -116,5 +120,5 @@
     struct socket tcb;
 #ifdef VBOX_WITH_SLIRP_MT
-    RTSEMMUTEX      tcb_mutex;
+    RTCRITSECT      tcb_mutex;
 #endif
     struct socket *tcp_last_so;
@@ -134,5 +138,5 @@
     struct socket udb;
 #ifdef VBOX_WITH_SLIRP_MT
-    RTSEMMUTEX      udb_mutex;
+    RTCRITSECT      udb_mutex;
 #endif
     struct socket *udp_last_so;
@@ -277,24 +281,28 @@
 #define __X(x) x
 #define _X(x) __X(x)
-
+#define _str(x) #x
+#define str(x) _str(x)
 #ifdef VBOX_WITH_SLIRP_MT
 #define QSOCKET_LOCK(queue)                                                     \
 do {                                                                            \
-    int rc = RTSemMutexRequest(_X(queue) ## _mutex, RT_INDEFINITE_WAIT);        \
+    int rc;                                                                     \
+    rc = RTCritSectEnter(&_X(queue) ## _mutex);            \
     AssertReleaseRC(rc);                                                        \
 } while (0)
 #define QSOCKET_UNLOCK(queue)                           \
 do {                                                    \
-    int rc = RTSemMutexRelease(_X(queue) ## _mutex);    \
+    int rc;                                             \
+    rc = RTCritSectLeave(&_X(queue) ## _mutex);        \
     AssertReleaseRC(rc);                                \
 } while (0)
 #define QSOCKET_LOCK_CREATE(queue)                      \
 do {                                                    \
-    int rc = RTSemMutexCreate(&pData->queue ## _mutex); \
+    int rc;                                             \
+    rc = RTCritSectInit(&pData->queue ## _mutex);     \
     AssertReleaseRC(rc);                                \
 } while (0)
 #define QSOCKET_LOCK_DESTROY(queue)                     \
 do {                                                    \
-    int rc = RTSemMutexDestroy(pData->queue ## _mutex); \
+    int rc = RTCritSectDelete(&pData->queue ## _mutex); \
     AssertReleaseRC(rc);                                \
 } while (0)
@@ -303,5 +311,5 @@
         QSOCKET_LOCK(__X(queue_## label ## _label));                \
         (so) = (_X(queue_ ## label ## _label)).so_next;             \
-        SOCKET_LOCK((so));                                          \
+        if ((so) != &(_X(queue_## label ## _label))) SOCKET_LOCK((so));  \
         for(;;)                                                     \
         {                                                           \
@@ -311,4 +319,5 @@
                 break;                                              \
             }                                                       \
+            Log2(("%s:%d Processing so:%R[natsock]\n", __FUNCTION__, __LINE__, (so)));  \
             if ((so)->so_next != &(_X(queue_## label ## _label)))   \
             {                                                       \
@@ -317,4 +326,182 @@
             (sonext) = (so)->so_next;                               \
             QSOCKET_UNLOCK(__X(queue_## label ##_label)); 
+
+# define CONTINUE_NO_UNLOCK(label) goto loop_end_ ## label ## _mt_nounlock
+# define CONTINUE(label) goto loop_end_ ## label ## _mt
+/* @todo replace queue parameter with macrodinition */
+# define LOOP_LABEL(label, so, sonext) loop_end_ ## label ## _mt:       \
+    SOCKET_UNLOCK(so);                                                  \
+    loop_end_ ## label ## _mt_nounlock:                                 \
+    QSOCKET_LOCK(_X(queue_ ## label ## _label));                        \
+    (so) = (sonext)
+
+#define DO_TCP_OUTPUT(data, sotcb)                                      \
+do {                                                                    \
+    PRTREQ pReq = NULL;                                                 \
+    int rc;                                                             \
+    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
+    AssertReleaseRC(rc);                                                \
+    pReq->u.Internal.pfn      = (PFNRT)tcp_output;                      \
+    pReq->u.Internal.cArgs    = 2;                                      \
+    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
+    pReq->u.Internal.aArgs[1] = (uintptr_t)(sotcb);                     \
+    pReq->fFlags              = RTREQFLAGS_VOID;     \
+    rc = RTReqQueue(pReq, 0);                                           \
+    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
+    {                                                                   \
+        SOCKET_UNLOCK(so);                                               \
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
+        AssertReleaseRC(rc);                                            \
+        SOCKET_LOCK(so);                                                \
+        RTReqFree(pReq);                                                \
+    }                                                                   \
+    else                                                                \
+        AssertReleaseRC(rc);                                            \
+} while(0)
+
+#define DO_TCP_INPUT(data, mbuf, size, so)                              \
+do {                                                                    \
+    PRTREQ pReq = NULL;                                                 \
+    int rc;                                                             \
+    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
+    AssertReleaseRC(rc);                                                \
+    pReq->u.Internal.pfn      = (PFNRT)tcp_input;                       \
+    pReq->u.Internal.cArgs    = 4;                                      \
+    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
+    pReq->u.Internal.aArgs[1] = (uintptr_t)(mbuf);                      \
+    pReq->u.Internal.aArgs[2] = (uintptr_t)(size);                      \
+    pReq->u.Internal.aArgs[3] = (uintptr_t)(so);                        \
+    pReq->fFlags              = RTREQFLAGS_VOID;                        \
+    rc = RTReqQueue(pReq, 0);                                           \
+    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
+    {                                                                   \
+        SOCKET_UNLOCK(so);                                               \
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
+        AssertReleaseRC(rc);                                            \
+        SOCKET_LOCK(so);                                                \
+        RTReqFree(pReq);                                                \
+    }                                                                   \
+    else                                                                \
+        AssertReleaseRC(rc);                                            \
+} while(0)
+
+#define DO_TCP_CONNECT(data, so)                                        \
+do {                                                                    \
+    PRTREQ pReq = NULL;                                                 \
+    int rc;                                                             \
+    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
+    AssertReleaseRC(rc);                                                \
+    pReq->u.Internal.pfn      = (PFNRT)tcp_connect;                     \
+    pReq->u.Internal.cArgs    = 2;                                      \
+    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
+    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
+    pReq->fFlags              = RTREQFLAGS_VOID;                        \
+    rc = RTReqQueue(pReq, 0); /* don't wait, we have to release lock before*/ \
+    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
+    {                                                                   \
+        SOCKET_UNLOCK(so);                                               \
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
+        AssertReleaseRC(rc);                                            \
+        SOCKET_LOCK(so);                                                \
+        RTReqFree(pReq);                                                \
+    }                                                                   \
+    else                                                                \
+        AssertReleaseRC(rc);                                            \
+} while(0)
+
+#define DO_SOREAD(ret, data, so, ifclose)                               \
+do {                                                                    \
+    PRTREQ pReq = NULL;                                                 \
+    int rc;                                                             \
+    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
+    AssertReleaseRC(rc);                                                \
+    pReq->u.Internal.pfn      = (PFNRT)soread_queue;                    \
+    pReq->u.Internal.cArgs    = 4;                                      \
+    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
+    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
+    pReq->u.Internal.aArgs[2] = (uintptr_t)(ifclose);                   \
+    pReq->u.Internal.aArgs[3] = (uintptr_t)&(ret);                      \
+    pReq->fFlags              = RTREQFLAGS_VOID;                        \
+    rc = RTReqQueue(pReq, 0); /* don't wait, we have to release lock before*/ \
+    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
+    {                                                                   \
+        SOCKET_UNLOCK(so);                                               \
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
+        AssertReleaseRC(rc);                                            \
+        SOCKET_LOCK(so);                                                \
+        RTReqFree(pReq);                                                \
+    }                                                                   \
+    else                                                                \
+        AssertReleaseRC(rc);                                            \
+} while(0)
+
+#define DO_SOWRITE(ret, data, so)                                       \
+do {                                                                    \
+    PRTREQ pReq = NULL;                                                 \
+    int rc;                                                             \
+    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
+    AssertReleaseRC(rc);                                                \
+    pReq->u.Internal.pfn      = (PFNRT)sowrite;                         \
+    pReq->u.Internal.cArgs    = 2;                                      \
+    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
+    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
+    pReq->fFlags              = RTREQFLAGS_RETURN_MASK;                 \
+    rc = RTReqQueue(pReq, 0); /* don't wait, we have to release lock before*/ \
+    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
+    {                                                                   \
+        SOCKET_UNLOCK(so);                                              \
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
+        SOCKET_LOCK(so);                                                \
+        ret = pReq->iStatus;                                            \
+        RTReqFree(pReq);                                                \
+    }                                                                   \
+    else                                                                \
+        AssertReleaseRC(rc);                                            \
+} while(0)
+
+#define DO_SORECFROM(data, so)                                          \
+do {                                                                    \
+    PRTREQ pReq = NULL;                                                 \
+    int rc;                                                             \
+    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
+    AssertReleaseRC(rc);                                                \
+    pReq->u.Internal.pfn      = (PFNRT)sorecvfrom;                      \
+    pReq->u.Internal.cArgs    = 2;                                      \
+    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
+    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
+    pReq->fFlags              = RTREQFLAGS_VOID;                        \
+    rc = RTReqQueue(pReq, 0);                                           \
+    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
+    {                                                                   \
+        SOCKET_UNLOCK(so);                                               \
+        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
+        AssertReleaseRC(rc);                                            \
+        SOCKET_LOCK(so);                                                \
+        RTReqFree(pReq);                                                \
+    }                                                                   \
+    else                                                                \
+        AssertReleaseRC(rc);                                            \
+} while(0)
+
+#define SOLOOKUP(so, label, src, sport, dst, dport)                     \
+do {                                                                    \
+    struct socket *sonxt;                                               \
+    (so) = NULL;                                                        \
+    QSOCKET_FOREACH(so, sonxt, label)                                   \
+    /* { */                                                             \
+        if (   so->so_lport        == (sport)                           \
+            && so->so_laddr.s_addr == (src).s_addr                      \
+            && so->so_faddr.s_addr == (dst).s_addr                      \
+            && so->so_fport        == (dport))                          \
+            {                                                           \
+                if (sonxt != &__X(queue_ ## label ## _label))           \
+                    SOCKET_UNLOCK(sonxt);                               \
+                break; /*so is locked*/                                 \
+            }                                                           \
+        LOOP_LABEL(so, sonxt, label);                                   \
+        }                                                               \
+    }                                                                   \
+}while (0) 
+    
 #else
 #define QSOCKET_LOCK(queue) do {} while (0)
@@ -326,5 +513,24 @@
    {                                                                                                                \
             (sonext) = (so)->so_next;
-#endif
-
+# define CONTINUE(label) continue
+# define CONTINUE_NO_UNLOCK(label) continue
+# define LOOP_LABEL(label, so, sonext) /* empty*/
+#define DO_TCP_OUTPUT(data, sotcb) tcp_output((data), (sotcb))
+#define DO_TCP_INPUT(data, mbuf, size, so) tcp_input((data), (mbuf), (size), (so))
+#define DO_TCP_CONNECT(data, so) tcp_connect((data), (so))
+#define DO_SOREAD(ret, data, so, ifclose) do{(ret) = soread((data), (so), (ifclose));}while(0)
+#define DO_SOWRITE(ret, data, so) do{(ret) = sowrite((data), (so));}while(0)
+#define DO_SORECFROM(data, so) sorecvfrom((data), (so))
+#define SOLOOKUP(so, label, src, sport, dst, dport)                                     \
+do {                                                                                    \
+    (so) = solookup(&__X(queue_ ## label ## _label), (src), (sport), (dst), (dport));   \
+} while (0)
+#endif
+
+#define TCP_OUTPUT(data, sotcb) DO_TCP_OUTPUT((data), (sotcb))
+#define TCP_INPUT(data, mbuf, size, so) DO_TCP_INPUT((data), (mbuf), (size), (so))
+#define TCP_CONNECT(data, so) DO_TCP_CONNECT((data), (so))
+#define SOREAD(ret, data, so, ifclose) DO_SOREAD((ret), (data), (so), (ifclose))
+#define SOWRITE(ret, data, so) DO_SOWRITE((ret), (data), (so))
+#define SORECVFROM(data, so) DO_SORECFROM((data), (so))
 #endif /* !_slirp_state_h_ */
Index: trunk/src/VBox/Devices/Network/slirp/socket.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/socket.c	(revision 16443)
@@ -60,5 +60,5 @@
     struct socket *so;
 
-    so = (struct socket *)RTMemAlloc(sizeof(struct socket));
+    so = (struct socket *)RTMemAllocZ(sizeof(struct socket));
     if(so)
     {
@@ -89,10 +89,19 @@
     if(so->so_next && so->so_prev)
         remque(pData, so);  /* crashes if so is not in a queue */
-
+    so->so_state = SS_NOFDREF; /* for debugging purposes */
     SOCKET_UNLOCK(so);
     SOCKET_LOCK_DESTROY(so);
 
     RTMemFree(so);
-}
+    so = NULL;
+}
+
+#ifdef VBOX_WITH_SLIRP_MT
+void
+soread_queue(PNATState pData, struct socket *so, int fCloseIfNothingRead, int *ret)
+{
+    *ret = soread(pData, so, fCloseIfNothingRead);
+}
+#endif
 
 /*
@@ -109,4 +118,9 @@
     struct iovec iov[2];
     int mss = so->so_tcpcb->t_maxseg;
+    Log2(("%s:%d soread before lock\n", __FUNCTION__, __LINE__));
+    QSOCKET_LOCK(tcb);
+    SOCKET_LOCK(so);
+    QSOCKET_UNLOCK(tcb);
+    Log2(("%s:%d soread before lock\n",__FUNCTION__, __LINE__));
 
     DEBUG_CALL("soread");
@@ -190,8 +204,14 @@
          */
         if (nn == 0 && !fCloseIfNothingRead)
+        {
+            SOCKET_UNLOCK(so);
             return 0;
+        }
 #endif
         if (nn < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
+        {
+            SOCKET_UNLOCK(so);
             return 0;
+        }
         else
         {
@@ -201,4 +221,5 @@
             sofcantrcvmore(so);
             tcp_sockclosed(pData, sototcpcb(so));
+            SOCKET_UNLOCK(so);
             return -1;
         }
@@ -231,4 +252,5 @@
     if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
         sb->sb_wptr -= sb->sb_datalen;
+    SOCKET_UNLOCK(so);
     return nn;
 }
@@ -344,10 +366,15 @@
     DEBUG_CALL("sowrite");
     DEBUG_ARG("so = %lx", (long)so);
-
+    QSOCKET_LOCK(tcb);
+    SOCKET_LOCK(so);
+    QSOCKET_UNLOCK(tcb);
     if (so->so_urgc)
     {
         sosendoob(so);
         if (sb->sb_cc == 0)
+        {
+            SOCKET_UNLOCK(so);    
             return 0;
+        }
     }
 
@@ -396,5 +423,8 @@
     /* This should never happen, but people tell me it does *shrug* */
     if (nn < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
+    {
+        SOCKET_UNLOCK(so);    
         return 0;
+    }
 
     if (nn < 0 || (nn == 0 && iov[0].iov_len > 0))
@@ -404,4 +434,5 @@
         sofcantsendmore(so);
         tcp_sockclosed(pData, sototcpcb(so));
+        SOCKET_UNLOCK(so);    
         return -1;
     }
@@ -431,4 +462,5 @@
         sofcantsendmore(so);
 
+    SOCKET_UNLOCK(so);    
     return nn;
 }
@@ -463,6 +495,13 @@
         u_long n;
 
-        if (!(m = m_get(pData)))
+        QSOCKET_LOCK(udb);
+        SOCKET_LOCK(so);
+        QSOCKET_UNLOCK(udb);
+
+        if (!(m = m_get(pData))) 
+        {
+            SOCKET_UNLOCK(so);
             return;
+        }
         m->m_data += if_maxlinkhdr;
 #ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
@@ -490,5 +529,5 @@
         m->m_len = recvfrom(so->s, m->m_data, len, 0,
                             (struct sockaddr *)&addr, &addrlen);
-        DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
+        Log2((" did recvfrom %d, errno = %d-%s\n",
                     m->m_len, errno,strerror(errno)));
         if(m->m_len < 0)
@@ -501,5 +540,5 @@
                 code = ICMP_UNREACH_NET;
 
-            DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
+            Log2((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
             icmp_error(pData, so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
             m_free(pData, m);
@@ -534,4 +573,5 @@
              */
             udp_output(pData, so, m, &addr);
+            SOCKET_UNLOCK(so);
         } /* rx error */
     } /* if ping packet */
@@ -678,5 +718,7 @@
         int tmperrno = WSAGetLastError(); /* Don't clobber the real reason we failed */
         closesocket(s);
+        QSOCKET_LOCK(tcb);
         sofree(pData, so);
+        QSOCKET_UNLOCK(tcb);
         /* Restore the real errno */
         WSASetLastError(tmperrno);
Index: trunk/src/VBox/Devices/Network/slirp/socket.h
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/socket.h	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/socket.h	(revision 16443)
@@ -11,5 +11,5 @@
 #define _SLIRP_SOCKET_H_
 #ifdef VBOX_WITH_SLIRP_MT
-#include <iprt/semaphore.h>
+#include <iprt/critsect.h>
 #endif
 
@@ -68,5 +68,5 @@
     struct sbuf     so_snd;      /* Send buffer */
 #ifdef VBOX_WITH_SLIRP_MT
-    RTSEMMUTEX      so_mutex;
+    RTCRITSECT      so_mutex;
 #endif
 };
@@ -75,20 +75,25 @@
 # define SOCKET_LOCK(so)                                                \
     do {                                                                \
-        int rc = RTSemMutexRequest((so)->so_mutex, RT_INDEFINITE_WAIT); \
+        int rc;                                                         \
+        Log2(("lock:%s:%d L on %R[natsock]\n", __FUNCTION__, __LINE__, (so)));       \
+        rc = RTCritSectEnter(&(so)->so_mutex);                           \
         AssertReleaseRC(rc);                                            \
     } while (0)
 # define SOCKET_UNLOCK(so)                                              \
     do {                                                                \
-        int rc = RTSemMutexRelease((so)->so_mutex);                     \
+        int rc;                                                         \
+        if ((so) != NULL) Log2(("lock:%s:%d U on %R[natsock]\n", __FUNCTION__, __LINE__, (so)));       \
+        rc = RTCritSectLeave(&(so)->so_mutex);                           \
         AssertReleaseRC(rc);                                            \
     } while (0)
 # define SOCKET_LOCK_CREATE(so)                                         \
     do {                                                                \
-        int rc = RTSemMutexCreate(&(so)->so_mutex);                     \
+        int rc;                                                         \
+        rc = RTCritSectInit(&(so)->so_mutex);                            \
         AssertReleaseRC(rc);                                            \
     } while (0)
 # define SOCKET_LOCK_DESTROY(so)                                        \
     do {                                                                \
-        int rc = RTSemMutexDestroy((so)->so_mutex);                     \
+        int rc = RTCritSectDelete(&(so)->so_mutex);                      \
         AssertReleaseRC(rc);                                            \
     } while (0)
@@ -130,4 +135,7 @@
 struct socket * socreate _P((void));
 void sofree _P((PNATState, struct socket *));
+#ifdef VBOX_WITH_SLIRP_MT
+void soread_queue (PNATState, struct socket *, int, int *);
+#endif
 int soread _P((PNATState, struct socket *, int));
 void sorecvoob _P((PNATState, struct socket *));
Index: trunk/src/VBox/Devices/Network/slirp/tcp_input.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_input.c	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_input.c	(revision 16443)
@@ -277,5 +277,11 @@
     DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
                 (long )m, iphlen, (long )inso ));
-
+    
+    if (inso != NULL) 
+    { 
+        QSOCKET_LOCK(tcb);
+        SOCKET_LOCK(inso);
+        QSOCKET_UNLOCK(tcb);
+    }
     /*
      * If called with m == 0, then we're continuing the connect
@@ -395,4 +401,7 @@
      */
 findso:
+    if (so != NULL && so != &tcb)
+        SOCKET_UNLOCK(so);
+    QSOCKET_LOCK(tcb);
     so = tcp_last_so;
     if (   so->so_fport        != ti->ti_dport
@@ -401,9 +410,41 @@
         || so->so_faddr.s_addr != ti->ti_dst.s_addr)
     {
+        struct socket *sonxt;
+        QSOCKET_UNLOCK(tcb);
+        /* @todo fix SOLOOKUP macrodefinition to be usable here */ 
+#ifndef VBOX_WITH_SLIRP_MT
         so = solookup(&tcb, ti->ti_src, ti->ti_sport,
                       ti->ti_dst, ti->ti_dport);
+#else
+        so = NULL;
+        QSOCKET_FOREACH(so, sonxt, tcp)        
+        /* { */
+            if (   so->so_lport        == ti->ti_sport
+                && so->so_laddr.s_addr == ti->ti_src.s_addr
+                && so->so_faddr.s_addr == ti->ti_dst.s_addr
+                && so->so_fport        == ti->ti_dport) 
+            {
+                if (sonxt != &tcb)
+                    SOCKET_UNLOCK(sonxt);
+                Log2(("lock: %s:%d We found socket %R[natsock]\n", __FUNCTION__, __LINE__, so));
+                break; /* so is locked here */
+            }
+        LOOP_LABEL(tcp, so, sonxt);
+        }
+        if (so == &tcb) {
+            Log2(("lock: %s:%d Haven't find anything \n", __FUNCTION__, __LINE__));
+            so = NULL;
+        }
+#endif
         if (so)
+        {
             tcp_last_so = so;
+        }
         ++tcpstat.tcps_socachemiss;
+    } 
+    else
+    {
+        SOCKET_LOCK(so);
+        QSOCKET_UNLOCK(tcb);
     }
 
@@ -421,4 +462,5 @@
      * as if it was LISTENING, and continue...
      */
+    Log2(("so = %p\n", so));
     if (so == 0)
     {
@@ -594,4 +636,5 @@
                   (void) tcp_output(pData, tp);
 
+              SOCKET_UNLOCK(so);
               return;
             }
@@ -637,4 +680,5 @@
             tp->t_flags |= TF_ACKNOW;
             tcp_output(pData, tp);
+            SOCKET_UNLOCK(so);
             return;
         }
@@ -736,4 +780,5 @@
                 tp->t_state = TCPS_SYN_RECEIVED;
             }
+            SOCKET_UNLOCK(so);
             return;
 
@@ -765,4 +810,5 @@
             tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
             tcpstat.tcps_accepts++;
+            Log2(("hit trimthenstep6\n"));
             goto trimthenstep6;
         } /* case TCPS_LISTEN */
@@ -854,4 +900,5 @@
             tp->snd_wl1 = ti->ti_seq - 1;
             tp->rcv_up = ti->ti_seq;
+            Log2(("hit6"));
             goto step6;
     } /* switch tp->t_state */
@@ -985,4 +1032,5 @@
                 iss = tp->rcv_nxt + TCP_ISSINCR;
                 tp = tcp_close(pData, tp);
+                SOCKET_UNLOCK(tp->t_socket);
                 goto findso;
             }
@@ -1117,4 +1165,5 @@
             tp->snd_wl1 = ti->ti_seq - 1;
             /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
+            Log2(("hit synrx_to_est\n"));
             goto synrx_to_est;
             /* fall into ... */
@@ -1201,4 +1250,5 @@
             }
 synrx_to_est:
+            Log2(("enter synrx_to_est\n"));
             /*
              * If the congestion window was inflated to account
@@ -1429,4 +1479,5 @@
             tp->rcv_up = tp->rcv_nxt;
 dodata:
+    Log2(("do data hit!\n"));
 
     /*
@@ -1567,4 +1618,5 @@
         tcp_output(pData, tp);
 
+    SOCKET_UNLOCK(so);
     return;
 
@@ -1580,9 +1632,9 @@
     tp->t_flags |= TF_ACKNOW;
     (void) tcp_output(pData, tp);
+    SOCKET_UNLOCK(so);
     return;
 
 dropwithreset:
     /* reuses m if m!=NULL, m_free() unnecessary */
-    Log2(("drop with reset\n"));
     if (tiflags & TH_ACK)
         tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
@@ -1594,4 +1646,6 @@
     }
 
+    if (so != &tcb)
+        SOCKET_UNLOCK(so);
     return;
 
@@ -1600,7 +1654,7 @@
      * Drop space held by incoming segment and return.
      */
-    Log2(("drop\n"));
     m_free(pData, m);
 
+    SOCKET_UNLOCK(so);
     return;
 }
Index: trunk/src/VBox/Devices/Network/slirp/tcp_timer.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/tcp_timer.c	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/tcp_timer.c	(revision 16443)
@@ -44,5 +44,5 @@
 tcp_fasttimo(PNATState pData)
 {
-    register struct socket *so;
+    register struct socket *so, *so_next;
     register struct tcpcb *tp;
 
@@ -51,5 +51,6 @@
     so = tcb.so_next;
     if (so)
-        for (; so != &tcb; so = so->so_next)
+        QSOCKET_FOREACH (so, so_next,tcp)
+        /* { */
             if (   (tp = (struct tcpcb *)so->so_tcpcb)
                 && (tp->t_flags & TF_DELACK))
@@ -58,6 +59,8 @@
                 tp->t_flags |= TF_ACKNOW;
                 tcpstat.tcps_delack++;
-                (void) tcp_output(pData, tp);
-            }
+                TCP_OUTPUT(pData, tp);
+            }
+        LOOP_LABEL(tcp, so, so_next);
+        }
 }
 
@@ -82,10 +85,10 @@
     if (ip == 0)
         return;
-    for (; ip != &tcb; ip = ipnxt)
-    {
+    QSOCKET_FOREACH(ip, ipnxt, tcp)
+    /* { */ 
         ipnxt = ip->so_next;
         tp = sototcpcb(ip);
         if (tp == 0)
-            continue;
+            CONTINUE(tcp);
         for (i = 0; i < TCPT_NTIMERS; i++)
         {
@@ -102,4 +105,5 @@
 tpgone:
         ;
+    LOOP_LABEL(tcp, ip, ipnxt);
     }
     tcp_iss += TCP_ISSINCR / PR_SLOWHZ;         /* increment iss */
Index: trunk/src/VBox/Devices/Network/slirp/udp.c
===================================================================
--- trunk/src/VBox/Devices/Network/slirp/udp.c	(revision 16303)
+++ trunk/src/VBox/Devices/Network/slirp/udp.c	(revision 16443)
@@ -384,12 +384,12 @@
             /* enable broadcast for later use */
             setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
+            status = getsockname(so->s, &sa_addr, &socklen);
+            Assert(status == 0 && sa_addr.sa_family == AF_INET);
+            so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
+            so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
             SOCKET_LOCK_CREATE(so);
             QSOCKET_LOCK(udb);
             insque(pData, so,&udb);
             QSOCKET_UNLOCK(udb);
-            status = getsockname(so->s, &sa_addr, &socklen);
-            Assert(status == 0 && sa_addr.sa_family == AF_INET);
-            so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
-            so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
         }
     }
@@ -403,5 +403,7 @@
     {
         closesocket(so->s);
+        QSOCKET_LOCK(udb);
         sofree(pData, so);
+        QSOCKET_UNLOCK(udb);
     }
 }
@@ -699,5 +701,8 @@
     so->s = socket(AF_INET,SOCK_DGRAM,0);
     so->so_expire = curtime + SO_EXPIRE;
+    SOCKET_LOCK_CREATE(so);
+    QSOCKET_LOCK(udb);
     insque(pData, so,&udb);
+    QSOCKET_UNLOCK(udb);
 
     addr.sin_family = AF_INET;
