VirtualBox

Changeset 25148 in vbox


Ignore:
Timestamp:
Dec 2, 2009 2:20:41 PM (15 years ago)
Author:
vboxsync
Message:

#3987: Virtio: Fixed the race for TX queue notification state.

Location:
trunk/src/VBox/Devices
Files:
2 edited

Legend:

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

    r24982 r25148  
    114114    VPCISTATE               VPCI;
    115115
     116    PDMCRITSECT             csRx;                           /**< Protects RX queue. */
     117
    116118    PDMINETWORKPORT         INetworkPort;
    117119    PDMINETWORKCONFIG       INetworkConfig;
     
    250252}
    251253
     254DECLINLINE(int) vnetCsRxEnter(PVNETSTATE pState, int rcBusy)
     255{
     256    return PDMCritSectEnter(&pState->csRx, rcBusy);
     257}
     258
     259DECLINLINE(void) vnetCsRxLeave(PVNETSTATE pState)
     260{
     261    PDMCritSectLeave(&pState->csRx);
     262}
     263
    252264
    253265PDMBOTHCBDECL(uint32_t) vnetGetHostFeatures(void *pvState)
     
    313325    VNETSTATE *pState = (VNETSTATE*)pvState;
    314326    Log(("%s Reset triggered\n", INSTANCE(pState)));
     327
     328    int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
     329    if (RT_UNLIKELY(rc != VINF_SUCCESS))
     330    {
     331        LogRel(("vnetReset failed to enter RX critical section!\n"));
     332        return;
     333    }
    315334    vpciReset(&pState->VPCI);
     335    vnetCsRxLeave(pState);
     336
    316337    // TODO: Implement reset
    317338    if (pState->fCableConnected)
     
    358379    VNETSTATE *pState = (VNETSTATE *)pvUser;
    359380
     381    int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     382    if (RT_UNLIKELY(rc != VINF_SUCCESS))
     383        return;
    360384    STATUS |= VNET_S_LINK_UP;
    361385    vpciRaiseInterrupt(&pState->VPCI, VERR_SEM_BUSY, VPCI_ISR_CONFIG);
    362386    vnetWakeupReceive(pDevIns);
     387    vnetCsLeave(pState);
    363388}
    364389
     
    457482static int vnetCanReceive(VNETSTATE *pState)
    458483{
    459     int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     484    int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
     485    AssertRCReturn(rc, rc);
     486
    460487    LogFlow(("%s vnetCanReceive\n", INSTANCE(pState)));
    461488    if (!(pState->VPCI.uStatus & VPCI_STATUS_DRV_OK))
     
    475502
    476503    LogFlow(("%s vnetCanReceive -> %Vrc\n", INSTANCE(pState), rc));
    477     vnetCsLeave(pState);
     504    vnetCsRxLeave(pState);
    478505    return rc;
    479506}
     
    675702{
    676703    VNETSTATE *pState = IFACE_TO_STATE(pInterface, INetworkPort);
    677     int        rc = VINF_SUCCESS;
    678704
    679705    Log2(("%s vnetReceive: pvBuf=%p cb=%u\n", INSTANCE(pState), pvBuf, cb));
    680     rc = vnetCanReceive(pState);
     706    int rc = vnetCanReceive(pState);
    681707    if (RT_FAILURE(rc))
    682708        return rc;
     
    693719    if (vnetAddressFilter(pState, pvBuf, cb))
    694720    {
    695         rc = vnetHandleRxPacket(pState, pvBuf, cb);
    696         STAM_REL_COUNTER_ADD(&pState->StatReceiveBytes, cb);
     721        rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
     722        if (RT_SUCCESS(rc))
     723        {
     724            rc = vnetHandleRxPacket(pState, pvBuf, cb);
     725            STAM_REL_COUNTER_ADD(&pState->StatReceiveBytes, cb);
     726            vnetCsRxLeave(pState);
     727        }
    697728    }
    698729    vpciSetReadLed(&pState->VPCI, false);
    699730    STAM_PROFILE_ADV_STOP(&pState->StatReceive, a);
    700 
    701731    return rc;
    702732}
     
    856886    VNETSTATE *pState = (VNETSTATE*)pvUser;
    857887
     888    int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     889    if (RT_UNLIKELY(rc != VINF_SUCCESS))
     890        return;
    858891    vringSetNotification(&pState->VPCI, &pState->pTxQueue->VRing, true);
    859892    Log3(("%s vnetTxTimer: Expired, %d packets pending\n", INSTANCE(pState),
    860893          vringReadAvailIndex(&pState->VPCI, &pState->pTxQueue->VRing) - pState->pTxQueue->uNextAvailIndex));
    861894    vnetTransmitPendingPackets(pState, pState->pTxQueue);
     895    vnetCsLeave(pState);
    862896}
    863897
     
    11141148    VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
    11151149
    1116     int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     1150    int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
    11171151    if (RT_UNLIKELY(rc != VINF_SUCCESS))
    11181152        return rc;
    1119     vnetCsLeave(pState);
     1153    vnetCsRxLeave(pState);
    11201154    return VINF_SUCCESS;
    11211155}
     
    11681202    VNETSTATE* pState = PDMINS_2_DATA(pDevIns, VNETSTATE*);
    11691203
    1170     int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     1204    int rc = vnetCsRxEnter(pState, VERR_SEM_BUSY);
    11711205    if (RT_UNLIKELY(rc != VINF_SUCCESS))
    11721206        return rc;
    1173     vnetCsLeave(pState);
     1207    vnetCsRxLeave(pState);
    11741208    return VINF_SUCCESS;
    11751209}
     
    13951429                    ("Cannot allocate TX buffer for virtio-net device\n"), VERR_NO_MEMORY);
    13961430
     1431    /* Initialize critical section. */
     1432    char szTmp[sizeof(pState->VPCI.szInstance) + 2];
     1433    RTStrPrintf(szTmp, sizeof(szTmp), "%sRX", pState->VPCI.szInstance);
     1434    rc = PDMDevHlpCritSectInit(pDevIns, &pState->csRx, szTmp);
     1435    if (RT_FAILURE(rc))
     1436        return rc;
     1437
    13971438    /* Map our ports to IO space. */
    13981439    rc = PDMDevHlpPCIIORegionRegister(pDevIns, 0,
     
    15051546        pState->pTxBuf = NULL;
    15061547    }
     1548    if (PDMCritSectIsInitialized(&pState->csRx))
     1549        PDMR3CritSectDelete(&pState->csRx);
    15071550
    15081551    return vpciDestruct(&pState->VPCI);
     
    15631606    AssertLogRelReturnVoid(iLUN == 0);
    15641607
    1565     vnetCsEnter(pState, VERR_SEM_BUSY);
     1608    int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     1609    if (RT_FAILURE(rc))
     1610    {
     1611        LogRel(("vnetDetach failed to enter critical section!\n"));
     1612        return;
     1613    }
    15661614
    15671615    /*
     
    15941642    AssertLogRelReturn(iLUN == 0, VERR_PDM_NO_SUCH_LUN);
    15951643
    1596     vnetCsEnter(pState, VERR_SEM_BUSY);
     1644    int rc = vnetCsEnter(pState, VERR_SEM_BUSY);
     1645    if (RT_FAILURE(rc))
     1646    {
     1647        LogRel(("vnetAttach failed to enter critical section!\n"));
     1648        return rc;
     1649    }
    15971650
    15981651    /*
    15991652     * Attach the driver.
    16001653     */
    1601     int rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->VPCI.IBase, &pState->pDrvBase, "Network Port");
     1654    rc = PDMDevHlpDriverAttach(pDevIns, 0, &pState->VPCI.IBase, &pState->pDrvBase, "Network Port");
    16021655    if (RT_SUCCESS(rc))
    16031656    {
  • trunk/src/VBox/Devices/VirtIO/Virtio.cpp

    r25007 r25148  
    258258int vpciRaiseInterrupt(VPCISTATE *pState, int rcBusy, uint8_t u8IntCause)
    259259{
    260     int rc = vpciCsEnter(pState, rcBusy);
    261     if (RT_UNLIKELY(rc != VINF_SUCCESS))
    262         return rc;
     260    // int rc = vpciCsEnter(pState, rcBusy);
     261    // if (RT_UNLIKELY(rc != VINF_SUCCESS))
     262    //     return rc;
    263263
    264264    STAM_COUNTER_INC(&pState->StatIntsRaised);
     
    268268    pState->uISR |= u8IntCause;
    269269    PDMDevHlpPCISetIrq(pState->CTX_SUFF(pDevIns), 0, 1);
    270     vpciCsLeave(pState);
     270    // vpciCsLeave(pState);
    271271    return VINF_SUCCESS;
    272272}
     
    314314    const char *szInst = INSTANCE(pState);
    315315    STAM_PROFILE_ADV_START(&pState->CTXSUFF(StatIORead), a);
     316
     317    /*
     318     * We probably do not need to enter critical section when reading registers
     319     * as the most of them are either constant or being changed during
     320     * initialization only, the exception being ISR which can be raced by all
     321     * threads but I see no big harm in it. It also happens to be the most read
     322     * register as it gets read in interrupt handler. By dropping cs protection
     323     * here we gain the ability to deliver RX packets to the guest while TX is
     324     * holding cs transmitting queued packets.
     325     *
     326    rc = vpciCsEnter(pState, VINF_IOM_HC_IOPORT_READ);
     327    if (RT_UNLIKELY(rc != VINF_SUCCESS))
     328    {
     329        STAM_PROFILE_ADV_STOP(&pState->CTXSUFF(StatIORead), a);
     330        return rc;
     331        }*/
    316332
    317333    port -= pState->addrIOPort;
     
    371387          szInst, port, cb*2, *pu32));
    372388    STAM_PROFILE_ADV_STOP(&pState->CTXSUFF(StatIORead), a);
     389    //vpciCsLeave(pState);
    373390    return rc;
    374391}
     
    405422    bool        fHasBecomeReady;
    406423    STAM_PROFILE_ADV_START(&pState->CTXSUFF(StatIOWrite), a);
     424
     425    rc = vpciCsEnter(pState, VINF_IOM_HC_IOPORT_WRITE);
     426    if (RT_UNLIKELY(rc != VINF_SUCCESS))
     427    {
     428        STAM_PROFILE_ADV_STOP(&pState->CTXSUFF(StatIOWrite), a);
     429        return rc;
     430    }
     431
    407432
    408433    port -= pState->addrIOPort;
     
    494519
    495520    STAM_PROFILE_ADV_STOP(&pState->CTXSUFF(StatIOWrite), a);
     521    vpciCsLeave(pState);
    496522    return rc;
    497523}
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