VirtualBox

儲存庫 vbox 的更動 16443


忽略:
時間撮記:
2009-1-31 上午07:16:03 (16 年 以前)
作者:
vboxsync
訊息:

NAT:MT

  1. slirp queue inroduced
  2. main points of thread interactions are saved with critical sections
  3. slirp polling routine and timers communicates with NAT guest IO thread via queue

TODO: not works well, not compilable on Unixes.

位置:
trunk/src/VBox/Devices/Network
檔案:
修改 10 筆資料

圖例:

未更動
新增
刪除
  • trunk/src/VBox/Devices/Network/DrvNAT.cpp

    r16291 r16443  
    5353 *        activity. This needs to be fixed properly.
    5454 */
    55 #define VBOX_NAT_DELAY_HACK
     55/*#define VBOX_NAT_DELAY_HACK*/
    5656
    5757
     
    148148    Log2(("drvNATSend: pvBuf=%p cb=%#x\n%.*Rhxd\n", pvBuf, cb, cb, pvBuf));
    149149
    150 #ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
     150#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC 
    151151
    152152    PRTREQ pReq = NULL;
     
    155155    if (pThis->pThread->enmState != PDMTHREADSTATE_RUNNING)
    156156        return VINF_SUCCESS;
     157#ifndef VBOX_WITH_SLIRP_MT
    157158    rc = RTReqAlloc(pThis->pReqQueue, &pReq, RTREQTYPE_INTERNAL);
     159#else
     160    rc = RTReqAlloc((PRTREQQUEUE)slirp_get_queue(pThis->pNATState), &pReq, RTREQTYPE_INTERNAL);
     161#endif
    158162    AssertReleaseRC(rc);
    159163    pReq->u.Internal.pfn      = (PFNRT)drvNATSendWorker;
     
    163167    pReq->u.Internal.aArgs[2] = (uintptr_t)cb;
    164168    pReq->fFlags              = RTREQFLAGS_VOID;
     169
    165170    rc = RTReqQueue(pReq, 0); /* don't wait, we have to wakeup the NAT thread fist */
    166171    if (RT_LIKELY(rc == VERR_TIMEOUT))
     
    181186        AssertReleaseRC(rc);
    182187    RTReqFree(pReq);
     188
     189    rc = WSASetEvent(pThis->hWakeupEvent);
     190    AssertRelease(rc == TRUE);
    183191
    184192#else /* !VBOX_WITH_SIMPLIFIED_SLIRP_SYNC */
     
    397405            /* only check for slow/fast timers */
    398406            slirp_select_poll(pThis->pNATState, /* fTimeout=*/true, /*fIcmp=*/false);
     407            Log2(("%s: timeout\n", __FUNCTION__));
    399408            continue;
    400409        }
    401410
    402411        /* poll the sockets in any case */
     412        Log2(("%s: poll\n", __FUNCTION__));
    403413        slirp_select_poll(pThis->pNATState, /* fTimeout=*/false, /* fIcmp=*/(event == WSA_WAIT_EVENT_0));
    404414        /* process _all_ outstanding requests but don't wait */
     
    444454{
    445455    PDRVNAT pThis = PDMINS_2_DATA(pDrvIns, PDRVNAT);
    446         while (1)
     456    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     457        return VINF_SUCCESS;
     458    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
    447459        {
     460        slirp_process_queue(pThis->pNATState);
    448461        }
     462    return VINF_SUCCESS;
    449463}
    450464
  • trunk/src/VBox/Devices/Network/slirp/debug.c

    r15683 r16443  
    185185    char buff[256];
    186186    int n;
    187     struct socket *so;
     187    struct socket *so, *so_next;
    188188
    189189    lprint(" \n");
     
    192192           "Proto[state]     Sock     Local Address, Port  Remote Address, Port RecvQ SendQ\n");
    193193
    194     for (so = tcb.so_next; so != &tcb; so = so->so_next)
    195     {
     194    QSOCKET_FOREACH(so, so_next, tcp)
     195    /* { */
    196196        n = sprintf(buff, "tcp[%s]", so->so_tcpcb?tcpstates[so->so_tcpcb->t_state]:"NONE");
    197197        while (n < 17)
     
    203203                inet_ntoa(so->so_faddr), ntohs(so->so_fport),
    204204                so->so_rcv.sb_cc, so->so_snd.sb_cc);
     205    LOOP_LABEL(tcp, so, so_next);
    205206    }
    206207
    207     for (so = udb.so_next; so != &udb; so = so->so_next)
    208     {
     208    QSOCKET_FOREACH(so, so_next, udp)
     209    /* { */
    209210        n = sprintf(buff, "udp[%d sec]", (so->so_expire - curtime) / 1000);
    210211        while (n < 17)
     
    216217                inet_ntoa(so->so_faddr), ntohs(so->so_fport),
    217218                so->so_rcv.sb_cc, so->so_snd.sb_cc);
     219    LOOP_LABEL(udp, so, so_next);
    218220    }
    219221}
     
    248250
    249251    AssertReturn(strcmp(pszType, "natsock") == 0, 0);
    250 
     252    if (so->so_state == SS_NOFDREF || so->s == -1)
     253        return RTStrFormat(pfnOutput, pvArgOutput, NULL, 0, "socket SS_NODREF");
    251254    status = getsockname(so->s, &addr, &socklen);
    252255
     
    257260            "state=%04x ip=" IP4_ADDR_PRINTF_FORMAT ":%d name=" IP4_ADDR_PRINTF_FORMAT ":%d",
    258261            so->s, so->so_type, so->so_state, IP4_ADDR_PRINTF_DECOMP(ip), ntohs(so->so_fport),
    259             IP4_ADDR_PRINTF_DECOMP(((struct sockaddr_in *)&addr)->sin_addr.s_addr),
     262            IP4_ADDR_PRINTF_DECOMP(ntohl(((struct sockaddr_in *)&addr)->sin_addr.s_addr)),
    260263            ntohs(((struct sockaddr_in *)&addr)->sin_port));
    261264}
  • trunk/src/VBox/Devices/Network/slirp/libslirp.h

    r15890 r16443  
    8989void slirp_register_external_event(PNATState pData, HANDLE hEvent, int index);
    9090#endif
     91#ifdef VBOX_WITH_SLIRP_MT
     92void slirp_process_queue(PNATState pData);
     93void *slirp_get_queue(PNATState pData);
     94#endif
    9195
    9296/*
  • trunk/src/VBox/Devices/Network/slirp/slirp.c

    r16303 r16443  
    88#include <iprt/assert.h>
    99
    10 #ifdef VBOX_WITH_SLIRP_MT
    11 # define CONTINUE(label) goto loop_end_ ## label ## _mt
    12 /* @todo replace queue parameter with macrodinition */
    13 # define LOOP_LABEL(label, so, sonext) loop_end_ ## label ## _mt:    \
    14     SOCKET_UNLOCK(so);                                               \
    15     QSOCKET_LOCK(_X(queue_ ## label ## _label));                     \
    16     (so) = (sonext)
    17 #else
    18 #define CONTINUE(label) continue;
    19 # define LOOP_LABEL(label, so, sonext) /* empty*/
    20 #endif
    2110#if !defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) || !defined(RT_OS_WINDOWS)
    2211
     
    387376{
    388377    int fNATfailed = 0;
     378    int rc;
    389379    PNATState pData = RTMemAlloc(sizeof(NATState));
    390380    *ppData = pData;
     
    409399    pData->phEvents[VBOX_SOCKET_EVENT_INDEX] = CreateEvent(NULL, FALSE, FALSE, NULL);
    410400# endif
     401#endif
     402#ifdef VBOX_WITH_SLIRP_MT
     403    QSOCKET_LOCK_CREATE(tcb);
     404    QSOCKET_LOCK_CREATE(udb);
     405    rc = RTReqCreateQueue(&pData->pReqQueue);
     406    AssertReleaseRC(rc);
    411407#endif
    412408
     
    686682        QSOCKET_FOREACH(so, so_next, udp)
    687683        /* { */
    688             so_next = so->so_next;
    689684
    690685            STAM_COUNTER_INC(&pData->StatUDP);
     
    698693                {
    699694                    udp_detach(pData, so);
    700                     CONTINUE(udp);
     695                    CONTINUE_NO_UNLOCK(udp);
    701696                }
    702697                else
     
    796791         * Check TCP sockets
    797792         */
    798         for (so = tcb.so_next; so != &tcb; so = so_next)
    799         {
    800             so_next = so->so_next;
     793        QSOCKET_FOREACH(so, so_next, tcp)
     794        /* { */
    801795
    802796            /*
     
    834828                if (so->so_state & SS_FACCEPTCONN)
    835829                {
    836                     tcp_connect(pData, so);
     830                    TCP_CONNECT(pData, so);
    837831#if defined(VBOX_WITH_SIMPLIFIED_SLIRP_SYNC) && defined(RT_OS_WINDOWS)
    838832                    if (!(NetworkEvents.lNetworkEvents & FD_CLOSE))
     
    841835                }
    842836
    843                 ret = soread(pData, so, /*fCloseIfNothingRead=*/false);
     837                SOREAD(ret, pData, so, /*fCloseIfNothingRead=*/false);
    844838                /* Output it if we read something */
    845839                if (ret > 0)
    846                     tcp_output(pData, sototcpcb(so));
     840                    TCP_OUTPUT(pData, sototcpcb(so));
    847841            }
    848842
     
    858852                for (;;)
    859853                {
    860                     ret = soread(pData, so, /*fCloseIfNothingRead=*/true);
     854                    SOREAD(ret, pData, so, /*fCloseIfNothingRead=*/true);
    861855                    if (ret > 0)
    862                         tcp_output(pData, sototcpcb(so));
     856                        TCP_OUTPUT(pData, sototcpcb(so));
    863857                    else
    864858                        break;
     
    907901                     * Continue tcp_input
    908902                     */
    909                     tcp_input(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
     903                    TCP_INPUT(pData, (struct mbuf *)NULL, sizeof(struct ip), so);
    910904                    /* continue; */
    911905                }
    912906                else
    913                     ret = sowrite(pData, so);
     907                    SOWRITE(ret, pData, so);
    914908                /*
    915909                 * XXX If we wrote something (a lot), there could be the need
     
    964958
    965959                }
    966                 tcp_input((struct mbuf *)NULL, sizeof(struct ip),so);
     960                TCP_INPUT((struct mbuf *)NULL, sizeof(struct ip),so);
    967961            } /* SS_ISFCONNECTING */
    968962#endif
     
    975969         * Incoming UDP data isn't buffered either.
    976970         */
    977         for (so = udb.so_next; so != &udb; so = so_next)
    978         {
    979             so_next = so->so_next;
    980 
     971         QSOCKET_FOREACH(so, so_next, udp)
     972         /* { */
    981973            POLL_UDP_EVENTS(rc, error, so, &NetworkEvents);
    982974
     
    985977            if (so->s != -1 && CHECK_FD_SET(so, NetworkEvents, readfds))
    986978            {
    987                 sorecvfrom(pData, so);
     979                SORECVFROM(pData, so);
    988980            }
    989981            LOOP_LABEL(udp, so, so_next);
     
    12901282    m_free(pData, m);
    12911283}
     1284#ifdef VBOX_WITH_SLIRP_MT
     1285void slirp_process_queue(PNATState pData)
     1286{
     1287     RTReqProcess(pData->pReqQueue, RT_INDEFINITE_WAIT);
     1288}
     1289void *slirp_get_queue(PNATState pData)
     1290{
     1291    return pData->pReqQueue;
     1292}
     1293#endif
  • trunk/src/VBox/Devices/Network/slirp/slirp_state.h

    r16292 r16443  
    2121#ifndef _slirp_state_h_
    2222#define _slirp_state_h_
     23#include <iprt/req.h>
    2324#include "ip_icmp.h"
    2425
     
    100101    struct in_addr alias_addr;
    101102    struct in_addr special_addr;
     103#ifdef VBOX_WITH_SLIRP_MT
     104    PRTREQQUEUE pReqQueue;
     105#endif
    102106#ifndef VBOX_WITH_MULTI_DNS
    103107    struct in_addr dns_addr;
     
    116120    struct socket tcb;
    117121#ifdef VBOX_WITH_SLIRP_MT
    118     RTSEMMUTEX      tcb_mutex;
     122    RTCRITSECT      tcb_mutex;
    119123#endif
    120124    struct socket *tcp_last_so;
     
    134138    struct socket udb;
    135139#ifdef VBOX_WITH_SLIRP_MT
    136     RTSEMMUTEX      udb_mutex;
     140    RTCRITSECT      udb_mutex;
    137141#endif
    138142    struct socket *udp_last_so;
     
    277281#define __X(x) x
    278282#define _X(x) __X(x)
    279 
     283#define _str(x) #x
     284#define str(x) _str(x)
    280285#ifdef VBOX_WITH_SLIRP_MT
    281286#define QSOCKET_LOCK(queue)                                                     \
    282287do {                                                                            \
    283     int rc = RTSemMutexRequest(_X(queue) ## _mutex, RT_INDEFINITE_WAIT);        \
     288    int rc;                                                                     \
     289    rc = RTCritSectEnter(&_X(queue) ## _mutex);            \
    284290    AssertReleaseRC(rc);                                                        \
    285291} while (0)
    286292#define QSOCKET_UNLOCK(queue)                           \
    287293do {                                                    \
    288     int rc = RTSemMutexRelease(_X(queue) ## _mutex);    \
     294    int rc;                                             \
     295    rc = RTCritSectLeave(&_X(queue) ## _mutex);        \
    289296    AssertReleaseRC(rc);                                \
    290297} while (0)
    291298#define QSOCKET_LOCK_CREATE(queue)                      \
    292299do {                                                    \
    293     int rc = RTSemMutexCreate(&pData->queue ## _mutex); \
     300    int rc;                                             \
     301    rc = RTCritSectInit(&pData->queue ## _mutex);     \
    294302    AssertReleaseRC(rc);                                \
    295303} while (0)
    296304#define QSOCKET_LOCK_DESTROY(queue)                     \
    297305do {                                                    \
    298     int rc = RTSemMutexDestroy(pData->queue ## _mutex); \
     306    int rc = RTCritSectDelete(&pData->queue ## _mutex); \
    299307    AssertReleaseRC(rc);                                \
    300308} while (0)
     
    303311        QSOCKET_LOCK(__X(queue_## label ## _label));                \
    304312        (so) = (_X(queue_ ## label ## _label)).so_next;             \
    305         SOCKET_LOCK((so));                                          \
     313        if ((so) != &(_X(queue_## label ## _label))) SOCKET_LOCK((so));  \
    306314        for(;;)                                                     \
    307315        {                                                           \
     
    311319                break;                                              \
    312320            }                                                       \
     321            Log2(("%s:%d Processing so:%R[natsock]\n", __FUNCTION__, __LINE__, (so)));  \
    313322            if ((so)->so_next != &(_X(queue_## label ## _label)))   \
    314323            {                                                       \
     
    317326            (sonext) = (so)->so_next;                               \
    318327            QSOCKET_UNLOCK(__X(queue_## label ##_label));
     328
     329# define CONTINUE_NO_UNLOCK(label) goto loop_end_ ## label ## _mt_nounlock
     330# define CONTINUE(label) goto loop_end_ ## label ## _mt
     331/* @todo replace queue parameter with macrodinition */
     332# define LOOP_LABEL(label, so, sonext) loop_end_ ## label ## _mt:       \
     333    SOCKET_UNLOCK(so);                                                  \
     334    loop_end_ ## label ## _mt_nounlock:                                 \
     335    QSOCKET_LOCK(_X(queue_ ## label ## _label));                        \
     336    (so) = (sonext)
     337
     338#define DO_TCP_OUTPUT(data, sotcb)                                      \
     339do {                                                                    \
     340    PRTREQ pReq = NULL;                                                 \
     341    int rc;                                                             \
     342    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
     343    AssertReleaseRC(rc);                                                \
     344    pReq->u.Internal.pfn      = (PFNRT)tcp_output;                      \
     345    pReq->u.Internal.cArgs    = 2;                                      \
     346    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
     347    pReq->u.Internal.aArgs[1] = (uintptr_t)(sotcb);                     \
     348    pReq->fFlags              = RTREQFLAGS_VOID;     \
     349    rc = RTReqQueue(pReq, 0);                                           \
     350    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
     351    {                                                                   \
     352        SOCKET_UNLOCK(so);                                               \
     353        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
     354        AssertReleaseRC(rc);                                            \
     355        SOCKET_LOCK(so);                                                \
     356        RTReqFree(pReq);                                                \
     357    }                                                                   \
     358    else                                                                \
     359        AssertReleaseRC(rc);                                            \
     360} while(0)
     361
     362#define DO_TCP_INPUT(data, mbuf, size, so)                              \
     363do {                                                                    \
     364    PRTREQ pReq = NULL;                                                 \
     365    int rc;                                                             \
     366    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
     367    AssertReleaseRC(rc);                                                \
     368    pReq->u.Internal.pfn      = (PFNRT)tcp_input;                       \
     369    pReq->u.Internal.cArgs    = 4;                                      \
     370    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
     371    pReq->u.Internal.aArgs[1] = (uintptr_t)(mbuf);                      \
     372    pReq->u.Internal.aArgs[2] = (uintptr_t)(size);                      \
     373    pReq->u.Internal.aArgs[3] = (uintptr_t)(so);                        \
     374    pReq->fFlags              = RTREQFLAGS_VOID;                        \
     375    rc = RTReqQueue(pReq, 0);                                           \
     376    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
     377    {                                                                   \
     378        SOCKET_UNLOCK(so);                                               \
     379        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
     380        AssertReleaseRC(rc);                                            \
     381        SOCKET_LOCK(so);                                                \
     382        RTReqFree(pReq);                                                \
     383    }                                                                   \
     384    else                                                                \
     385        AssertReleaseRC(rc);                                            \
     386} while(0)
     387
     388#define DO_TCP_CONNECT(data, so)                                        \
     389do {                                                                    \
     390    PRTREQ pReq = NULL;                                                 \
     391    int rc;                                                             \
     392    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
     393    AssertReleaseRC(rc);                                                \
     394    pReq->u.Internal.pfn      = (PFNRT)tcp_connect;                     \
     395    pReq->u.Internal.cArgs    = 2;                                      \
     396    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
     397    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
     398    pReq->fFlags              = RTREQFLAGS_VOID;                        \
     399    rc = RTReqQueue(pReq, 0); /* don't wait, we have to release lock before*/ \
     400    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
     401    {                                                                   \
     402        SOCKET_UNLOCK(so);                                               \
     403        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
     404        AssertReleaseRC(rc);                                            \
     405        SOCKET_LOCK(so);                                                \
     406        RTReqFree(pReq);                                                \
     407    }                                                                   \
     408    else                                                                \
     409        AssertReleaseRC(rc);                                            \
     410} while(0)
     411
     412#define DO_SOREAD(ret, data, so, ifclose)                               \
     413do {                                                                    \
     414    PRTREQ pReq = NULL;                                                 \
     415    int rc;                                                             \
     416    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
     417    AssertReleaseRC(rc);                                                \
     418    pReq->u.Internal.pfn      = (PFNRT)soread_queue;                    \
     419    pReq->u.Internal.cArgs    = 4;                                      \
     420    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
     421    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
     422    pReq->u.Internal.aArgs[2] = (uintptr_t)(ifclose);                   \
     423    pReq->u.Internal.aArgs[3] = (uintptr_t)&(ret);                      \
     424    pReq->fFlags              = RTREQFLAGS_VOID;                        \
     425    rc = RTReqQueue(pReq, 0); /* don't wait, we have to release lock before*/ \
     426    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
     427    {                                                                   \
     428        SOCKET_UNLOCK(so);                                               \
     429        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
     430        AssertReleaseRC(rc);                                            \
     431        SOCKET_LOCK(so);                                                \
     432        RTReqFree(pReq);                                                \
     433    }                                                                   \
     434    else                                                                \
     435        AssertReleaseRC(rc);                                            \
     436} while(0)
     437
     438#define DO_SOWRITE(ret, data, so)                                       \
     439do {                                                                    \
     440    PRTREQ pReq = NULL;                                                 \
     441    int rc;                                                             \
     442    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
     443    AssertReleaseRC(rc);                                                \
     444    pReq->u.Internal.pfn      = (PFNRT)sowrite;                         \
     445    pReq->u.Internal.cArgs    = 2;                                      \
     446    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
     447    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
     448    pReq->fFlags              = RTREQFLAGS_RETURN_MASK;                 \
     449    rc = RTReqQueue(pReq, 0); /* don't wait, we have to release lock before*/ \
     450    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
     451    {                                                                   \
     452        SOCKET_UNLOCK(so);                                              \
     453        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
     454        SOCKET_LOCK(so);                                                \
     455        ret = pReq->iStatus;                                            \
     456        RTReqFree(pReq);                                                \
     457    }                                                                   \
     458    else                                                                \
     459        AssertReleaseRC(rc);                                            \
     460} while(0)
     461
     462#define DO_SORECFROM(data, so)                                          \
     463do {                                                                    \
     464    PRTREQ pReq = NULL;                                                 \
     465    int rc;                                                             \
     466    rc = RTReqAlloc((data)->pReqQueue, &pReq, RTREQTYPE_INTERNAL);      \
     467    AssertReleaseRC(rc);                                                \
     468    pReq->u.Internal.pfn      = (PFNRT)sorecvfrom;                      \
     469    pReq->u.Internal.cArgs    = 2;                                      \
     470    pReq->u.Internal.aArgs[0] = (uintptr_t)(data);                      \
     471    pReq->u.Internal.aArgs[1] = (uintptr_t)(so);                        \
     472    pReq->fFlags              = RTREQFLAGS_VOID;                        \
     473    rc = RTReqQueue(pReq, 0);                                           \
     474    if (RT_LIKELY(rc) == VERR_TIMEOUT)                                  \
     475    {                                                                   \
     476        SOCKET_UNLOCK(so);                                               \
     477        rc = RTReqWait(pReq, RT_INDEFINITE_WAIT);                       \
     478        AssertReleaseRC(rc);                                            \
     479        SOCKET_LOCK(so);                                                \
     480        RTReqFree(pReq);                                                \
     481    }                                                                   \
     482    else                                                                \
     483        AssertReleaseRC(rc);                                            \
     484} while(0)
     485
     486#define SOLOOKUP(so, label, src, sport, dst, dport)                     \
     487do {                                                                    \
     488    struct socket *sonxt;                                               \
     489    (so) = NULL;                                                        \
     490    QSOCKET_FOREACH(so, sonxt, label)                                   \
     491    /* { */                                                             \
     492        if (   so->so_lport        == (sport)                           \
     493            && so->so_laddr.s_addr == (src).s_addr                      \
     494            && so->so_faddr.s_addr == (dst).s_addr                      \
     495            && so->so_fport        == (dport))                          \
     496            {                                                           \
     497                if (sonxt != &__X(queue_ ## label ## _label))           \
     498                    SOCKET_UNLOCK(sonxt);                               \
     499                break; /*so is locked*/                                 \
     500            }                                                           \
     501        LOOP_LABEL(so, sonxt, label);                                   \
     502        }                                                               \
     503    }                                                                   \
     504}while (0)
     505   
    319506#else
    320507#define QSOCKET_LOCK(queue) do {} while (0)
     
    326513   {                                                                                                                \
    327514            (sonext) = (so)->so_next;
    328 #endif
    329 
     515# define CONTINUE(label) continue
     516# define CONTINUE_NO_UNLOCK(label) continue
     517# define LOOP_LABEL(label, so, sonext) /* empty*/
     518#define DO_TCP_OUTPUT(data, sotcb) tcp_output((data), (sotcb))
     519#define DO_TCP_INPUT(data, mbuf, size, so) tcp_input((data), (mbuf), (size), (so))
     520#define DO_TCP_CONNECT(data, so) tcp_connect((data), (so))
     521#define DO_SOREAD(ret, data, so, ifclose) do{(ret) = soread((data), (so), (ifclose));}while(0)
     522#define DO_SOWRITE(ret, data, so) do{(ret) = sowrite((data), (so));}while(0)
     523#define DO_SORECFROM(data, so) sorecvfrom((data), (so))
     524#define SOLOOKUP(so, label, src, sport, dst, dport)                                     \
     525do {                                                                                    \
     526    (so) = solookup(&__X(queue_ ## label ## _label), (src), (sport), (dst), (dport));   \
     527} while (0)
     528#endif
     529
     530#define TCP_OUTPUT(data, sotcb) DO_TCP_OUTPUT((data), (sotcb))
     531#define TCP_INPUT(data, mbuf, size, so) DO_TCP_INPUT((data), (mbuf), (size), (so))
     532#define TCP_CONNECT(data, so) DO_TCP_CONNECT((data), (so))
     533#define SOREAD(ret, data, so, ifclose) DO_SOREAD((ret), (data), (so), (ifclose))
     534#define SOWRITE(ret, data, so) DO_SOWRITE((ret), (data), (so))
     535#define SORECVFROM(data, so) DO_SORECFROM((data), (so))
    330536#endif /* !_slirp_state_h_ */
  • trunk/src/VBox/Devices/Network/slirp/socket.c

    r16293 r16443  
    6060    struct socket *so;
    6161
    62     so = (struct socket *)RTMemAlloc(sizeof(struct socket));
     62    so = (struct socket *)RTMemAllocZ(sizeof(struct socket));
    6363    if(so)
    6464    {
     
    8989    if(so->so_next && so->so_prev)
    9090        remque(pData, so);  /* crashes if so is not in a queue */
    91 
     91    so->so_state = SS_NOFDREF; /* for debugging purposes */
    9292    SOCKET_UNLOCK(so);
    9393    SOCKET_LOCK_DESTROY(so);
    9494
    9595    RTMemFree(so);
    96 }
     96    so = NULL;
     97}
     98
     99#ifdef VBOX_WITH_SLIRP_MT
     100void
     101soread_queue(PNATState pData, struct socket *so, int fCloseIfNothingRead, int *ret)
     102{
     103    *ret = soread(pData, so, fCloseIfNothingRead);
     104}
     105#endif
    97106
    98107/*
     
    109118    struct iovec iov[2];
    110119    int mss = so->so_tcpcb->t_maxseg;
     120    Log2(("%s:%d soread before lock\n", __FUNCTION__, __LINE__));
     121    QSOCKET_LOCK(tcb);
     122    SOCKET_LOCK(so);
     123    QSOCKET_UNLOCK(tcb);
     124    Log2(("%s:%d soread before lock\n",__FUNCTION__, __LINE__));
    111125
    112126    DEBUG_CALL("soread");
     
    190204         */
    191205        if (nn == 0 && !fCloseIfNothingRead)
     206        {
     207            SOCKET_UNLOCK(so);
    192208            return 0;
     209        }
    193210#endif
    194211        if (nn < 0 && (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK))
     212        {
     213            SOCKET_UNLOCK(so);
    195214            return 0;
     215        }
    196216        else
    197217        {
     
    201221            sofcantrcvmore(so);
    202222            tcp_sockclosed(pData, sototcpcb(so));
     223            SOCKET_UNLOCK(so);
    203224            return -1;
    204225        }
     
    231252    if (sb->sb_wptr >= (sb->sb_data + sb->sb_datalen))
    232253        sb->sb_wptr -= sb->sb_datalen;
     254    SOCKET_UNLOCK(so);
    233255    return nn;
    234256}
     
    344366    DEBUG_CALL("sowrite");
    345367    DEBUG_ARG("so = %lx", (long)so);
    346 
     368    QSOCKET_LOCK(tcb);
     369    SOCKET_LOCK(so);
     370    QSOCKET_UNLOCK(tcb);
    347371    if (so->so_urgc)
    348372    {
    349373        sosendoob(so);
    350374        if (sb->sb_cc == 0)
     375        {
     376            SOCKET_UNLOCK(so);   
    351377            return 0;
     378        }
    352379    }
    353380
     
    396423    /* This should never happen, but people tell me it does *shrug* */
    397424    if (nn < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK))
     425    {
     426        SOCKET_UNLOCK(so);   
    398427        return 0;
     428    }
    399429
    400430    if (nn < 0 || (nn == 0 && iov[0].iov_len > 0))
     
    404434        sofcantsendmore(so);
    405435        tcp_sockclosed(pData, sototcpcb(so));
     436        SOCKET_UNLOCK(so);   
    406437        return -1;
    407438    }
     
    431462        sofcantsendmore(so);
    432463
     464    SOCKET_UNLOCK(so);   
    433465    return nn;
    434466}
     
    463495        u_long n;
    464496
    465         if (!(m = m_get(pData)))
     497        QSOCKET_LOCK(udb);
     498        SOCKET_LOCK(so);
     499        QSOCKET_UNLOCK(udb);
     500
     501        if (!(m = m_get(pData)))
     502        {
     503            SOCKET_UNLOCK(so);
    466504            return;
     505        }
    467506        m->m_data += if_maxlinkhdr;
    468507#ifdef VBOX_WITH_SIMPLIFIED_SLIRP_SYNC
     
    490529        m->m_len = recvfrom(so->s, m->m_data, len, 0,
    491530                            (struct sockaddr *)&addr, &addrlen);
    492         DEBUG_MISC((dfd, " did recvfrom %d, errno = %d-%s\n",
     531        Log2((" did recvfrom %d, errno = %d-%s\n",
    493532                    m->m_len, errno,strerror(errno)));
    494533        if(m->m_len < 0)
     
    501540                code = ICMP_UNREACH_NET;
    502541
    503             DEBUG_MISC((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
     542            Log2((dfd," rx error, tx icmp ICMP_UNREACH:%i\n", code));
    504543            icmp_error(pData, so->so_m, ICMP_UNREACH,code, 0,strerror(errno));
    505544            m_free(pData, m);
     
    534573             */
    535574            udp_output(pData, so, m, &addr);
     575            SOCKET_UNLOCK(so);
    536576        } /* rx error */
    537577    } /* if ping packet */
     
    678718        int tmperrno = WSAGetLastError(); /* Don't clobber the real reason we failed */
    679719        closesocket(s);
     720        QSOCKET_LOCK(tcb);
    680721        sofree(pData, so);
     722        QSOCKET_UNLOCK(tcb);
    681723        /* Restore the real errno */
    682724        WSASetLastError(tmperrno);
  • trunk/src/VBox/Devices/Network/slirp/socket.h

    r16291 r16443  
    1111#define _SLIRP_SOCKET_H_
    1212#ifdef VBOX_WITH_SLIRP_MT
    13 #include <iprt/semaphore.h>
     13#include <iprt/critsect.h>
    1414#endif
    1515
     
    6868    struct sbuf     so_snd;      /* Send buffer */
    6969#ifdef VBOX_WITH_SLIRP_MT
    70     RTSEMMUTEX      so_mutex;
     70    RTCRITSECT      so_mutex;
    7171#endif
    7272};
     
    7575# define SOCKET_LOCK(so)                                                \
    7676    do {                                                                \
    77         int rc = RTSemMutexRequest((so)->so_mutex, RT_INDEFINITE_WAIT); \
     77        int rc;                                                         \
     78        Log2(("lock:%s:%d L on %R[natsock]\n", __FUNCTION__, __LINE__, (so)));       \
     79        rc = RTCritSectEnter(&(so)->so_mutex);                           \
    7880        AssertReleaseRC(rc);                                            \
    7981    } while (0)
    8082# define SOCKET_UNLOCK(so)                                              \
    8183    do {                                                                \
    82         int rc = RTSemMutexRelease((so)->so_mutex);                     \
     84        int rc;                                                         \
     85        if ((so) != NULL) Log2(("lock:%s:%d U on %R[natsock]\n", __FUNCTION__, __LINE__, (so)));       \
     86        rc = RTCritSectLeave(&(so)->so_mutex);                           \
    8387        AssertReleaseRC(rc);                                            \
    8488    } while (0)
    8589# define SOCKET_LOCK_CREATE(so)                                         \
    8690    do {                                                                \
    87         int rc = RTSemMutexCreate(&(so)->so_mutex);                     \
     91        int rc;                                                         \
     92        rc = RTCritSectInit(&(so)->so_mutex);                            \
    8893        AssertReleaseRC(rc);                                            \
    8994    } while (0)
    9095# define SOCKET_LOCK_DESTROY(so)                                        \
    9196    do {                                                                \
    92         int rc = RTSemMutexDestroy((so)->so_mutex);                     \
     97        int rc = RTCritSectDelete(&(so)->so_mutex);                      \
    9398        AssertReleaseRC(rc);                                            \
    9499    } while (0)
     
    130135struct socket * socreate _P((void));
    131136void sofree _P((PNATState, struct socket *));
     137#ifdef VBOX_WITH_SLIRP_MT
     138void soread_queue (PNATState, struct socket *, int, int *);
     139#endif
    132140int soread _P((PNATState, struct socket *, int));
    133141void sorecvoob _P((PNATState, struct socket *));
  • trunk/src/VBox/Devices/Network/slirp/tcp_input.c

    r16291 r16443  
    277277    DEBUG_ARGS((dfd," m = %8lx  iphlen = %2d  inso = %lx\n",
    278278                (long )m, iphlen, (long )inso ));
    279 
     279   
     280    if (inso != NULL)
     281    {
     282        QSOCKET_LOCK(tcb);
     283        SOCKET_LOCK(inso);
     284        QSOCKET_UNLOCK(tcb);
     285    }
    280286    /*
    281287     * If called with m == 0, then we're continuing the connect
     
    395401     */
    396402findso:
     403    if (so != NULL && so != &tcb)
     404        SOCKET_UNLOCK(so);
     405    QSOCKET_LOCK(tcb);
    397406    so = tcp_last_so;
    398407    if (   so->so_fport        != ti->ti_dport
     
    401410        || so->so_faddr.s_addr != ti->ti_dst.s_addr)
    402411    {
     412        struct socket *sonxt;
     413        QSOCKET_UNLOCK(tcb);
     414        /* @todo fix SOLOOKUP macrodefinition to be usable here */
     415#ifndef VBOX_WITH_SLIRP_MT
    403416        so = solookup(&tcb, ti->ti_src, ti->ti_sport,
    404417                      ti->ti_dst, ti->ti_dport);
     418#else
     419        so = NULL;
     420        QSOCKET_FOREACH(so, sonxt, tcp)       
     421        /* { */
     422            if (   so->so_lport        == ti->ti_sport
     423                && so->so_laddr.s_addr == ti->ti_src.s_addr
     424                && so->so_faddr.s_addr == ti->ti_dst.s_addr
     425                && so->so_fport        == ti->ti_dport)
     426            {
     427                if (sonxt != &tcb)
     428                    SOCKET_UNLOCK(sonxt);
     429                Log2(("lock: %s:%d We found socket %R[natsock]\n", __FUNCTION__, __LINE__, so));
     430                break; /* so is locked here */
     431            }
     432        LOOP_LABEL(tcp, so, sonxt);
     433        }
     434        if (so == &tcb) {
     435            Log2(("lock: %s:%d Haven't find anything \n", __FUNCTION__, __LINE__));
     436            so = NULL;
     437        }
     438#endif
    405439        if (so)
     440        {
    406441            tcp_last_so = so;
     442        }
    407443        ++tcpstat.tcps_socachemiss;
     444    }
     445    else
     446    {
     447        SOCKET_LOCK(so);
     448        QSOCKET_UNLOCK(tcb);
    408449    }
    409450
     
    421462     * as if it was LISTENING, and continue...
    422463     */
     464    Log2(("so = %p\n", so));
    423465    if (so == 0)
    424466    {
     
    594636                  (void) tcp_output(pData, tp);
    595637
     638              SOCKET_UNLOCK(so);
    596639              return;
    597640            }
     
    637680            tp->t_flags |= TF_ACKNOW;
    638681            tcp_output(pData, tp);
     682            SOCKET_UNLOCK(so);
    639683            return;
    640684        }
     
    736780                tp->t_state = TCPS_SYN_RECEIVED;
    737781            }
     782            SOCKET_UNLOCK(so);
    738783            return;
    739784
     
    765810            tp->t_timer[TCPT_KEEP] = TCPTV_KEEP_INIT;
    766811            tcpstat.tcps_accepts++;
     812            Log2(("hit trimthenstep6\n"));
    767813            goto trimthenstep6;
    768814        } /* case TCPS_LISTEN */
     
    854900            tp->snd_wl1 = ti->ti_seq - 1;
    855901            tp->rcv_up = ti->ti_seq;
     902            Log2(("hit6"));
    856903            goto step6;
    857904    } /* switch tp->t_state */
     
    9851032                iss = tp->rcv_nxt + TCP_ISSINCR;
    9861033                tp = tcp_close(pData, tp);
     1034                SOCKET_UNLOCK(tp->t_socket);
    9871035                goto findso;
    9881036            }
     
    11171165            tp->snd_wl1 = ti->ti_seq - 1;
    11181166            /* Avoid ack processing; snd_una==ti_ack  =>  dup ack */
     1167            Log2(("hit synrx_to_est\n"));
    11191168            goto synrx_to_est;
    11201169            /* fall into ... */
     
    12011250            }
    12021251synrx_to_est:
     1252            Log2(("enter synrx_to_est\n"));
    12031253            /*
    12041254             * If the congestion window was inflated to account
     
    14291479            tp->rcv_up = tp->rcv_nxt;
    14301480dodata:
     1481    Log2(("do data hit!\n"));
    14311482
    14321483    /*
     
    15671618        tcp_output(pData, tp);
    15681619
     1620    SOCKET_UNLOCK(so);
    15691621    return;
    15701622
     
    15801632    tp->t_flags |= TF_ACKNOW;
    15811633    (void) tcp_output(pData, tp);
     1634    SOCKET_UNLOCK(so);
    15821635    return;
    15831636
    15841637dropwithreset:
    15851638    /* reuses m if m!=NULL, m_free() unnecessary */
    1586     Log2(("drop with reset\n"));
    15871639    if (tiflags & TH_ACK)
    15881640        tcp_respond(pData, tp, ti, m, (tcp_seq)0, ti->ti_ack, TH_RST);
     
    15941646    }
    15951647
     1648    if (so != &tcb)
     1649        SOCKET_UNLOCK(so);
    15961650    return;
    15971651
     
    16001654     * Drop space held by incoming segment and return.
    16011655     */
    1602     Log2(("drop\n"));
    16031656    m_free(pData, m);
    16041657
     1658    SOCKET_UNLOCK(so);
    16051659    return;
    16061660}
  • trunk/src/VBox/Devices/Network/slirp/tcp_timer.c

    r15845 r16443  
    4444tcp_fasttimo(PNATState pData)
    4545{
    46     register struct socket *so;
     46    register struct socket *so, *so_next;
    4747    register struct tcpcb *tp;
    4848
     
    5151    so = tcb.so_next;
    5252    if (so)
    53         for (; so != &tcb; so = so->so_next)
     53        QSOCKET_FOREACH (so, so_next,tcp)
     54        /* { */
    5455            if (   (tp = (struct tcpcb *)so->so_tcpcb)
    5556                && (tp->t_flags & TF_DELACK))
     
    5859                tp->t_flags |= TF_ACKNOW;
    5960                tcpstat.tcps_delack++;
    60                 (void) tcp_output(pData, tp);
    61             }
     61                TCP_OUTPUT(pData, tp);
     62            }
     63        LOOP_LABEL(tcp, so, so_next);
     64        }
    6265}
    6366
     
    8285    if (ip == 0)
    8386        return;
    84     for (; ip != &tcb; ip = ipnxt)
    85     {
     87    QSOCKET_FOREACH(ip, ipnxt, tcp)
     88    /* { */
    8689        ipnxt = ip->so_next;
    8790        tp = sototcpcb(ip);
    8891        if (tp == 0)
    89             continue;
     92            CONTINUE(tcp);
    9093        for (i = 0; i < TCPT_NTIMERS; i++)
    9194        {
     
    102105tpgone:
    103106        ;
     107    LOOP_LABEL(tcp, ip, ipnxt);
    104108    }
    105109    tcp_iss += TCP_ISSINCR / PR_SLOWHZ;         /* increment iss */
  • trunk/src/VBox/Devices/Network/slirp/udp.c

    r16291 r16443  
    384384            /* enable broadcast for later use */
    385385            setsockopt(so->s, SOL_SOCKET, SO_BROADCAST, (const char *)&opt, sizeof(opt));
     386            status = getsockname(so->s, &sa_addr, &socklen);
     387            Assert(status == 0 && sa_addr.sa_family == AF_INET);
     388            so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
     389            so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
    386390            SOCKET_LOCK_CREATE(so);
    387391            QSOCKET_LOCK(udb);
    388392            insque(pData, so,&udb);
    389393            QSOCKET_UNLOCK(udb);
    390             status = getsockname(so->s, &sa_addr, &socklen);
    391             Assert(status == 0 && sa_addr.sa_family == AF_INET);
    392             so->so_hlport = ((struct sockaddr_in *)&sa_addr)->sin_port;
    393             so->so_hladdr.s_addr = ((struct sockaddr_in *)&sa_addr)->sin_addr.s_addr;
    394394        }
    395395    }
     
    403403    {
    404404        closesocket(so->s);
     405        QSOCKET_LOCK(udb);
    405406        sofree(pData, so);
     407        QSOCKET_UNLOCK(udb);
    406408    }
    407409}
     
    699701    so->s = socket(AF_INET,SOCK_DGRAM,0);
    700702    so->so_expire = curtime + SO_EXPIRE;
     703    SOCKET_LOCK_CREATE(so);
     704    QSOCKET_LOCK(udb);
    701705    insque(pData, so,&udb);
     706    QSOCKET_UNLOCK(udb);
    702707
    703708    addr.sin_family = AF_INET;
注意: 瀏覽 TracChangeset 來幫助您使用更動檢視器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette