VirtualBox

Changeset 7831 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Apr 9, 2008 12:31:12 PM (17 years ago)
Author:
vboxsync
Message:

net: moved the wait/notify mechanism for receive buffers into the device

Location:
trunk/src/VBox/Devices/Network
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Network/DevPCNet.cpp

    r7795 r7831  
    114114
    115115#if HC_ARCH_BITS == 64
    116     uint32_t                            Alignment;
     116    uint32_t                            Alignment1;
    117117#endif
    118118
     
    137137    uint16_t                            aMII[MII_MAX_REG];
    138138    uint16_t                            u16CSR0LastSeenByGuest;
    139     uint16_t                            Alignment0[HC_ARCH_BITS == 32 ? 2 : 4];
     139    uint16_t                            Alignment2[HC_ARCH_BITS == 32 ? 2 : 4];
    140140    /** Last time we polled the queues */
    141141    uint64_t                            u64LastPoll;
     
    144144    uint32_t                            cbSendFrame;
    145145#if HC_ARCH_BITS == 64
    146     uint32_t                            Alignment2;
     146    uint32_t                            Alignment3;
    147147#endif
    148148    /** Buffer address of current send frame */
     
    215215    /** Access critical section. */
    216216    PDMCRITSECT                         CritSect;
     217    /** Event semaphore for blocking on receive. */
     218    RTSEMEVENT                          hEventOutOfRxSpace;
     219    /** We are waiting/about to start waiting for more receive buffers. */
     220    bool volatile                       fMaybeOutOfSpace;
     221    uint8_t                             Alignment5[HC_ARCH_BITS == 64 ? 7 : 3];
    217222
    218223#ifdef PCNET_NO_POLLING
     
    233238
    234239#if HC_ARCH_BITS == 64
    235     uint32_t                            Alignment3;
     240    uint32_t                            Alignment6;
    236241#endif
    237242
     
    278283    STAMPROFILEADV                      StatRdtePollGC;
    279284    STAMPROFILEADV                      StatRdtePollHC;
     285    STAMPROFILE                         StatRxOverflow;
     286    STAMCOUNTER                         StatRxOverflowWakeup;
    280287    STAMCOUNTER                         aStatXmitFlush[16];
    281288    STAMCOUNTER                         aStatXmitChainCounts[16];
     
    295302    STAMCOUNTER                         StatRingWriteFailedGC;
    296303
    297     STAMCOUNTER                         StatRingWriteOutsideRangeHC;
    298     STAMCOUNTER                         StatRingWriteOutsideRangeR0;
    299     STAMCOUNTER                         StatRingWriteOutsideRangeGC;
     304    STAMCOUNTER                         StatRingWriteOutsideHC;
     305    STAMCOUNTER                         StatRingWriteOutsideR0;
     306    STAMCOUNTER                         StatRingWriteOutsideGC;
    300307# endif
    301308#endif /* VBOX_WITH_STATISTICS */
     
    11631170        else
    11641171        {
    1165             STAM_COUNTER_INC(&CTXALLSUFF(pData->StatRingWriteOutsideRange)); ;
     1172            STAM_COUNTER_INC(&CTXALLSUFF(pData->StatRingWriteOutside)); ;
    11661173            return VINF_SUCCESS;    /* outside of the ring range */
    11671174        }
     
    15641571
    15651572#ifdef IN_RING3
     1573static DECLCALLBACK(void) pcnetWakeupReceive(PPDMDEVINS pDevIns)
     1574{
     1575    PCNetState *pData = PDMINS2DATA(pDevIns, PCNetState *);
     1576    STAM_COUNTER_INC(&pData->StatRxOverflowWakeup);
     1577    if (pData->hEventOutOfRxSpace != NIL_RTSEMEVENT)
     1578        RTSemEventSignal(pData->hEventOutOfRxSpace);
     1579}
     1580
    15661581static DECLCALLBACK(bool) pcnetCanRxQueueConsumer(PPDMDEVINS pDevIns, PPDMQUEUEITEMCORE pItem)
    15671582{
    1568     PCNetState *pData = PDMINS2DATA(pDevIns, PCNetState *);
    1569     if (pData->pDrv)
    1570         pData->pDrv->pfnNotifyCanReceive(pData->pDrv);
     1583    pcnetWakeupReceive(pDevIns);
    15711584    return true;
    15721585}
    1573 #endif
     1586#endif /* IN_RING3 */
    15741587
    15751588
     
    16151628                CSR_CRBC(pData) = rmd.rmd1.bcnt;               /* Receive Byte Count */
    16161629                CSR_CRST(pData) = ((uint32_t *)&rmd)[1] >> 16; /* Receive Status */
     1630                if (pData->fMaybeOutOfSpace)
     1631                {
    16171632#ifdef IN_RING3
    1618                 if (pData->pDrv)
    1619                     pData->pDrv->pfnNotifyCanReceive(pData->pDrv);
     1633                    pcnetWakeupReceive(PCNETSTATE_2_DEVINS(pData));
    16201634#else
    1621                 PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(CTXSUFF(pData->pCanRxQueue));
    1622                 if (pItem)
    1623                     PDMQueueInsert(CTXSUFF(pData->pCanRxQueue), pItem);
    1624 #endif
     1635                    PPDMQUEUEITEMCORE pItem = PDMQueueAlloc(CTXSUFF(pData->pCanRxQueue));
     1636                    if (pItem)
     1637                        PDMQueueInsert(CTXSUFF(pData->pCanRxQueue), pItem);
     1638#endif
     1639                }
    16251640            }
    16261641            else
     
    42244239 * This must be called before the pfnRecieve() method is called.
    42254240 *
    4226  * @returns Number of bytes the driver can receive.
     4241 * @returns VBox status code.
    42274242 * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    4228  * @thread  EMT
    4229  */
    4230 static DECLCALLBACK(size_t) pcnetCanReceive(PPDMINETWORKPORT pInterface)
    4231 {
    4232     size_t cb = 0;
    4233     int    rc;
    4234     PCNetState *pData = INETWORKPORT_2_DATA(pInterface);
    4235 
    4236     rc = PDMCritSectEnter(&pData->CritSect, VERR_SEM_BUSY);
     4243 */
     4244static int pcnetCanReceive(PCNetState *pData)
     4245{
     4246    int rc = PDMCritSectEnter(&pData->CritSect, VERR_SEM_BUSY);
    42374247    AssertReleaseRC(rc);
     4248
     4249    rc = VERR_NET_NO_BUFFER_SPACE;
    42384250
    42394251    if (RT_LIKELY(!CSR_DRX(pData) && !CSR_STOP(pData) && !CSR_SPND(pData)))
     
    42424254            pcnetRdtePoll(pData);
    42434255
    4244         if (HOST_IS_OWNER(CSR_CRST(pData)))
    4245         {
     4256        if (RT_UNLIKELY(HOST_IS_OWNER(CSR_CRST(pData))))
    42464257            /** @todo Notify the guest _now_. Will potentially increase the interrupt load */
    42474258            pData->aCSR[0] |= 0x1000; /* Set MISS flag */
     4259        else
     4260            rc = VINF_SUCCESS;
     4261    }
     4262
     4263    PDMCritSectLeave(&pData->CritSect);
     4264    return rc;
     4265}
     4266
     4267/**
     4268 *
     4269 */
     4270static DECLCALLBACK(int) pcnetWaitReceiveAvail(PPDMINETWORKPORT pInterface, unsigned cMillies)
     4271{
     4272    PCNetState *pData = INETWORKPORT_2_DATA(pInterface);
     4273
     4274    int rc = pcnetCanReceive(pData);
     4275    if (RT_SUCCESS(rc))
     4276        return VINF_SUCCESS;
     4277    if (RT_UNLIKELY(cMillies == 0))
     4278        return VERR_NET_NO_BUFFER_SPACE;
     4279
     4280    rc = VERR_INTERRUPTED;
     4281    ASMAtomicXchgBool(&pData->fMaybeOutOfSpace, true);
     4282    STAM_PROFILE_START(&pData->StatRxOverflow, a);
     4283    while (RT_LIKELY(PDMDevHlpVMState(pData->CTXSUFF(pDevIns)) == VMSTATE_RUNNING))
     4284    {
     4285        int rc2 = pcnetCanReceive(pData);
     4286        if (RT_SUCCESS(rc2))
     4287        {
     4288            rc = VINF_SUCCESS;
     4289            break;
    42484290        }
    4249         else
    4250         {
    4251             /* byte count stored in two's complement 12 bits wide */
    4252             Log(("#%d pcnetCanReceiveNoSync %d bytes\n", PCNET_INST_NR, 4096 - CSR_CRBC(pData)));
    4253             cb = 4096 - CSR_CRBC(pData);
    4254         }
    4255     }
    4256 
    4257     PDMCritSectLeave(&pData->CritSect);
    4258     return cb;
    4259 }
    4260 
     4291        LogFlow(("pcnetWaitReceiveAvail: waiting cMillies=%u...\n", cMillies));
     4292        RTSemEventWait(pData->hEventOutOfRxSpace, cMillies);
     4293    }
     4294    STAM_PROFILE_STOP(&pData->StatRxOverflow, a);
     4295    ASMAtomicXchgBool(&pData->fMaybeOutOfSpace, false);
     4296
     4297    return rc;
     4298}
    42614299
    42624300/**
     
    44574495        RTSemEventDestroy(pData->hSendEventSem);
    44584496        pData->hSendEventSem = NIL_RTSEMEVENT;
     4497        RTSemEventSignal(pData->hEventOutOfRxSpace);
     4498        RTSemEventDestroy(pData->hEventOutOfRxSpace);
    44594499        PDMR3CritSectDelete(&pData->CritSect);
    44604500    }
     
    45594599    pData->IBase.pfnQueryInterface          = pcnetQueryInterface;
    45604600    /* INeworkPort */
    4561     pData->INetworkPort.pfnCanReceive       = pcnetCanReceive;
     4601    pData->INetworkPort.pfnWaitReceiveAvail = pcnetWaitReceiveAvail;
    45624602    pData->INetworkPort.pfnReceive          = pcnetReceive;
    45634603    /* INetworkConfig */
     
    47024742        return rc;
    47034743
     4744    rc = RTSemEventCreate(&pData->hEventOutOfRxSpace);
     4745    AssertRC(rc);
     4746
    47044747    /*
    47054748     * Create the transmit queue.
     
    47974840    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatAPROMRead,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling APROM reads",              "/Devices/PCNet%d/IO/APROMRead", iInstance);
    47984841    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatAPROMWrite,         STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling APROM writes",             "/Devices/PCNet%d/IO/APROMWrite", iInstance);
    4799     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOReadGC,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNetIO reads in GC",      "/Devices/PCNet%d/IO/ReadGC", iInstance);
    4800     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOReadHC,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNetIO reads in HC",      "/Devices/PCNet%d/IO/ReadHC", iInstance);
    4801     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOWriteGC,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet IO writes in GC",    "/Devices/PCNet%d/IO/WriteGC", iInstance);
    4802     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOWriteHC,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet IO writes in HC",    "/Devices/PCNet%d/IO/WriteHC", iInstance);
    4803     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatTimer,              STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet Timer",              "/Devices/PCNet%d/Timer", iInstance);
    4804     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatReceive,            STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet receive",            "/Devices/PCNet%d/Receive", iInstance);
     4842    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOReadGC,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in GC",           "/Devices/PCNet%d/IO/ReadGC", iInstance);
     4843    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOReadHC,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO reads in HC",           "/Devices/PCNet%d/IO/ReadHC", iInstance);
     4844    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOWriteGC,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in GC",          "/Devices/PCNet%d/IO/WriteGC", iInstance);
     4845    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatIOWriteHC,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling IO writes in HC",          "/Devices/PCNet%d/IO/WriteHC", iInstance);
     4846    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatTimer,              STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling Timer",                    "/Devices/PCNet%d/Timer", iInstance);
     4847    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatReceive,            STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling receive",                  "/Devices/PCNet%d/Receive", iInstance);
     4848    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRxOverflow,         STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling RX overflows",        "/Devices/PCNet%d/RxOverflow", iInstance);
     4849    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRxOverflowWakeup,   STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Nr of RX overflow wakeups",     "/Devices/PCNet%d/RxOverflowWakeup", iInstance);
    48054850#endif
    48064851    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatReceiveBytes,       STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data received",            "/Devices/PCNet%d/ReceiveBytes", iInstance);
    48074852#ifdef VBOX_WITH_STATISTICS
    4808     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatTransmit,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet transmit in HC",     "/Devices/PCNet%d/Transmit/Total", iInstance);
     4853    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatTransmit,           STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling transmits in HC",          "/Devices/PCNet%d/Transmit/Total", iInstance);
    48094854#endif
    48104855    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatTransmitBytes,      STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_BYTES,          "Amount of data transmitted",         "/Devices/PCNet%d/TransmitBytes", iInstance);
     
    48294874    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatXmitSkipCurrent,    STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "",                                   "/Devices/PCNet%d/Xmit/Skipped", iInstance, i + 1);
    48304875
    4831     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatInterrupt,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet interrupt checks",   "/Devices/PCNet%d/UpdateIRQ", iInstance);
    4832     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatPollTimer,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling PCNet poll timer",         "/Devices/PCNet%d/PollTimer", iInstance);
     4876    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatInterrupt,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling interrupt checks",         "/Devices/PCNet%d/UpdateIRQ", iInstance);
     4877    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatPollTimer,          STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling poll timer",               "/Devices/PCNet%d/PollTimer", iInstance);
    48334878    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatMIIReads,           STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Number of MII reads",                "/Devices/PCNet%d/MIIReads", iInstance);
    48344879# ifdef PCNET_NO_POLLING
     
    48414886    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteFailedR0,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of failed ring page writes",      "/Devices/PCNet%d/Ring/R0/Failed", iInstance);
    48424887    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteFailedGC,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of failed ring page writes",      "/Devices/PCNet%d/Ring/GC/Failed", iInstance);
    4843     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteOutsideRangeHC,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring range", "/Devices/PCNet%d/Ring/HC/Outside", iInstance);
    4844     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteOutsideRangeR0,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring range", "/Devices/PCNet%d/Ring/R0/Outside", iInstance);
    4845     PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteOutsideRangeGC,  STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES, "Nr of monitored writes outside ring range", "/Devices/PCNet%d/Ring/GC/Outside", iInstance);
     4888    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteOutsideHC, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of monitored writes outside ring","/Devices/PCNet%d/Ring/HC/Outside", iInstance);
     4889    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteOutsideR0, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of monitored writes outside ring","/Devices/PCNet%d/Ring/R0/Outside", iInstance);
     4890    PDMDevHlpSTAMRegisterF(pDevIns, &pData->StatRingWriteOutsideGC, STAMTYPE_COUNTER, STAMVISIBILITY_ALWAYS, STAMUNIT_OCCURENCES,     "Nr of monitored writes outside ring","/Devices/PCNet%d/Ring/GC/Outside", iInstance);
    48464891# endif /* PCNET_NO_POLLING */
    48474892#endif
  • trunk/src/VBox/Devices/Network/DrvIntNet.cpp

    r6300 r7831  
    7878    /** Event semaphore the Thread waits on while the VM is suspended. */
    7979    RTSEMEVENT              EventSuspended;
    80     /** Indicates that we're in waiting for recieve space to become available. */
    81     bool volatile           fOutOfSpace;
    82     /** Event semaphore the Thread sleeps on while polling for more
    83      * buffer space to become available.
    84      * @todo We really need the network device to signal this! */
    85     RTSEMEVENT              EventOutOfSpace;
    8680    /** Set if the link is down.
    8781     * When the link is down all incoming packets will be dropped. */
     
    9589    /** Profiling packet receive runs. */
    9690    STAMPROFILEADV          StatReceive;
    97     /** Number of receive overflows. */
    98     STAMPROFILE             StatRecvOverflows;
    9991#endif /* VBOX_WITH_STATISTICS */
    10092
     
    315307
    316308/**
    317  * More receive buffer has become available.
    318  *
    319  * This is called when the NIC frees up receive buffers.
    320  *
    321  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    322  * @remark  This function isn't called by pcnet nor yet.
    323  * @thread  EMT
    324  */
    325 static DECLCALLBACK(void) drvIntNetNotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    326 {
    327     PDRVINTNET pThis = PDMINETWORKCONNECTOR_2_DRVINTNET(pInterface);
    328     if (pThis->fOutOfSpace)
    329     {
    330         LogFlow(("drvIntNetNotifyCanReceive: signaling\n"));
    331         RTSemEventSignal(pThis->EventOutOfSpace);
    332     }
    333 }
    334 
    335 
    336 /**
    337309 * Wait for space to become available up the driver/device chain.
    338310 *
     
    347319    LogFlow(("drvIntNetAsyncIoWaitForSpace: cbFrame=%zu\n", cbFrame));
    348320    STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
    349     STAM_PROFILE_START(&pData->StatRecvOverflows, b);
    350 
    351     ASMAtomicXchgSize(&pThis->fOutOfSpace, true);
    352     int rc;
    353     unsigned cYields = 0;
    354     for (;;)
    355     {
    356         /* yield/sleep */
    357         if (   !RTThreadYield()
    358             || ++cYields % 100 == 0)
    359         {
    360             /** @todo we need a callback from the device which can wake us up here. */
    361             rc = RTSemEventWait(pThis->EventOutOfSpace, 1);
    362             if (    VBOX_FAILURE(rc)
    363                 &&  rc != VERR_TIMEOUT)
    364                 break;
    365         }
    366         if (pThis->enmState != ASYNCSTATE_RUNNING)
    367         {
    368             rc = VERR_STATE_CHANGED;
    369             break;
    370         }
    371 
    372         /* retry */
    373         size_t cbMax = pThis->pPort->pfnCanReceive(pThis->pPort);
    374         if (cbMax >= cbFrame)
    375         {
    376             rc = VINF_SUCCESS;
    377             break;
    378         }
    379     }
    380     ASMAtomicXchgSize(&pThis->fOutOfSpace, false);
    381 
    382     STAM_PROFILE_STOP(&pThis->StatRecvOverflows, b);
     321    int rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
    383322    STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
    384323    LogFlow(("drvIntNetAsyncIoWaitForSpace: returns %Vrc\n", rc));
     
    431370                 */
    432371                size_t cbFrame = pHdr->cbFrame;
    433                 size_t cbMax = pThis->pPort->pfnCanReceive(pThis->pPort);
     372                size_t cbMax = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, 0);
    434373                if (cbMax >= cbFrame)
    435374                {
     
    657596    ASMAtomicXchgSize(&pThis->enmState, ASYNCSTATE_TERMINATE);
    658597    ASMAtomicXchgSize(&pThis->fLinkDown, true);
    659     RTSEMEVENT EventOutOfSpace = pThis->EventOutOfSpace;
    660     pThis->EventOutOfSpace = NIL_RTSEMEVENT;
    661598    RTSEMEVENT EventSuspended = pThis->EventSuspended;
    662599    pThis->EventSuspended = NIL_RTSEMEVENT;
     
    681618    if (pThis->Thread != NIL_RTTHREAD)
    682619    {
    683         if (EventOutOfSpace != NIL_RTSEMEVENT)
    684             RTSemEventSignal(EventOutOfSpace);
    685620        if (EventSuspended != NIL_RTSEMEVENT)
    686621            RTSemEventSignal(EventSuspended);
     
    693628     * Destroy the semaphores.
    694629     */
    695     if (EventOutOfSpace != NIL_RTSEMEVENT)
    696         RTSemEventDestroy(EventOutOfSpace);
    697630    if (EventSuspended != NIL_RTSEMEVENT)
    698631        RTSemEventDestroy(EventSuspended);
     
    721654    pThis->Thread                       = NIL_RTTHREAD;
    722655    pThis->EventSuspended               = NIL_RTSEMEVENT;
    723     pThis->EventOutOfSpace              = NIL_RTSEMEVENT;
    724656    pThis->enmState                     = ASYNCSTATE_SUSPENDED;
    725657    pThis->fActivateEarly               = false;
     
    730662    pThis->INetworkConnector.pfnSetPromiscuousMode  = drvIntNetSetPromiscuousMode;
    731663    pThis->INetworkConnector.pfnNotifyLinkChanged   = drvIntNetNotifyLinkChanged;
    732     pThis->INetworkConnector.pfnNotifyCanReceive    = drvIntNetNotifyCanReceive;
    733664
    734665    /*
     
    809740     */
    810741    rc = RTSemEventCreate(&pThis->EventSuspended);
    811     if (VBOX_FAILURE(rc))
    812         return rc;
    813     rc = RTSemEventCreate(&pThis->EventOutOfSpace);
    814742    if (VBOX_FAILURE(rc))
    815743        return rc;
     
    871799    RTStrPrintf(szStatName, sizeof(szStatName), "/Net/IntNet%d/Receive",        pDrvIns->iInstance);
    872800    pDrvIns->pDrvHlp->pfnSTAMRegister(pDrvIns, &pThis->StatReceive,             STAMTYPE_PROFILE, szStatName,   STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.");
    873     RTStrPrintf(szStatName, sizeof(szStatName), "/Net/IntNet%d/RecvOverflows",  pDrvIns->iInstance);
    874     pDrvIns->pDrvHlp->pfnSTAMRegister(pDrvIns, &pThis->StatRecvOverflows,       STAMTYPE_PROFILE, szStatName,   STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.");
    875801    RTStrPrintf(szStatName, sizeof(szStatName), "/Net/IntNet%d/Transmit",       pDrvIns->iInstance);
    876802    pDrvIns->pDrvHlp->pfnSTAMRegister(pDrvIns, &pThis->StatTransmit,            STAMTYPE_PROFILE, szStatName,   STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.");
  • trunk/src/VBox/Devices/Network/DrvNAT.cpp

    r6374 r7831  
    158158
    159159/**
    160  * More receive buffer has become available.
    161  *
    162  * This is called when the NIC frees up receive buffers.
    163  *
    164  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    165  * @thread  EMT
    166  */
    167 static DECLCALLBACK(void) drvNATNotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    168 {
    169     LogFlow(("drvNATNotifyCanReceive:\n"));
    170     /** @todo do something useful here. */
    171 }
    172 
    173 
    174 /**
    175160 * Poller callback.
    176161 */
     
    215200        return 0;
    216201
    217     return pData->pPort->pfnCanReceive(pData->pPort);
     202    int rc =  pData->pPort->pfnWaitReceiveAvail(pData->pPort, 0);
     203    return RT_SUCCESS(rc);
    218204}
    219205
     
    405391    pData->INetworkConnector.pfnSetPromiscuousMode = drvNATSetPromiscuousMode;
    406392    pData->INetworkConnector.pfnNotifyLinkChanged  = drvNATNotifyLinkChanged;
    407     pData->INetworkConnector.pfnNotifyCanReceive   = drvNATNotifyCanReceive;
    408393
    409394    /*
  • trunk/src/VBox/Devices/Network/DrvNetSniffer.cpp

    r5999 r7831  
    183183
    184184/**
    185  * More receive buffer has become available.
    186  *
    187  * This is called when the NIC frees up receive buffers.
    188  *
    189  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    190  * @thread  EMT
    191  */
    192 static DECLCALLBACK(void) drvNetSnifferNotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    193 {
    194     LogFlow(("drvNetSnifferNotifyCanReceive:\n"));
    195     PDRVNETSNIFFER pData = PDMINETWORKCONNECTOR_2_DRVNETSNIFFER(pInterface);
    196     if (pData->pConnector)
    197         pData->pConnector->pfnNotifyCanReceive(pData->pConnector);
    198 }
    199 
    200 
    201 /**
    202185 * Check how much data the device/driver can receive data now.
    203186 * This must be called before the pfnRecieve() method is called.
     
    207190 * @thread  EMT
    208191 */
    209 static DECLCALLBACK(size_t) drvNetSnifferCanReceive(PPDMINETWORKPORT pInterface)
     192static DECLCALLBACK(int) drvNetSnifferWaitReceiveAvail(PPDMINETWORKPORT pInterface, unsigned cMillies)
    210193{
    211194    PDRVNETSNIFFER pData = PDMINETWORKPORT_2_DRVNETSNIFFER(pInterface);
    212     return pData->pPort->pfnCanReceive(pData->pPort);
     195    return pData->pPort->pfnWaitReceiveAvail(pData->pPort, cMillies);
    213196}
    214197
     
    335318    pData->INetworkConnector.pfnSetPromiscuousMode  = drvNetSnifferSetPromiscuousMode;
    336319    pData->INetworkConnector.pfnNotifyLinkChanged   = drvNetSnifferNotifyLinkChanged;
    337     pData->INetworkConnector.pfnNotifyCanReceive    = drvNetSnifferNotifyCanReceive;
    338320    /* INetworkPort */
    339     pData->INetworkPort.pfnCanReceive   = drvNetSnifferCanReceive;
    340     pData->INetworkPort.pfnReceive      = drvNetSnifferReceive;
     321    pData->INetworkPort.pfnWaitReceiveAvail         = drvNetSnifferWaitReceiveAvail;
     322    pData->INetworkPort.pfnReceive                  = drvNetSnifferReceive;
    341323
    342324    /*
  • trunk/src/VBox/Devices/Network/DrvTAP.cpp

    r7799 r7831  
    114114    /** Reader thread. */
    115115    PPDMTHREAD              pThread;
    116     /** We are waiting for more receive buffers. */
    117     bool volatile           fMaybeOutOfSpace;
    118     /** Event semaphore for blocking on receive. */
    119     RTSEMEVENT              EventOutOfSpace;
    120116
    121117#ifdef VBOX_WITH_STATISTICS
     
    132128    /** Profiling packet receive runs. */
    133129    STAMPROFILEADV          StatReceive;
    134     /** Profiling receive descriptor overflows. */
    135     STAMPROFILE             StatRecvOverflows;
    136130#endif /* VBOX_WITH_STATISTICS */
    137131
     
    228222
    229223/**
    230  * More receive buffer has become available.
    231  *
    232  * This is called when the NIC frees up receive buffers.
    233  *
    234  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    235  * @thread  EMT
    236  */
    237 static DECLCALLBACK(void) drvTAPNotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    238 {
    239     PDRVTAP pData = PDMINETWORKCONNECTOR_2_DRVTAP(pInterface);
    240 
    241     LogFlow(("drvTAPNotifyCanReceive:\n"));
    242     /** @todo r=bird: A better solution would be to ditch the NotifyCanReceive callback and
    243      *                instead change the CanReceive to do all the work. That is, CanReceive
    244      *                will not return until there are receive buffers available. This will
    245      *                reduce the amount of code duplication, and would permit pcnet to avoid
    246      *                queuing unnecessary ring-3 tasks.
    247      */
    248     if (pData->fMaybeOutOfSpace)
    249         RTSemEventSignal(pData->EventOutOfSpace);
    250 }
    251 
    252 
    253 /**
    254224 * Asynchronous I/O thread for handling receive.
    255225 *
     
    267237
    268238    STAM_PROFILE_ADV_START(&pData->StatReceive, a);
    269 
    270     int rc = RTSemEventCreate(&pData->EventOutOfSpace);
    271     AssertRC(rc);
    272239
    273240    /*
     
    288255        STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
    289256        errno=0;
    290         rc = poll(&aFDs[0], ELEMENTS(aFDs), -1 /* infinite */);
     257        int rc = poll(&aFDs[0], ELEMENTS(aFDs), -1 /* infinite */);
    291258
    292259        /* this might have changed in the meantime */
     
    331298                 *    overflow error to allocate more receive buffers
    332299                 */
    333                 ASMAtomicXchgBool(&pData->fMaybeOutOfSpace, true);
    334                 size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort);
    335                 if (cbMax == 0)
    336                 {
    337                     /** @todo receive overflow handling needs serious improving! */
    338                     STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
    339                     STAM_PROFILE_START(&pData->StatRecvOverflows, b);
    340                     while (   cbMax == 0
    341                            && pThread->enmState == PDMTHREADSTATE_RUNNING)
    342                     {
    343                         LogFlow(("drvTAPAsyncIoThread: cbMax=%d cbRead=%d waiting...\n", cbMax, cbRead));
    344                         /* We get signalled by the network driver. 50ms is just for sanity */
    345                         RTSemEventWait(pData->EventOutOfSpace, 50);
    346                         cbMax = pData->pPort->pfnCanReceive(pData->pPort);
    347                     }
    348                     STAM_PROFILE_STOP(&pData->StatRecvOverflows, b);
    349                     STAM_PROFILE_ADV_START(&pData->StatReceive, a);
    350                 }
    351                 ASMAtomicXchgBool(&pData->fMaybeOutOfSpace, false);
    352                 if (pThread->enmState != PDMTHREADSTATE_RUNNING)
     300                STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
     301                int rc = pData->pPort->pfnWaitReceiveAvail(pData->pPort, RT_INDEFINITE_WAIT);
     302                STAM_PROFILE_ADV_START(&pData->StatReceive, a);
     303                if (RT_FAILURE(rc))
    353304                    break;
    354305
     
    405356
    406357
    407     rc = RTSemEventDestroy(pData->EventOutOfSpace);
    408     AssertRC(rc);
    409     pData->EventOutOfSpace = NIL_RTSEMEVENT;
    410 
    411358    LogFlow(("drvTAPAsyncIoThread: returns %Vrc\n", VINF_SUCCESS));
    412359    STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
     
    425372{
    426373    PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP);
    427 
    428     /* Ensure that it does not spin in the CanReceive loop.
    429        (May assert in IPRT if we're really unlucky.) */
    430     if (pData->fMaybeOutOfSpace)
    431         RTSemEventSignal(pData->EventOutOfSpace);
    432374
    433375    int rc = RTFileWrite(pData->PipeWrite, "", 1, NULL);
     
    956898    pData->INetworkConnector.pfnSetPromiscuousMode  = drvTAPSetPromiscuousMode;
    957899    pData->INetworkConnector.pfnNotifyLinkChanged   = drvTAPNotifyLinkChanged;
    958     pData->INetworkConnector.pfnNotifyCanReceive    = drvTAPNotifyCanReceive;
    959900
    960901    /*
     
    10931034    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatTransmit,      STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet transmit runs.",  "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
    10941035    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatReceive,       STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet receive runs.",   "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
    1095     PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance);
    10961036#endif /* VBOX_WITH_STATISTICS */
    10971037
  • trunk/src/VBox/Devices/Network/DrvTAPOs2.cpp

    r6300 r7831  
    6262    /** Receiver thread. */
    6363    PPDMTHREAD              pThread;
    64     /** Event semaphore for blocking on receive. */
    65     RTSEMEVENT              EventOutOfSpace;
    66     /** We are checking or waiting for more receive buffers. */
    67     bool volatile           fMaybeOutOfSpace;
    6864    /** Set if the link is down.
    6965     * When the link is down all incoming packets will be dropped. */
     
    8783    /** Profiling packet receive runs. */
    8884    STAMPROFILEADV          StatReceive;
    89     STAMPROFILE             StatRecvOverflows;
    9085#endif /* VBOX_WITH_STATISTICS */
    9186
     
    209204    LogFlow(("%s: NotifyLinkChanged: enmLinkState=%d %d->%d\n", pThis->szName, pThis->fLinkDown, fLinkDown));
    210205    ASMAtomicXchgBool(&pThis->fLinkDown, fLinkDown);
    211 }
    212 
    213 
    214 /**
    215  * More receive buffer has become available.
    216  *
    217  * This is called when the NIC frees up receive buffers.
    218  *
    219  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    220  * @thread  EMT
    221  */
    222 static DECLCALLBACK(void) drvTAPOs2NotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    223 {
    224     PDRVTAPOS2 pThis = PDMINETWORKCONNECTOR_2_DRVTAPOS2(pInterface);
    225 
    226     /* don't waste time signalling the semaphore unnecessary */
    227     if (!pThis->fMaybeOutOfSpace)
    228         LogFlow(("%s: NotifyCanReceive: fMaybeOutOfSpace=false\n", pThis->szName));
    229     else
    230     {
    231         LogFlow(("%s: NotifyCanReceive: fMaybeOutOfSpace=true\n", pThis->szName));
    232         RTSemEventSignal(pThis->EventOutOfSpace);
    233     }
    234206}
    235207
     
    282254             * Wait for the device to have some room.
    283255             */
    284             ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, true);
    285             size_t cbMax = pThis->pPort->pfnCanReceive(pThis->pPort);
    286             if (cbMax == 0)
    287             {
    288                 STAM_PROFILE_ADV_STOP(&pThis->StatReceive, a);
    289                 STAM_PROFILE_START(&pThis->StatRecvOverflows, b);
    290                 while (   cbMax == 0
    291                        && pThread->enmState == PDMTHREADSTATE_RUNNING)
    292                 {
    293                     LogFlow(("%s: ReceiveThread: cbMax=%d cbRead=%d waiting...\n", pThis->szName, cbMax, cbRead));
    294                     RTSemEventWait(pThis->EventOutOfSpace, 50);
    295                     cbMax = pThis->pPort->pfnCanReceive(pThis->pPort);
    296                 }
    297                 STAM_PROFILE_STOP(&pThis->StatRecvOverflows, b);
    298                 STAM_PROFILE_ADV_START(&pThis->StatReceive, a);
    299             }
    300             ASMAtomicXchgBool(&pThis->fMaybeOutOfSpace, false);
    301             if (pThread->enmState != PDMTHREADSTATE_RUNNING)
    302                 break; /* just drop it, no big deal. */
     256            rc = pThis->pPort->pfnWaitReceiveAvail(pThis->pPort, RT_INDEFINITE_WAIT);
     257            if (RT_FAILURE(rc))
     258                break;
    303259
    304260            /*
     
    358314    AssertMsg(orc == 0, ("%d\n", orc)); NOREF(orc);
    359315
    360     /* wake it up if it's waiting for receive buffers. */
    361     if (pThis->fMaybeOutOfSpace)
    362         RTSemEventSignal(pThis->EventOutOfSpace);
    363 
    364316    return VINF_SUCCESS;
    365317}
     
    405357
    406358    /* PDM will destroy the thread for us, it's suspended right now. */
    407 
    408     /*
    409      * Destroy the out-of-space event semaphore.
    410      */
    411     if (pThis->EventOutOfSpace != NIL_RTSEMEVENTMULTI)
    412     {
    413         int rc = RTSemEventDestroy(pThis->EventOutOfSpace);
    414         AssertRC(rc);
    415         pThis->EventOutOfSpace = NIL_RTSEMEVENTMULTI;
    416     }
    417359
    418360    /*
     
    473415    pThis->INetworkConnector.pfnSetPromiscuousMode  = drvTAPOs2SetPromiscuousMode;
    474416    pThis->INetworkConnector.pfnNotifyLinkChanged   = drvTAPOs2NotifyLinkChanged;
    475     pThis->INetworkConnector.pfnNotifyCanReceive    = drvTAPOs2NotifyCanReceive;
    476417
    477418    /*
     
    590531                pThis->szName, pThis->iLan, pThis->iConnectedTo, Parm[0], Parm[1]));
    591532
    592     /*
    593      * Create the out-of-space semaphore and the async receiver thread.
    594      */
    595     rc = RTSemEventCreate(&pThis->EventOutOfSpace);
    596     AssertRCReturn(rc, rc);
    597 
    598533    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pThis->pThread, pThis, drvTAPOs2ReceiveThread, drvTAPOs2WakeupReceiveThread,
    599534                                  0, RTTHREADTYPE_IO, pThis->szName);
     
    610545    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatTransmit,      STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet transmit runs.",  "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
    611546    PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatReceive,       STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL,    "Profiling packet receive runs.",   "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
    612     PDMDrvHlpSTAMRegisterF(pDrvIns, &pThis->StatRecvOverflows, STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance);
    613547#endif /* VBOX_WITH_STATISTICS */
    614548
  • trunk/src/VBox/Devices/Network/DrvTAPWin32.cpp

    r7321 r7831  
    1818
    1919
    20 #define ASYNC_NETIO
    21 
    2220/*******************************************************************************
    2321*   Header Files                                                               *
     
    3230#include <iprt/string.h>
    3331#include <iprt/thread.h>
    34 #ifdef ASYNC_NETIO
    3532#include <iprt/asm.h>
    3633#include <iprt/semaphore.h>
    37 #endif
    3834
    3935#include <windows.h>
     
    6864    TAP_VERSION             tapVersion;
    6965
    70 #ifdef ASYNC_NETIO
    7166    /** The thread handle. NIL_RTTHREAD if no thread. */
    72     RTTHREAD                hThread;
     67    PPDMTHREAD              pThread;
    7368    /** The event semaphore the thread is waiting on. */
    7469    HANDLE                  hHaltAsyncEventSem;
    75     /** We are waiting for more receive buffers. */
    76     uint32_t volatile       fOutOfSpace;
    77     /** Event semaphore for blocking on receive. */
    78     RTSEMEVENT              EventOutOfSpace;
    79 #endif
    8070
    8171#ifdef DEBUG
     
    9787    /** Profiling packet receive runs. */
    9888    STAMPROFILEADV          StatReceive;
    99 # ifdef ASYNC_NETIO
    10089    STAMPROFILE             StatRecvOverflows;
    101 # endif
    10290#endif /* VBOX_WITH_STATISTICS */
    10391} DRVTAP, *PDRVTAP;
     
    191179
    192180/**
    193  * More receive buffer has become available.
    194  *
    195  * This is called when the NIC frees up receive buffers.
    196  *
    197  * @param   pInterface      Pointer to the interface structure containing the called function pointer.
    198  * @thread  EMT
    199  */
    200 static DECLCALLBACK(void) drvTAPW32NotifyCanReceive(PPDMINETWORKCONNECTOR pInterface)
    201 {
    202     PDRVTAP pData = PDMINETWORKCONNECTOR_2_DRVTAP(pInterface);
    203 
    204     LogFlow(("drvTAPW32NotifyCanReceive:\n"));
    205     if (ASMAtomicXchgU32(&pData->fOutOfSpace, false))
    206         RTSemEventSignal(pData->EventOutOfSpace);
    207 }
    208 
    209 
    210 #ifndef ASYNC_NETIO
    211 /**
    212  * Poller callback.
    213  */
    214 static DECLCALLBACK(void) drvTAPW32Poller(PPDMDRVINS pDrvIns)
    215 {
    216     DWORD rc = ERROR_SUCCESS;
    217     PDRVTAP pData = PDMINS2DATA(pDrvIns, PDRVTAP);
    218     STAM_PROFILE_ADV_START(&pData->StatReceive, a);
    219 
    220     /* check how much the device/driver can receive now. */
    221     size_t  cbMax = pData->pPort->pfnCanReceive(pData->pPort);
    222 
    223     while (cbMax)
    224     {
    225         if (cbMax > 0 && !pData->overlappedRead.hEvent)
    226         {
    227             BOOL  bRet;
    228 
    229             cbMax = RT_MIN(cbMax, sizeof(pData->readBuffer));
    230             memset(&pData->overlappedRead, 0, sizeof(pData->overlappedRead));
    231             pData->overlappedRead.hEvent = pData->hEventRead;
    232             bRet = ReadFile(pData->hFile, pData->readBuffer, cbMax, &pData->dwNumberOfBytesRead, &pData->overlappedRead);
    233             if (bRet == FALSE)
    234             {
    235                 rc = GetLastError();
    236                 AssertMsg(rc == ERROR_SUCCESS || rc == ERROR_IO_PENDING || rc == ERROR_MORE_DATA, ("ReadFileEx failed with rc=%d\n", rc));
    237                 if (rc != ERROR_IO_PENDING && rc != ERROR_MORE_DATA)
    238                     break;
    239             }
    240         }
    241         if (cbMax)
    242         {
    243             DWORD dwNumberOfBytesTransferred = 0;
    244 
    245             if (GetOverlappedResult(pData->hFile, &pData->overlappedRead, &dwNumberOfBytesTransferred, FALSE) == TRUE)
    246             {
    247                 /* push it to the driver. */
    248                 Log2(("drvTAPW32Poller%d: cbRead=%#x\n"
    249                       "%.*Vhxd\n", pData->InstanceNr,
    250                       dwNumberOfBytesTransferred, dwNumberOfBytesTransferred, pData->readBuffer));
    251 
    252                 STAM_COUNTER_INC(&pData->StatPktRecv);
    253                 STAM_COUNTER_ADD(&pData->StatPktRecvBytes, dwNumberOfBytesTransferred);
    254 
    255 #ifdef DEBUG
    256                 pData->dwLastWriteTime = timeGetTime();
    257                 Log(("drvTAPW32Receive %d bytes at %08x - delta %x\n", dwNumberOfBytesTransferred,
    258                      pData->dwLastWriteTime, pData->dwLastWriteTime - pData->dwLastReadTime));
    259 #endif
    260 
    261                 rc = pData->pPort->pfnReceive(pData->pPort, pData->readBuffer, dwNumberOfBytesTransferred);
    262                 AssertRC(rc);
    263 
    264                 memset(&pData->overlappedRead, 0, sizeof(pData->overlappedRead));
    265             }
    266             else
    267             {
    268                 rc = GetLastError();
    269                 Assert(rc == ERROR_IO_INCOMPLETE);
    270 
    271                 /* reset overlapped structure on aborted read operation */
    272                 if (rc != ERROR_IO_INCOMPLETE)
    273                 {
    274                     memset(&pData->overlappedRead, 0, sizeof(pData->overlappedRead));
    275                 }
    276                 break;
    277             }
    278         }
    279         cbMax = pData->pPort->pfnCanReceive(pData->pPort);
    280     }
    281     STAM_PROFILE_ADV_STOP(&pData->StatReceive, a);
    282 }
    283 #else /* !ASYNC_NETIO */
    284 /**
    285181 * Async I/O thread for an interface.
    286182 */
    287 static DECLCALLBACK(int) drvTAPW32AsyncIo(RTTHREAD ThreadSelf, void *pvUser)
     183static DECLCALLBACK(int) drvTAPW32AsyncIoThread(PPDMDRVINS pDrvIns, PPDMTHREAD pThread)
    288184{
    289185    PDRVTAP pData = (PDRVTAP)pvUser;
     
    291187    DWORD   rc = ERROR_SUCCESS, dwNumberOfBytesTransferred;
    292188
     189    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     190        return VINF_SUCCESS;
     191
    293192    Assert(pData);
    294193    haWait[0] = pData->hEventRead;
    295194    haWait[1] = pData->hHaltAsyncEventSem;
    296 
    297     rc = RTSemEventCreate(&pData->EventOutOfSpace);
    298     AssertRC(rc);
    299195
    300196    while(1)
     
    326222
    327223        /* Not very nice, but what else can we do? */
    328         size_t cbMax = pData->pPort->pfnCanReceive(pData->pPort);
    329         if (cbMax == 0)
    330         {
    331             STAM_PROFILE_START(&pData->StatRecvOverflows, b);
    332             while (cbMax == 0)
    333             {
    334 #if 1
    335                 ASMAtomicXchgU32(&pData->fOutOfSpace, true);
    336                 RTSemEventWait(pData->EventOutOfSpace, 50);
    337 #else
    338                 RTThreadSleep(16); /* @todo right value? */
    339 #endif
    340                 /* Check if the VM was terminated */
    341                 rc = WaitForSingleObject(haWait[1], 0);
    342                 if (rc == WAIT_OBJECT_0)
    343                 {
    344                     STAM_PROFILE_STOP(&pData->StatRecvOverflows, b);
    345                     goto exit_thread;
    346                 }
    347 
    348                 cbMax = pData->pPort->pfnCanReceive(pData->pPort);
    349             }
    350             ASMAtomicXchgU32(&pData->fOutOfSpace, false);
    351             STAM_PROFILE_STOP(&pData->StatRecvOverflows, b);
    352             Assert(cbMax >= dwNumberOfBytesTransferred);
    353         }
     224        rc = pData->pPort->pfnWaitReceiveAvail(pData->pPort, RT_INDEFINITE_WAIT);
     225        if (RT_FAILURE(rc))
     226            break;
    354227
    355228        STAM_COUNTER_INC(&pData->StatPktRecv);
     
    364237    }
    365238
    366 exit_thread:
    367239    SetEvent(pData->hHaltAsyncEventSem);
    368240    Log(("drvTAPW32AsyncIo: exit thread!!\n"));
    369241    return VINF_SUCCESS;
    370242}
    371 #endif /* !ASYNC_NETIO */
    372243
    373244/**
     
    412283    LogFlow(("drvTAPW32Destruct\n"));
    413284
    414 #ifdef ASYNC_NETIO
    415285    /** @todo this isn't a safe method to notify the async thread; it might be using the instance
    416286     *        data after we've been destroyed; could wait for it to terminate, but that's not
     
    418288     */
    419289    SetEvent(pData->hHaltAsyncEventSem);
    420 
    421     /* Ensure that it does not spin in the CanReceive loop. Do it _after_ we set set the
    422      * hHaltAsyncEventSem to ensure that we don't go into the loop again immediately. */
    423     if (ASMAtomicXchgU32(&pData->fOutOfSpace, false))
    424         RTSemEventSignal(pData->EventOutOfSpace);
    425290
    426291    /* Yield or else our async thread will never acquire the event semaphore */
     
    428293    /* Wait for the async thread to quit; up to half a second */
    429294    WaitForSingleObject(pData->hHaltAsyncEventSem, 500);
    430 #endif
    431295
    432296    mediastatus.fConnect = FALSE;
     
    466330    pData->INetworkConnector.pfnSetPromiscuousMode  = drvTAPW32SetPromiscuousMode;
    467331    pData->INetworkConnector.pfnNotifyLinkChanged   = drvTAPW32NotifyLinkChanged;
    468     pData->INetworkConnector.pfnNotifyCanReceive    = drvTAPW32NotifyCanReceive;
    469332
    470333    /*
     
    560423    memset(&pData->overlappedRead, 0, sizeof(pData->overlappedRead));
    561424
    562 #ifdef ASYNC_NETIO
    563425    pData->hHaltAsyncEventSem = CreateEvent(NULL, FALSE, FALSE, NULL);
    564426
    565427    /* Create asynchronous thread */
    566     rc = RTThreadCreate(&pData->hThread, drvTAPW32AsyncIo, (void *)pData, 128*1024, RTTHREADTYPE_IO, 0, "TAP");
    567     AssertRC(rc);
     428    rc = PDMDrvHlpPDMThreadCreate(pDrvIns, &pData->pThread, pData, drvTAPW32AsyncIoThread, drvTAPW32AsyncIoWakeup, 128 * _1K, RTTHREADTYPE_IO, "TAP");
     429    AssertRCReturn(rc, rc);
    568430
    569431    Assert(pData->hThread != NIL_RTTHREAD && pData->hHaltAsyncEventSem != NULL);
    570 #else
    571     /*
    572      * Register poller
    573      */
    574     rc = pDrvIns->pDrvHlp->pfnPDMPollerRegister(pDrvIns, drvTAPW32Poller);
    575     AssertRC(rc);
    576 #endif
    577432
    578433#ifdef VBOX_WITH_STATISTICS
     
    586441    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatTransmit,     STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet transmit runs.", "/Drivers/TAP%d/Transmit", pDrvIns->iInstance);
    587442    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatReceive,      STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_CALL, "Profiling packet receive runs.",  "/Drivers/TAP%d/Receive", pDrvIns->iInstance);
    588 # ifdef ASYNC_NETIO
    589443    PDMDrvHlpSTAMRegisterF(pDrvIns, &pData->StatRecvOverflows,STAMTYPE_PROFILE, STAMVISIBILITY_ALWAYS, STAMUNIT_TICKS_PER_OCCURENCE, "Profiling packet receive overflows.", "/Drivers/TAP%d/RecvOverflows", pDrvIns->iInstance);
    590 # endif
    591444#endif
    592445
Note: See TracChangeset for help on using the changeset viewer.

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