VirtualBox

Changeset 72459 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Jun 6, 2018 8:17:43 AM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
122941
Message:

Dev/VirtioNet: (​bugref:8651) TX thread is used instead of TX timer.

File:
1 edited

Legend:

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

    r71944 r72459  
    6464#endif /* VBOX_DEVICE_STRUCT_TESTCASE */
    6565
    66 
    67 #define VNET_TX_DELAY           150   /**< 150 microseconds */
     66/*
     67 * Commenting out VNET_TX_DELAY enables async transmission in a dedicated thread.
     68 * When VNET_TX_DELAY is defined, a timer handler does the job.
     69 */
     70//#define VNET_TX_DELAY           150   /**< 150 microseconds */
    6871#define VNET_MAX_FRAME_SIZE     65535 + 18  /**< Max IP packet size + Ethernet header with VLAN tag */
    6972#define VNET_MAC_FILTER_LEN     32
     
    154157    uint32_t                u32MaxDiff;
    155158    uint64_t                u64NanoTS;
    156 #endif /* VNET_TX_DELAY */
     159#else /* !VNET_TX_DELAY */
     160    /** The support driver session handle. */
     161    R3R0PTRTYPE(PSUPDRVSESSION)     pSupDrvSession;
     162    /** The event semaphore TX thread waits on. */
     163    SUPSEMEVENT                     hTxEvent;
     164    R3PTRTYPE(PPDMTHREAD)           pTxThread;
     165#endif /* !VNET_TX_DELAY */
    157166
    158167    /** Indicates transmission in progress -- only one thread is allowed. */
     
    14761485}
    14771486
     1487inline int vnetCreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis)
     1488{
     1489    RT_NOREF(pDevIns, pThis);
     1490    return VINF_SUCCESS;
     1491}
     1492
     1493inline void vnetDestroyTxThreadAndEvent(PVNETSTATE pThis)
     1494{
     1495    RT_NOREF(pThis);
     1496}
    14781497#else /* !VNET_TX_DELAY */
    14791498
     1499static DECLCALLBACK(int) vnetTxThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1500{
     1501    RT_NOREF(pDevIns);
     1502    PVNETSTATE pThis = (PVNETSTATE)pThread->pvUser;
     1503    int rc = VINF_SUCCESS;
     1504
     1505    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     1506        return VINF_SUCCESS;
     1507
     1508    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     1509    {
     1510        rc = SUPSemEventWaitNoResume(pThis->pSupDrvSession, pThis->hTxEvent, RT_INDEFINITE_WAIT);
     1511        if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     1512            break;
     1513        vnetTransmitPendingPackets(pThis, pThis->pTxQueue, false /*fOnWorkerThread*/); // @todo: shouldn't it be true instead?
     1514        Log(("vnetTxThread: enable kicking and get to sleep\n"));
     1515        vringSetNotification(&pThis->VPCI, &pThis->pTxQueue->VRing, true);
     1516    }
     1517
     1518    return rc;
     1519}
     1520
     1521/**
     1522 * Unblock TX thread so it can respond to a state change.
     1523 *
     1524 * @returns VBox status code.
     1525 * @param   pDevIns     The device instance.
     1526 * @param   pThread     The send thread.
     1527 */
     1528static DECLCALLBACK(int) vnetTxThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     1529{
     1530    RT_NOREF(pDevIns);
     1531    PVNETSTATE pThis = (PVNETSTATE)pThread->pvUser;
     1532    return SUPSemEventSignal(pThis->pSupDrvSession, pThis->hTxEvent);
     1533}
     1534
     1535static int vnetCreateTxThreadAndEvent(PPDMDEVINS pDevIns, PVNETSTATE pThis)
     1536{
     1537    int rc = SUPSemEventCreate(pThis->pSupDrvSession, &pThis->hTxEvent);
     1538    if (RT_FAILURE(rc))
     1539        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     1540                                   N_("VNET: Failed to create SUP event semaphore"));
     1541    rc = PDMDevHlpThreadCreate(pDevIns, &pThis->pTxThread, pThis, vnetTxThread,
     1542                               vnetTxThreadWakeUp, 0, RTTHREADTYPE_IO, INSTANCE(pThis));
     1543    if (RT_FAILURE(rc))
     1544        return PDMDevHlpVMSetError(pDevIns, rc, RT_SRC_POS,
     1545                                   N_("VNET: Failed to create worker thread %s"), INSTANCE(pThis));
     1546    return VINF_SUCCESS;
     1547}
     1548
     1549static void vnetDestroyTxThreadAndEvent(PVNETSTATE pThis)
     1550{
     1551    if (pThis->pTxThread)
     1552    {
     1553        int rcThread;
     1554        /* Destroy the thread. */
     1555        int rc = PDMR3ThreadDestroy(pThis->pTxThread, &rcThread);
     1556        if (RT_FAILURE(rc) || RT_FAILURE(rcThread))
     1557            AssertMsgFailed(("%s Failed to destroy async IO thread rc=%Rrc rcThread=%Rrc\n", __FUNCTION__, rc, rcThread));
     1558        pThis->pTxThread = NULL;
     1559    }
     1560    if (pThis->hTxEvent != NIL_SUPSEMEVENT)
     1561    {
     1562        SUPSemEventClose(pThis->pSupDrvSession, pThis->hTxEvent);
     1563        pThis->hTxEvent = NIL_SUPSEMEVENT;
     1564    }
     1565}
     1566
    14801567static DECLCALLBACK(void) vnetQueueTransmit(void *pvState, PVQUEUE pQueue)
    14811568{
    14821569    PVNETSTATE pThis = (PVNETSTATE)pvState;
    14831570
    1484     vnetTransmitPendingPackets(pThis, pQueue, false /*fOnWorkerThread*/);
     1571    Log(("vnetQueueTransmit: disable kicking and wake up TX thread\n"));
     1572    vringSetNotification(&pThis->VPCI, &pQueue->VRing, false);
     1573    SUPSemEventSignal(pThis->pSupDrvSession, pThis->hTxEvent);
    14851574}
    14861575
     
    19192008    }
    19202009
     2010    vnetDestroyTxThreadAndEvent(pThis);
    19212011    /*
    19222012     * Zero some important members.
     
    19662056        AssertMsgStmt(pThis->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),
    19672057                      rc = VERR_PDM_MISSING_INTERFACE_BELOW);
     2058
     2059        vnetCreateTxThreadAndEvent(pDevIns, pThis);
    19682060    }
    19692061    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
     
    20322124    PVNETSTATE pThis = PDMINS_2_DATA(pDevIns, PVNETSTATE);
    20332125
     2126#ifdef VNET_TX_DELAY
    20342127    LogRel(("TxTimer stats (avg/min/max): %7d usec %7d usec %7d usec\n",
    20352128            pThis->u32AvgDiff, pThis->u32MinDiff, pThis->u32MaxDiff));
     2129#endif /* VNET_TX_DELAY */
    20362130    Log(("%s Destroying instance\n", INSTANCE(pThis)));
    20372131    if (pThis->hEventMoreRxDescAvail != NIL_RTSEMEVENT)
     
    21632257        return rc;
    21642258
    2165 #ifdef VNET_TX_DELAY
     2259#ifndef VNET_TX_DELAY
     2260    pThis->pSupDrvSession = PDMDevHlpGetSupDrvSession(pDevIns);
     2261    pThis->hTxEvent       = NIL_SUPSEMEVENT;
     2262    pThis->pTxThread      = NULL;
     2263#else /* VNET_TX_DELAY */
    21662264    /* Create Transmit Delay Timer */
    21672265    rc = PDMDevHlpTMTimerCreate(pDevIns, TMCLOCK_VIRTUAL, vnetTxTimer, pThis,
     
    21882286        AssertMsgReturn(pThis->pDrv, ("Failed to obtain the PDMINETWORKUP interface!\n"),
    21892287                        VERR_PDM_MISSING_INTERFACE_BELOW);
     2288
     2289        vnetCreateTxThreadAndEvent(pDevIns, pThis);
    21902290    }
    21912291    else if (   rc == VERR_PDM_NO_ATTACHED_DRIVER
Note: See TracChangeset for help on using the changeset viewer.

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