VirtualBox

Changeset 62294 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Jul 18, 2016 10:12:57 AM (9 years ago)
Author:
vboxsync
Message:

VUSB: Add reference couting to the USB device structure to prevent races between EMT and the worker threads when the device is attached leading to crashes

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

Legend:

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

    r62211 r62294  
    279279        pUsbIns->pvVUsbDev2 = NULL;
    280280    }
    281     vusbDevDestroy(pDev);
    282     RTMemFree(pDev);
     281    vusbDevRelease(pDev);
    283282    return rc;
    284283}
     
    290289    PVUSBDEV pDev = (PVUSBDEV)pUsbIns->pvVUsbDev2;
    291290    Assert(pDev);
    292     vusbDevDestroy(pDev);
    293     RTMemFree(pDev);
    294     pUsbIns->pvVUsbDev2 = NULL;
     291
     292    /*
     293     * Deal with pending async reset.
     294     * (anything but reset)
     295     */
     296    vusbDevSetStateCmp(pDev, VUSB_DEVICE_STATE_DEFAULT, VUSB_DEVICE_STATE_RESET);
     297
     298    /*
     299     * Detach and free resources.
     300     */
     301    if (pDev->pHub)
     302        vusbDevDetach(pDev);
     303
     304    vusbDevRelease(pDev);
    295305    return VINF_SUCCESS;
    296306}
     
    322332{
    323333    unsigned iHash = vusbHashAddress(Address);
    324     for (PVUSBDEV pDev = pRh->apAddrHash[iHash]; pDev; pDev = pDev->pNextHash)
    325         if (pDev->u8Address == Address)
    326             return pDev;
    327     return NULL;
     334    PVUSBDEV pDev = NULL;
     335
     336    RTCritSectEnter(&pRh->CritSectDevices);
     337    for (PVUSBDEV pCur = pRh->apAddrHash[iHash]; pCur; pCur = pCur->pNextHash)
     338        if (pCur->u8Address == Address)
     339        {
     340            pDev = pCur;
     341            break;
     342        }
     343
     344    if (pDev)
     345        vusbDevRetain(pDev);
     346    RTCritSectLeave(&pRh->CritSectDevices);
     347    return pDev;
    328348}
    329349
     
    355375    /* The URB comes from the roothub if there is no device (invalid address). */
    356376    if (pUrb->pVUsb->pDev)
     377    {
    357378        vusbUrbPoolFree(&pUrb->pVUsb->pDev->UrbPool, pUrb);
     379        vusbDevRelease(pUrb->pVUsb->pDev);
     380    }
    358381    else
    359382        vusbUrbPoolFree(&pRh->Hub.Dev.UrbPool, pUrb);
     
    371394    if (!pDev)
    372395        pDev = vusbRhFindDevByAddress(pRh, DstAddress);
     396    else
     397        vusbDevRetain(pDev);
    373398
    374399    if (pDev)
     
    706731    else
    707732    {
     733        vusbDevRetain(&pRh->Hub.Dev);
    708734        pUrb->pVUsb->pDev = &pRh->Hub.Dev;
    709735        Log(("vusb: pRh=%p: SUBMIT: Address %i not found!!!\n", pRh, pUrb->DstAddress));
     
    12351261    pThis->Hub.Dev.u8NewAddress         = VUSB_INVALID_ADDRESS;
    12361262    pThis->Hub.Dev.i16Port              = -1;
     1263    pThis->Hub.Dev.cRefs                = 1;
    12371264    pThis->Hub.Dev.IDevice.pfnReset     = vusbRhDevReset;
    12381265    pThis->Hub.Dev.IDevice.pfnPowerOn   = vusbRhDevPowerOn;
  • trunk/src/VBox/Devices/USB/VUSBDevice.cpp

    r59859 r62294  
    966966    pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
    967967
     968    RTCritSectEnter(&pDev->pHub->pRootHub->CritSectDevices);
    968969    PVUSBDEV pCur = pDev->pHub->pRootHub->apAddrHash[u8Hash];
    969970    if (pCur == pDev)
     
    989990        }
    990991    }
     992    RTCritSectLeave(&pDev->pHub->pRootHub->CritSectDevices);
    991993}
    992994
     
    12641266 *
    12651267 * @param   pDev    The device.
    1266  * @thread  EMT
     1268 * @thread any.
    12671269 */
    12681270void vusbDevDestroy(PVUSBDEV pDev)
     
    12701272    LogFlow(("vusbDevDestroy: pDev=%p[%s] enmState=%d\n", pDev, pDev->pUsbIns->pszName, pDev->enmState));
    12711273
    1272     /*
    1273      * Deal with pending async reset.
    1274      * (anything but reset)
    1275      */
    1276     vusbDevSetStateCmp(pDev, VUSB_DEVICE_STATE_DEFAULT, VUSB_DEVICE_STATE_RESET);
    1277 
    1278     /*
    1279      * Detach and free resources.
    1280      */
    1281     if (pDev->pHub)
    1282         vusbDevDetach(pDev);
    12831274    RTMemFree(pDev->paIfStates);
    12841275    TMR3TimerDestroy(pDev->pResetTimer);
     
    13071298    /* Not using vusbDevSetState() deliberately here because it would assert on the state. */
    13081299    pDev->enmState = VUSB_DEVICE_STATE_DESTROYED;
     1300    pDev->pUsbIns->pvVUsbDev2 = NULL;
     1301    RTMemFree(pDev);
    13091302}
    13101303
     
    17661759    pDev->pHub = NULL;
    17671760    pDev->enmState = VUSB_DEVICE_STATE_DETACHED;
     1761    pDev->cRefs = 1;
    17681762    pDev->u8Address = VUSB_INVALID_ADDRESS;
    17691763    pDev->u8NewAddress = VUSB_INVALID_ADDRESS;
  • trunk/src/VBox/Devices/USB/VUSBInternal.h

    r59875 r62294  
    227227    /** The device state. */
    228228    VUSBDEVICESTATE volatile enmState;
     229    /** Reference counter to protect the device structure from going away. */
     230    uint32_t volatile        cRefs;
    229231
    230232    /** The device address. */
     
    254256    /** List of active async URBs. */
    255257    RTLISTANCHOR        LstAsyncUrbs;
    256 #if HC_ARCH_BITS == 32
    257     /** Align the size to a 8 byte boundary. */
    258     uint32_t            u32Alignment0;
    259 #endif
    260258
    261259    /** Dumper state. */
     
    750748}
    751749
     750/**
     751 * Retains the given VUSB device pointer.
     752 *
     753 * @returns New reference count.
     754 * @param   pThis          The VUSB device pointer.
     755 */
     756DECLINLINE(uint32_t) vusbDevRetain(PVUSBDEV pThis)
     757{
     758    AssertPtrReturn(pThis, UINT32_MAX);
     759
     760    uint32_t cRefs = ASMAtomicIncU32(&pThis->cRefs);
     761    AssertMsg(cRefs > 1 && cRefs < _1M, ("%#x %p\n", cRefs, pThis));
     762    return cRefs;
     763}
     764
     765/**
     766 * Releases the given VUSB device pointer.
     767 *
     768 * @returns New reference count.
     769 * @retval 0 if no onw is holding a reference anymore causing the device to be destroyed.
     770 */
     771DECLINLINE(uint32_t) vusbDevRelease(PVUSBDEV pThis)
     772{
     773    AssertPtrReturn(pThis, UINT32_MAX);
     774
     775    uint32_t cRefs = ASMAtomicDecU32(&pThis->cRefs);
     776    AssertMsg(cRefs < _1M, ("%#x %p\n", cRefs, pThis));
     777    if (cRefs == 0)
     778        vusbDevDestroy(pThis);
     779    return cRefs;
     780}
     781
    752782/** Strings for the CTLSTAGE enum values. */
    753783extern const char * const g_apszCtlStates[4];
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