VirtualBox

Changeset 4422 in vbox for trunk


Ignore:
Timestamp:
Aug 29, 2007 1:37:48 PM (17 years ago)
Author:
vboxsync
Message:

Tamed the send thread using PDMThread.

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

Legend:

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

    r4196 r4422  
    4747 */
    4848
     49/** To enable the PDMThread based send thread code.
     50 * This is just a emergency switch in case changes doesn't quite work and
     51 * we want to get 1.5 out.
     52 * @todo cleanup after 1.5.  */
     53#define USE_PDMTHREAD 1
     54
    4955/*******************************************************************************
    5056*   Header Files                                                               *
     
    198204    /** If set the link is temporarily down because of a saved state load. */
    199205    bool                                fLinkTempDown;
    200     /** This flag is set on SavePrep to prevent altering of memory after pgmR3Save() was called */
     206    /** This flag is set on SavePrep to prevent altering of memory after pgmR3Save() was called
     207     * @todo r=bird: This is inadequate, we are not supposed to do anything at all while the VM
     208     *               isn't running. Naturally, the problem really lies with the driver and not
     209     *               the pcnet code. We will have to address this properly at some time. */
    201210    bool                                fSaving;
    202211
     
    215224    /** Async send thread */
    216225    RTSEMEVENT                          hSendEventSem;
     226#ifdef USE_PDMTHREAD
     227    /** The Async send thread. */
     228    PPDMTHREAD                          pSendThread;
     229#else
    217230    RTTHREAD                            hSendThread;
     231#endif
    218232
    219233    /** Access critical section. */
     
    20532067                    {
    20542068                        int rc = pcnetXmitCompleteFrame(pData);
     2069#ifdef USE_PDMTHREAD
     2070                        AssertRCReturn(rc, rc);
     2071#else
    20552072                        if (VBOX_FAILURE(rc))
    20562073                            return rc; /* can happen during termination */
     2074#endif
    20572075                    }
    20582076                }
     
    21602178                    {
    21612179                        int rc = pcnetXmitCompleteFrame(pData);
     2180#ifdef USE_PDMTHREAD
     2181                        AssertRCReturn(rc, rc);
     2182#else
    21622183                        if (VBOX_FAILURE(rc))
    21632184                            return rc; /* can happen during termination */
     2185#endif
    21642186                    }
    21652187                    else if (CSR_LOOP(pData) && !fDropFrame)
     
    22232245}
    22242246
     2247
     2248#ifdef USE_PDMTHREAD
     2249/**
     2250 * Async I/O thread for delayed sending of packets.
     2251 *
     2252 * @returns VBox status code. Returning failure will naturally terminate the thread.
     2253 * @param   pDevIns     The pcnet device instance.
     2254 * @param   pThread     The thread.
     2255 */
     2256static DECLCALLBACK(int) pcnetAsyncSendThread(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     2257{
     2258    PCNetState *pThis = PDMINS2DATA(pDevIns, PCNetState *);
     2259
     2260    /*
     2261     * We can enter this function in two states, initializing or resuming.
     2262     *
     2263     * The idea about the initializing bit is that we can do per-thread
     2264     * initialization while the creator thread can still pick up errors.
     2265     * At present, there is nothing to init, or at least nothing that
     2266     * need initing in the thread.
     2267     */
     2268    if (pThread->enmState == PDMTHREADSTATE_INITIALIZING)
     2269        return VINF_SUCCESS;
     2270
     2271    /*
     2272     * Stay in the run-loop until we're supposed to leave the
     2273     * running state. If something really bad happens, we'll
     2274     * quit the loop while in the running state and return
     2275     * an error status to PDM and let it terminate the thread.
     2276     */
     2277    while (pThread->enmState == PDMTHREADSTATE_RUNNING)
     2278    {
     2279        /*
     2280         * Block until we've got something to send or is supposed
     2281         * to leave the running state.
     2282         */
     2283        int rc = RTSemEventWait(pThis->hSendEventSem, RT_INDEFINITE_WAIT);
     2284        AssertRCReturn(rc, rc);
     2285        if (RT_UNLIKELY(pThread->enmState != PDMTHREADSTATE_RUNNING))
     2286            break;
     2287
     2288        /*
     2289         * Perform async send. Mind that we might be requested to
     2290         * suspended while waiting for the critical section.
     2291         */
     2292        rc = PDMCritSectEnter(&pThis->CritSect, VERR_PERMISSION_DENIED);
     2293        AssertReleaseRCReturn(rc, rc);
     2294
     2295        if (pThread->enmState == PDMTHREADSTATE_RUNNING)
     2296        {
     2297            rc = pcnetAsyncTransmit(pThis);
     2298            AssertReleaseRC(rc);
     2299        }
     2300
     2301        PDMCritSectLeave(&pThis->CritSect);
     2302    }
     2303
     2304    /* The thread is being suspended or terminated. */
     2305    return VINF_SUCCESS;
     2306}
     2307
     2308
     2309/**
     2310 * Unblock the send thread so it can respond to a state change.
     2311 *
     2312 * @returns VBox status code.
     2313 * @param   pDevIns     The pcnet device instance.
     2314 * @param   pThread     The send thread.
     2315 */
     2316static DECLCALLBACK(int) pcnetAsyncSendThreadWakeUp(PPDMDEVINS pDevIns, PPDMTHREAD pThread)
     2317{
     2318    PCNetState *pThis = PDMINS2DATA(pDevIns, PCNetState *);
     2319    return RTSemEventSignal(pThis->hSendEventSem);
     2320}
     2321
     2322
     2323#else /* USE_PDMTHREAD */
    22252324/**
    22262325 * Async I/O thread for delayed sending of packets.
     
    22482347    return VINF_SUCCESS;
    22492348}
     2349#endif /* USE_PDMTHREAD */
    22502350
    22512351#endif /* IN_RING3 */
     
    22632363        pcnetTransmit(pData);
    22642364}
     2365
    22652366
    22662367/**
     
    39944095    PCNetState *pData = PDMINS2DATA(pDevIns, PCNetState *);
    39954096
    3996     PDMCritSectEnter(&pData->CritSect, VERR_ACCESS_DENIED);
    3997 
    3998     RTSemEventDestroy(pData->hSendEventSem);
    3999     pData->hSendEventSem = 0;
    4000     PDMCritSectLeave(&pData->CritSect);
    4001 
    4002     PDMR3CritSectDelete(&pData->CritSect);
     4097    if (PDMCritSectIsInitialized(&pData->CritSect))
     4098    {
     4099#ifdef USE_PDMTHREAD
     4100        /*
     4101         * At this point the send thread is suspended and will not enter
     4102         * this module again. So, no coordination is needed here and PDM
     4103         * will take care of terminating and cleaning up the thread.
     4104         */
     4105        RTSemEventDestroy(pData->hSendEventSem);
     4106        pData->hSendEventSem = NIL_RTSEMEVENT;
     4107        PDMR3CritSectDelete(&pData->CritSect);
     4108#else
     4109        PDMCritSectEnter(&pData->CritSect, VERR_ACCESS_DENIED);
     4110
     4111        RTSemEventDestroy(pData->hSendEventSem);
     4112        pData->hSendEventSem = 0;
     4113
     4114        PDMCritSectLeave(&pData->CritSect);
     4115        PDMR3CritSectDelete(&pData->CritSect);
     4116#endif
     4117    }
    40034118    return VINF_SUCCESS;
    40044119}
     
    42704385
    42714386    /* Create asynchronous thread */
     4387#ifdef USE_PDMTHREAD
     4388    rc = PDMDevHlpPDMThreadCreate(pDevIns, &pData->pSendThread, pData, pcnetAsyncSendThread, pcnetAsyncSendThreadWakeUp, 0, RTTHREADTYPE_IO, "PCNET_SEND");
     4389    AssertRCReturn(rc, rc);
     4390#else
    42724391    rc = RTThreadCreate(&pData->hSendThread, pcnetAsyncSend, (void *)pData, 128*1024, RTTHREADTYPE_IO, 0, "PCNET_SEND");
    42734392    AssertRC(rc);
     4393#endif
    42744394
    42754395#ifdef VBOX_WITH_STATISTICS
  • trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp

    r4071 r4422  
    353353    GEN_CHECK_OFF(PCNetState, pLedsConnector);
    354354    GEN_CHECK_OFF(PCNetState, hSendEventSem);
     355#ifdef USE_PDMTHREAD
     356    GEN_CHECK_OFF(PCNetState, pSendThread);
     357#else
    355358    GEN_CHECK_OFF(PCNetState, hSendThread);
     359#endif
    356360    GEN_CHECK_OFF(PCNetState, CritSect);
    357361    GEN_CHECK_OFF(PCNetState, cPendingSends);
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