VirtualBox

Changeset 52148 in vbox


Ignore:
Timestamp:
Jul 23, 2014 12:42:21 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95182
Message:

Devices/USB: ancel URBs on the I/O thread if available, fixes a race causing an assertion

Location:
trunk/src/VBox/Devices/USB
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/USB/VUSBDevice.cpp

    r49814 r52148  
    11301130            vusbUrbDoReapAsyncDev(pDev, RT_INDEFINITE_WAIT);
    11311131
     1132        /* Process any URBs waiting to be cancelled first. */
     1133        int rc = RTReqQueueProcess(pDev->hReqQueueCancel, 0); /* Don't wait if there is nothing to do. */
     1134        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
     1135
    11321136        /* Woken up or there is an URB to queue. */
    11331137        PRTQUEUEATOMICITEM pHead = RTQueueAtomicRemoveAll(&pDev->QueueUrb);
     
    11391143
    11401144            LogFlow(("%s: Queuing URB\n", pUrb->pszDesc));
    1141             int rc = pUrb->pUsbIns->pReg->pfnUrbQueue(pUrb->pUsbIns, pUrb);
     1145            rc = pUrb->pUsbIns->pReg->pfnUrbQueue(pUrb->pUsbIns, pUrb);
    11421146            if (RT_FAILURE(rc))
    11431147            {
     
    12191223        rc = rcThread;
    12201224
     1225    pDev->hUrbIoThread = NIL_RTTHREAD;
     1226
    12211227    return rc;
    12221228}
     
    12921298    /* Destroy I/O thread. */
    12931299    vusbDevUrbIoThreadDestroy(pDev);
     1300
     1301    /* Destroy request queue. */
     1302    int rc = RTReqQueueDestroy(pDev->hReqQueueCancel);
     1303    AssertRC(rc);
    12941304
    12951305    /*
     
    17301740    AssertMsgReturn(pDev->paIfStates, ("RTMemAllocZ(%d) failed\n", cbIface), VERR_NO_MEMORY);
    17311741
     1742    /* Setup request queue for cancelling URBs synchronously. */
     1743    rc = RTReqQueueCreate(&pDev->hReqQueueCancel);
     1744    AssertRCReturn(rc, rc);
     1745
    17321746    rc = vusbDevUrbIoThreadCreate(pDev);
    17331747    AssertRCReturn(rc, rc);
  • trunk/src/VBox/Devices/USB/VUSBInternal.h

    r49815 r52148  
    3030#include <iprt/assert.h>
    3131#include <iprt/queueatomic.h>
     32#include <iprt/req.h>
    3233
    3334RT_C_DECLS_BEGIN
     
    219220    /** Queue of URBs to submit. */
    220221    RTQUEUEATOMIC       QueueUrb;
     222    /** Request queue for cancelling URBs on the I/O thread. */
     223    RTREQQUEUE          hReqQueueCancel;
    221224    /** Flag whether the URB I/O thread should terminate. */
    222225    bool volatile       fTerminate;
  • trunk/src/VBox/Devices/USB/VUSBUrb.cpp

    r49814 r52148  
    20372037}
    20382038
    2039 
    2040 /**
    2041  * Cancels an URB with CRC failure.
    2042  *
    2043  * Cancelling an URB is a tricky thing. The USBProxy backend can not
    2044  * all cancel it and we must keep the URB around until it's ripe and
    2045  * can be reaped the normal way. However, we must complete the URB
    2046  * now, before leaving this function. This is not nice. sigh.
    2047  *
    2048  * This function will cancel the URB if it's in-flight and complete
    2049  * it. The device will in its pfnCancel method be given the chance to
    2050  * say that the URB doesn't need reaping and should be unlinked.
    2051  *
    2052  * An URB which is in the cancel state after pfnCancel will remain in that
    2053  * state and in the async list until its reaped. When it's finally reaped
    2054  * it will be unlinked and freed without doing any completion.
    2055  *
    2056  * There are different modes of canceling an URB. When devices are being
    2057  * disconnected etc., they will be completed with an error (CRC). However,
    2058  * when the HC needs to temporarily halt communication with a device, the
    2059  * URB/TD must be left alone if possible.
    2060  *
     2039/**
     2040 * The worker for vusbUrbCancel() which is executed on the I/O thread.
     2041 *
     2042 * @returns nothing.
    20612043 * @param   pUrb        The URB to cancel.
    2062  * @param   mode        The way the URB should be canceled.
    2063  */
    2064 void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode)
     2044 * @param   enmMode     The way the URB should be canceled.
     2045 */
     2046static void vusbUrbCancelWorker(PVUSBURB pUrb, CANCELMODE enmMode)
    20652047{
    20662048    vusbUrbAssert(pUrb);
     
    21022084    {
    21032085        AssertMsg(pUrb->enmState == VUSBURBSTATE_CANCELLED, ("Invalid state %d, pUrb=%p\n", pUrb->enmState, pUrb));
    2104         switch (mode)
     2086        switch (enmMode)
    21052087        {
    21062088            default:
     
    21172099}
    21182100
     2101/**
     2102 * Cancels an URB with CRC failure.
     2103 *
     2104 * Cancelling an URB is a tricky thing. The USBProxy backend can not
     2105 * all cancel it and we must keep the URB around until it's ripe and
     2106 * can be reaped the normal way. However, we must complete the URB
     2107 * now, before leaving this function. This is not nice. sigh.
     2108 *
     2109 * This function will cancel the URB if it's in-flight and complete
     2110 * it. The device will in its pfnCancel method be given the chance to
     2111 * say that the URB doesn't need reaping and should be unlinked.
     2112 *
     2113 * An URB which is in the cancel state after pfnCancel will remain in that
     2114 * state and in the async list until its reaped. When it's finally reaped
     2115 * it will be unlinked and freed without doing any completion.
     2116 *
     2117 * There are different modes of canceling an URB. When devices are being
     2118 * disconnected etc., they will be completed with an error (CRC). However,
     2119 * when the HC needs to temporarily halt communication with a device, the
     2120 * URB/TD must be left alone if possible.
     2121 *
     2122 * @param   pUrb        The URB to cancel.
     2123 * @param   mode        The way the URB should be canceled.
     2124 */
     2125void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode)
     2126{
     2127    PRTREQ hReq = NULL;
     2128
     2129    if (pUrb->VUsb.pDev->hUrbIoThread != NIL_RTTHREAD)
     2130    {
     2131        int rc = RTReqQueueCallVoid(pUrb->VUsb.pDev->hReqQueueCancel, &hReq, 0,
     2132                                    (PFNRT)vusbUrbCancelWorker, 2, pUrb, mode);
     2133        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
     2134        vusbDevUrbIoThreadWakeup(pUrb->VUsb.pDev);
     2135        rc = RTReqWait(hReq, RT_INDEFINITE_WAIT);
     2136        AssertRC(rc);
     2137    }
     2138    else /* Call the worker directly. */
     2139        vusbUrbCancelWorker(pUrb, mode);
     2140}
     2141
    21192142
    21202143/**
  • trunk/src/VBox/Devices/USB/freebsd/USBProxyDevice-freebsd.cpp

    r50236 r52148  
    673673 * @copydoc USBPROXYBACK::pfnUrbQueue
    674674 */
    675 static DECLCALLBACK(int) usbProxyFreeBSDUrbQueue(PVUSBURB pUrb)
    676 {
    677     PUSBPROXYDEV pProxyDev = PDMINS_2_DATA(pUrb->pUsbIns, PUSBPROXYDEV);
     675static DECLCALLBACK(int) usbProxyFreeBSDUrbQueue(PUSBPROXYDEV pProxyDev, PVUSBURB pUrb)
     676{
    678677    PUSBPROXYDEVFBSD pDevFBSD = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVFBSD);
    679678    PUSBENDPOINTFBSD pEndpointFBSD;
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