VirtualBox

Changeset 52254 in vbox


Ignore:
Timestamp:
Aug 2, 2014 3:34:53 PM (10 years ago)
Author:
vboxsync
Message:

Devices/USB: Several fixes and misc cleanups, the VM crash when detaching a USB device while transfering data should be fixed, likewise several assertions in debug builds should be fixed now. Removed a bit dead code in the linux backend (timeout handling which wasn't active)

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

Legend:

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

    r51636 r52254  
    586586    LogFlow(("vusbRhCancelUrbsEp: pRh=%p pUrb=%p\n", pRh));
    587587
    588     /* Tear down reaper thread on the device. */
    589     PVUSBDEV pDev = pUrb->VUsb.pDev;
    590     int rc = vusbDevUrbIoThreadDestroy(pDev);
    591     if (RT_FAILURE(rc))
    592         return rc;
    593 
    594588    vusbUrbCancel(pUrb, CANCELMODE_UNDO);
    595589
    596     PVUSBURB pRipe;
    597     if (pUrb->enmState == VUSBURBSTATE_REAPED)
    598         pRipe = pUrb;
    599     else
    600         pRipe = pUrb->pUsbIns->pReg->pfnUrbReap(pUrb->pUsbIns, 0);
    601     if (pRipe)
    602     {
    603         pRipe->enmStatus = VUSBSTATUS_CRC;
    604         vusbUrbRipe(pRipe);
    605     }
    606 
    607     rc = vusbDevUrbIoThreadCreate(pDev);
    608     return rc;
     590    /* The reaper thread will take care of completing the URB. */
     591
     592    return VINF_SUCCESS;
    609593}
    610594
     
    615599
    616600    /*
    617      * Tear down all reaper threads first to avoid concurrency issues.
    618      * pfnUrbReap is not thread safe.
    619      */
    620     PVUSBDEV pDev = pRh->pDevices;
    621     while (pDev)
    622     {
    623         int rc = vusbDevUrbIoThreadDestroy(pDev);
    624         AssertRC(rc); /* Should not fail. */
    625         pDev = pDev->pNext;
    626     }
    627 
    628     /*
    629601     * Cancel the URBS.
    630602     */
     603    RTCritSectEnter(&pRh->CritSect);
    631604    PVUSBURB pUrb = pRh->pAsyncUrbHead;
    632605    LogFlow(("vusbRhCancelAllUrbs: pRh=%p\n", pRh));
     
    637610        pUrb = pNext;
    638611    }
    639 
    640     /*
    641      * Reap any URBs which now are ripe.
    642      */
    643     pUrb = pRh->pAsyncUrbHead;
    644     while (pUrb)
    645     {
    646         PVUSBURB pRipe;
    647         if (pUrb->enmState == VUSBURBSTATE_REAPED)
    648             pRipe = pUrb;
    649         else
    650             pRipe = pUrb->pUsbIns->pReg->pfnUrbReap(pUrb->pUsbIns, 0);
    651         if (!pRipe || pUrb == pRipe)
    652             pUrb = pUrb->VUsb.pNext;
    653         if (pRipe)
    654         {
    655             pRipe->enmStatus = VUSBSTATUS_CRC;
    656             vusbUrbRipe(pRipe);
    657         }
    658     }
    659 
    660     /*
    661      * Create the reaper threads again.
    662      */
    663     pDev = pRh->pDevices;
    664     while (pDev)
    665     {
    666         int rc = vusbDevUrbIoThreadCreate(pDev);
    667         AssertRC(rc); /** @todo: What if this fails? */
    668         pDev = pDev->pNext;
    669     }
     612    RTCritSectLeave(&pRh->CritSect);
    670613}
    671614
  • trunk/src/VBox/Devices/USB/VUSBDevice.cpp

    r52148 r52254  
    132132             pPipe, g_apszCtlStates[pPipe->pCtrl ? pPipe->pCtrl->enmStage : 3]));
    133133
    134     pPipe->ReadAheadThread = NIL_RTTHREAD;
    135134    if ((pEndPtDesc->Core.bmAttributes & 0x3) == 0)
    136135    {
     
    144143        pPipe->in = pEndPtDesc;
    145144
    146 #if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
     145#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_DARWIN)
    147146        /*
    148147         * For high-speed isochronous input endpoints, spin off a read-ahead buffering thread.
    149148         */
    150149        if ((pEndPtDesc->Core.bmAttributes & 0x03) == 1)
    151             vusbReadAheadStart(pDev, pPipe);
     150            pPipe->hReadAhead = vusbReadAheadStart(pDev, pPipe);
    152151#endif
    153152    }
     
    185184
    186185        /* If there was a read-ahead thread associated with this endpoint, tell it to go away. */
    187         if (pPipe->pvReadAheadArgs)
     186        if (pPipe->hReadAhead)
    188187        {
    189188            Log(("vusb: and tell read-ahead thread for the endpoint to terminate\n"));
    190             vusbReadAheadStop(pPipe->pvReadAheadArgs);
     189            vusbReadAheadStop(pPipe->hReadAhead);
     190            pPipe->hReadAhead = NULL;
    191191        }
    192192    }
     
    315315    if (pDev->pUsbIns->pReg->pfnUsbSetConfiguration)
    316316    {
    317         int rc = pDev->pUsbIns->pReg->pfnUsbSetConfiguration(pDev->pUsbIns, pNewCfgDesc->Core.bConfigurationValue,
    318                                                                 pDev->pCurCfgDesc, pDev->paIfStates, pNewCfgDesc);
     317        int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)pDev->pUsbIns->pReg->pfnUsbSetConfiguration, 5,
     318                                         pDev->pUsbIns, pNewCfgDesc->Core.bConfigurationValue,
     319                                         pDev->pCurCfgDesc, pDev->paIfStates, pNewCfgDesc);
    319320        if (RT_FAILURE(rc))
    320321        {
     
    459460    if (pDev->pUsbIns->pReg->pfnUsbSetInterface)
    460461    {
    461         int rc = pDev->pUsbIns->pReg->pfnUsbSetInterface(pDev->pUsbIns, iIf, iAlt);
     462        int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)pDev->pUsbIns->pReg->pfnUsbSetInterface, 3, pDev->pUsbIns, iIf, iAlt);
    462463        if (RT_FAILURE(rc))
    463464        {
     
    529530                &&  pDev->pUsbIns->pReg->pfnUsbClearHaltedEndpoint)
    530531            {
    531                 int rc = pDev->pUsbIns->pReg->pfnUsbClearHaltedEndpoint(pDev->pUsbIns, pSetup->wIndex);
     532                int rc = vusbDevIoThreadExecSync(pDev, (PFNRT)pDev->pUsbIns->pReg->pfnUsbClearHaltedEndpoint,
     533                                                 2, pDev->pUsbIns, pSetup->wIndex);
    532534                return RT_SUCCESS(rc);
    533535            }
     
    11311133
    11321134        /* Process any URBs waiting to be cancelled first. */
    1133         int rc = RTReqQueueProcess(pDev->hReqQueueCancel, 0); /* Don't wait if there is nothing to do. */
     1135        int rc = RTReqQueueProcess(pDev->hReqQueueSync, 0); /* Don't wait if there is nothing to do. */
    11341136        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
    1135 
    1136         /* Woken up or there is an URB to queue. */
    1137         PRTQUEUEATOMICITEM pHead = RTQueueAtomicRemoveAll(&pDev->QueueUrb);
    1138         while (pHead)
    1139         {
    1140             PVUSBURB pUrb = RT_FROM_MEMBER(pHead, VUSBURB, Dev.QueueItem);
    1141 
    1142             pHead = pHead->pNext;
    1143 
    1144             LogFlow(("%s: Queuing URB\n", pUrb->pszDesc));
    1145             rc = pUrb->pUsbIns->pReg->pfnUrbQueue(pUrb->pUsbIns, pUrb);
    1146             if (RT_FAILURE(rc))
    1147             {
    1148                 LogFlow(("%s: Queuing URB failed with %Rrc\n", pUrb->pszDesc, rc));
    1149 
    1150                 /*
    1151                  * The device was detached, so we fail everything.
    1152                  * (We should really detach and destroy the device, but we'll have to wait till Main reacts.)
    1153                  */
    1154                 if (rc == VERR_VUSB_DEVICE_NOT_ATTACHED)
    1155                     rc = vusbUrbSubmitHardError(pUrb);
    1156 
    1157                 /*
    1158                  * We don't increment error count if async URBs are in flight, in
    1159                  * this case we just assume we need to throttle back, this also
    1160                  * makes sure we don't halt bulk endpoints at the wrong time.
    1161                  */
    1162                 else if (   RT_FAILURE(rc)
    1163                          && !pDev->aPipes[pUrb->EndPt].async
    1164                          /* && pUrb->enmType == VUSBXFERTYPE_BULK ?? */
    1165                          && !vusbUrbErrorRh(pUrb))
    1166                 {
    1167                     /* don't retry it anymore. */
    1168                     pUrb->enmState = VUSBURBSTATE_REAPED;
    1169                     pUrb->enmStatus = VUSBSTATUS_CRC;
    1170                     vusbUrbCompletionRh(pUrb);
    1171                 }
    1172             }
    1173         }
    11741137    }
    11751138
     
    13001263
    13011264    /* Destroy request queue. */
    1302     int rc = RTReqQueueDestroy(pDev->hReqQueueCancel);
     1265    int rc = RTReqQueueDestroy(pDev->hReqQueueSync);
    13031266    AssertRC(rc);
    13041267
     
    16561619}
    16571620
     1621
     1622/**
     1623 * Executes a given function synchronously on the I/O thread waiting for it to complete.
     1624 *
     1625 * @returns IPRT status code.
     1626 * @param   pDev           The USB device instance data
     1627 * @param   pfnFunction    The function to execute.
     1628 * @param   cArgs          Number of arguments to the function.
     1629 * @param   ...            The parameter list.
     1630 *
     1631 * @remarks See remarks on RTReqQueueCallV
     1632 */
     1633DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...)
     1634{
     1635    int rc = VINF_SUCCESS;
     1636    PRTREQ hReq = NULL;
     1637    va_list va;
     1638
     1639    va_start(va, cArgs);
     1640    Assert(pDev->hUrbIoThread != NIL_RTTHREAD);
     1641    if (RT_LIKELY(pDev->hUrbIoThread != NIL_RTTHREAD))
     1642    {
     1643        rc = RTReqQueueCallV(pDev->hReqQueueSync, &hReq, 0 /* cMillies */, RTREQFLAGS_IPRT_STATUS, pfnFunction, cArgs, va);
     1644        Assert(RT_SUCCESS(rc) || rc == VERR_TIMEOUT);
     1645        vusbDevUrbIoThreadWakeup(pDev);
     1646        rc = RTReqWait(hReq, RT_INDEFINITE_WAIT);
     1647        AssertRC(rc);
     1648    }
     1649    else
     1650        rc = VERR_INVALID_STATE;
     1651
     1652    va_end(va);
     1653    return rc;
     1654}
     1655
     1656static DECLCALLBACK(int) vusbDevGetDescriptorCacheWorker(PPDMUSBINS pUsbIns, PCPDMUSBDESCCACHE *ppDescCache)
     1657{
     1658    *ppDescCache = pUsbIns->pReg->pfnUsbGetDescriptorCache(pUsbIns);
     1659    return VINF_SUCCESS;
     1660}
    16581661
    16591662/**
     
    16961699    pDev->pvResetArgs = NULL;
    16971700    pDev->pResetTimer = NULL;
    1698     RTQueueAtomicInit(&pDev->QueueUrb);
    16991701
    17001702    /*
     
    17051707    AssertRCReturn(rc, rc);
    17061708
     1709    /* Setup request queue executing synchronous tasks on the I/O thread. */
     1710    rc = RTReqQueueCreate(&pDev->hReqQueueSync);
     1711    AssertRCReturn(rc, rc);
     1712
     1713    /* Create I/O thread. */
     1714    rc = vusbDevUrbIoThreadCreate(pDev);
     1715    AssertRCReturn(rc, rc);
     1716
    17071717    /*
    17081718     * Get the descriptor cache from the device. (shall cannot fail)
    17091719     */
    1710     pDev->pDescCache = pUsbIns->pReg->pfnUsbGetDescriptorCache(pUsbIns);
    1711     Assert(pDev->pDescCache);
     1720    rc = vusbDevIoThreadExecSync(pDev, (PFNRT)vusbDevGetDescriptorCacheWorker, 2, pUsbIns, &pDev->pDescCache);
     1721    AssertRC(rc);
     1722    AssertPtr(pDev->pDescCache);
    17121723#ifdef VBOX_STRICT
    17131724    if (pDev->pDescCache->fUseCachedStringsDescriptors)
     
    17401751    AssertMsgReturn(pDev->paIfStates, ("RTMemAllocZ(%d) failed\n", cbIface), VERR_NO_MEMORY);
    17411752
    1742     /* Setup request queue for cancelling URBs synchronously. */
    1743     rc = RTReqQueueCreate(&pDev->hReqQueueCancel);
    1744     AssertRCReturn(rc, rc);
    1745 
    1746     rc = vusbDevUrbIoThreadCreate(pDev);
    1747     AssertRCReturn(rc, rc);
    1748 
    17491753    return VINF_SUCCESS;
    17501754}
  • trunk/src/VBox/Devices/USB/VUSBInternal.h

    r52150 r52254  
    113113void vusbMsgResetExtraData(PVUSBCTRLEXTRA pExtra);
    114114
     115/** Opaque VUSB read ahead buffer management handle. */
     116typedef struct VUSBREADAHEADINT *VUSBREADAHEAD;
    115117
    116118/**
     
    125127    /** Count of active async transfers. */
    126128    volatile uint32_t   async;
    127     /** The periodic read-ahead buffer thread. */
    128     RTTHREAD            ReadAheadThread;
    129     /** Pointer to the reset thread arguments. */
    130     void               *pvReadAheadArgs;
    131     /** Pointer to the first buffered URB. */
    132     PVUSBURB            pBuffUrbHead;
    133     /** Pointer to the last buffered URB. */
    134     PVUSBURB            pBuffUrbTail;
    135     /** Count of URBs in read-ahead buffer. */
    136     uint32_t            cBuffered;
    137     /** Count of URBs submitted for read-ahead but not yet reaped. */
    138     uint32_t            cSubmitted;
     129    /** Read ahead handle. */
     130    VUSBREADAHEAD       hReadAhead;
    139131} VUSBPIPE;
    140132/** Pointer to a VUSB pipe structure. */
     
    218210    /** URB submit and reap thread. */
    219211    RTTHREAD            hUrbIoThread;
    220     /** Queue of URBs to submit. */
    221     RTQUEUEATOMIC       QueueUrb;
    222     /** Request queue for cancelling URBs on the I/O thread. */
    223     RTREQQUEUE          hReqQueueCancel;
     212    /** Request queue for executing tasks on the I/O thread which should be done
     213     * synchronous and without any other thread accessing the USB device. */
     214    RTREQQUEUE          hReqQueueSync;
    224215    /** Flag whether the URB I/O thread should terminate. */
    225216    bool volatile       fTerminate;
     
    455446int vusbDevUrbIoThreadCreate(PVUSBDEV pDev);
    456447int vusbDevUrbIoThreadDestroy(PVUSBDEV pDev);
     448DECLHIDDEN(int) vusbDevIoThreadExecSync(PVUSBDEV pDev, PFNRT pfnFunction, unsigned cArgs, ...);
    457449
    458450void vusbUrbCompletionReadAhead(PVUSBURB pUrb);
    459 void vusbReadAheadStart(PVUSBDEV pDev, PVUSBPIPE pPipe);
    460 void vusbReadAheadStop(void *pvReadAheadArgs);
     451VUSBREADAHEAD vusbReadAheadStart(PVUSBDEV pDev, PVUSBPIPE pPipe);
     452void vusbReadAheadStop(VUSBREADAHEAD hReadAhead);
    461453int  vusbUrbQueueAsyncRh(PVUSBURB pUrb);
    462 int  vusbUrbSubmitBufferedRead(PVUSBURB pUrb, PVUSBPIPE pPipe);
     454int  vusbUrbSubmitBufferedRead(PVUSBURB pUrb, VUSBREADAHEAD hReadAhead);
    463455PVUSBURB vusbRhNewUrb(PVUSBROOTHUB pRh, uint8_t DstAddress, uint32_t cbData, uint32_t cTds);
    464456
  • trunk/src/VBox/Devices/USB/VUSBReadAhead.cpp

    r50453 r52254  
    3232#include <iprt/assert.h>
    3333#include <iprt/asm.h>
     34#include <iprt/critsect.h>
    3435#include "VUSBInternal.h"
    3536
     
    4041
    4142/**
    42  * Argument package of vusbDevReadAheadThread().
    43  */
    44 typedef struct vusb_read_ahead_args
     43 * VUSB Readahead instance data.
     44 */
     45typedef struct VUSBREADAHEADINT
    4546{
    4647    /** Pointer to the device which the thread is for. */
     
    5152    bool                fHighSpeed;
    5253    /** A flag telling the thread to terminate. */
    53     bool                fTerminate;
    54 } VUSBREADAHEADARGS, *PVUSBREADAHEADARGS;
     54    volatile bool       fTerminate;
     55    /** Maximum number of URBs to submit. */
     56    uint32_t            cUrbsMax;
     57    /** The periodic read-ahead buffer thread. */
     58    RTTHREAD            hReadAheadThread;
     59    /** Pointer to the first buffered URB. */
     60    PVUSBURB            pBuffUrbHead;
     61    /** Pointer to the last buffered URB. */
     62    PVUSBURB            pBuffUrbTail;
     63    /** Count of URBs in read-ahead buffer. */
     64    uint32_t            cBuffered;
     65    /** Count of URBs submitted for read-ahead but not yet reaped. */
     66    uint32_t            cSubmitted;
     67    /** Critical section to serialize access the buffered URB list. */
     68    RTCRITSECT          CritSectBuffUrbList;
     69} VUSBREADAHEADINT, *PVUSBREADAHEADINT;
    5570
    5671
     
    156171static DECLCALLBACK(int) vusbDevReadAheadThread(RTTHREAD Thread, void *pvUser)
    157172{
     173    PVUSBREADAHEADINT       pThis = (PVUSBREADAHEADINT)pvUser;
    158174    PVUSBPIPE               pPipe;
    159     PVUSBREADAHEADARGS      pArgs = (PVUSBREADAHEADARGS)pvUser;
    160175    PCVUSBDESCENDPOINT      pDesc;
    161176    PVUSBURB                pUrb;
     
    164179
    165180    LogFlow(("vusb: periodic read-ahead buffer thread started\n"));
    166     Assert(pArgs);
    167     Assert(pArgs->pPipe && pArgs->pDev);
    168 
    169     pPipe = pArgs->pPipe;
     181    Assert(pThis);
     182    Assert(pThis->pPipe && pThis->pDev);
     183
     184    pPipe = pThis->pPipe;
    170185    pDesc = &pPipe->in->Core;
    171186    Assert(pDesc);
    172187
    173     /* The previous read-ahead thread could be still running (vusbReadAheadStop sets only
    174      * fTerminate to true and returns immediately). Therefore we have to wait until the
    175      * previous thread is done and all submitted URBs are completed. */
    176     while (   pPipe->cSubmitted > 0
    177            && pPipe->cBuffered > 0)
    178     {
    179         Log2(("vusbDevReadAheadThread: still %u packets submitted, waiting before starting...\n", pPipe->cSubmitted));
    180         RTThreadSleep(1);
    181     }
    182     pPipe->pvReadAheadArgs = pArgs;
    183     pPipe->cBuffered = 0;
     188    Assert(!pThis->cSubmitted && !pThis->cBuffered);
    184189
    185190    /* Figure out the maximum bandwidth we might need */
    186     if (pArgs->fHighSpeed)
     191    if (pThis->fHighSpeed)
    187192    {
    188193        /* High-speed endpoint */
     
    207212     * queue the URBs here, they are reaped on a different thread.
    208213     */
    209     while (pArgs->fTerminate == false)
    210     {
    211         while (pPipe->cSubmitted < 120 && pPipe->cBuffered < 120)
    212         {
    213             pUrb = vusbDevNewIsocUrb(pArgs->pDev, pDesc->bEndpointAddress & 0xF, interval, max_pkt_size * mult);
     214    while (!pThis->fTerminate)
     215    {
     216        while (pThis->cSubmitted < pThis->cUrbsMax && pThis->cBuffered < pThis->cUrbsMax)
     217        {
     218            pUrb = vusbDevNewIsocUrb(pThis->pDev, pDesc->bEndpointAddress & 0xF, interval, max_pkt_size * mult);
    214219            if (!pUrb) {
    215220                /* Happens if device was unplugged. */
    216221                Log(("vusb: read-ahead thread failed to allocate new URB; exiting\n"));
    217                 vusbReadAheadStop(pvUser);
     222                vusbReadAheadStop(pThis);
    218223                break;
    219224            }
     
    230235                /* Happens if device was unplugged. */
    231236                Log(("vusb: read-ahead thread failed to queue URB with %Rrc; exiting\n", rc));
    232                 vusbReadAheadStop(pvUser);
     237                pThis->cUrbsMax = pThis->cSubmitted;
     238                pUrb->VUsb.pfnFree(pUrb);
    233239                break;
    234240            }
    235             ++pPipe->cSubmitted;
     241            else
     242                ASMAtomicIncU32(&pThis->cSubmitted);
    236243        }
    237244        RTThreadSleep(1);
    238245    }
    239246    LogFlow(("vusb: periodic read-ahead buffer thread exiting\n"));
    240     pPipe->pvReadAheadArgs = NULL;
    241247
    242248    /* wait until there are no more submitted packets */
    243     while (pPipe->cSubmitted > 0)
    244     {
    245         Log2(("vusbDevReadAheadThread: still %u packets submitted, waiting before terminating...\n", pPipe->cSubmitted));
     249    while (pThis->cSubmitted > 0)
     250    {
     251        Log2(("vusbDevReadAheadThread: still %u packets submitted, waiting before terminating...\n", pThis->cSubmitted));
    246252        RTThreadSleep(1);
    247253    }
    248254
     255    RTCritSectEnter(&pThis->CritSectBuffUrbList);
    249256    /*
    250257     * Free all still buffered URBs because another endpoint with a different packet size
    251258     * and complete different data formats might be served later.
    252259     */
    253     while (pPipe->pBuffUrbHead)
    254     {
    255         PVUSBURB pBufferedUrb = pPipe->pBuffUrbHead;
    256 
    257         pPipe->pBuffUrbHead = pBufferedUrb->Hci.pNext;
     260    while (pThis->pBuffUrbHead)
     261    {
     262        PVUSBURB pBufferedUrb = pThis->pBuffUrbHead;
     263
     264        pThis->pBuffUrbHead = pBufferedUrb->Hci.pNext;
    258265        pBufferedUrb->VUsb.pfnFree(pBufferedUrb);
    259266    }
    260267
    261     pPipe->pBuffUrbTail = NULL;
    262     pPipe->cBuffered = 0;
    263     RTMemTmpFree(pArgs);
     268    RTCritSectLeave(&pThis->CritSectBuffUrbList);
     269    RTCritSectDelete(&pThis->CritSectBuffUrbList);
     270    RTMemTmpFree(pThis);
    264271
    265272    return rc;
     
    275282    Assert(pUrb);
    276283    Assert(pUrb->Hci.pNext);
    277     PVUSBREADAHEADARGS      pArgs = (PVUSBREADAHEADARGS)pUrb->Hci.pNext;
    278     PVUSBPIPE               pPipe = pArgs->pPipe;
     284    PVUSBREADAHEADINT pThis = (PVUSBREADAHEADINT)pUrb->Hci.pNext;
     285    PVUSBPIPE         pPipe = pThis->pPipe;
    279286    Assert(pPipe);
    280287
     288    RTCritSectEnter(&pThis->CritSectBuffUrbList);
    281289    pUrb->Hci.pNext = NULL; // @todo: use a more suitable field
    282     if (pPipe->pBuffUrbHead == NULL)
     290    if (pThis->pBuffUrbHead == NULL)
    283291    {
    284292        // The queue is empty, this is easy
    285         Assert(!pPipe->pBuffUrbTail);
    286         pPipe->pBuffUrbTail = pPipe->pBuffUrbHead = pUrb;
     293        Assert(!pThis->pBuffUrbTail);
     294        pThis->pBuffUrbTail = pThis->pBuffUrbHead = pUrb;
    287295    }
    288296    else
    289297    {
    290298        // Some URBs are queued already
    291         Assert(pPipe->pBuffUrbTail);
    292         Assert(!pPipe->pBuffUrbTail->Hci.pNext);
    293         pPipe->pBuffUrbTail = pPipe->pBuffUrbTail->Hci.pNext = pUrb;
    294     }
    295     --pPipe->cSubmitted;
    296     ++pPipe->cBuffered;
     299        Assert(pThis->pBuffUrbTail);
     300        Assert(!pThis->pBuffUrbTail->Hci.pNext);
     301        pThis->pBuffUrbTail = pThis->pBuffUrbTail->Hci.pNext = pUrb;
     302    }
     303    ASMAtomicDecU32(&pThis->cSubmitted);
     304    ++pThis->cBuffered;
     305    RTCritSectLeave(&pThis->CritSectBuffUrbList);
    297306}
    298307
     
    303312 *
    304313 * @param pUrb      The URB submitted by HC
    305  * @param pPipe     The pipe with read-ahead buffering
     314 * @param hReadAhead The read-ahead buffering instance
    306315 *
    307316 * @return int      Status code
    308317 */
    309 int vusbUrbSubmitBufferedRead(PVUSBURB pUrb, PVUSBPIPE pPipe)
    310 {
    311     PVUSBURB    pBufferedUrb;
    312     Assert(pUrb && pPipe);
    313 
    314     pBufferedUrb = pPipe->pBuffUrbHead;
     318int vusbUrbSubmitBufferedRead(PVUSBURB pUrb, VUSBREADAHEAD hReadAhead)
     319{
     320    PVUSBREADAHEADINT pThis = hReadAhead;
     321    PVUSBURB pBufferedUrb;
     322    Assert(pUrb && pThis);
     323
     324    RTCritSectEnter(&pThis->CritSectBuffUrbList);
     325    pBufferedUrb = pThis->pBuffUrbHead;
    315326    if (pBufferedUrb)
    316327    {
     
    318329
    319330        // There's a URB available in the read-ahead buffer; use it
    320         pPipe->pBuffUrbHead = pBufferedUrb->Hci.pNext;
    321         if (pPipe->pBuffUrbHead == NULL)
    322             pPipe->pBuffUrbTail = NULL;
    323 
    324         --pPipe->cBuffered;
     331        pThis->pBuffUrbHead = pBufferedUrb->Hci.pNext;
     332        if (pThis->pBuffUrbHead == NULL)
     333            pThis->pBuffUrbTail = NULL;
     334
     335        --pThis->cBuffered;
     336        RTCritSectLeave(&pThis->CritSectBuffUrbList);
    325337
    326338        // Make sure the buffered URB is what we expect
     
    358370    else
    359371    {
     372        RTCritSectLeave(&pThis->CritSectBuffUrbList);
    360373        // No URB on hand. Either we exhausted the buffer (shouldn't happen!) or the guest simply
    361374        // asked for data too soon. Pretend that the device didn't deliver any data.
     
    370383        // This assertion is wrong as the URB could be re-allocated in the meantime by the EMT (race)
    371384        // Assert(pUrb->enmState == VUSBURBSTATE_FREE);
    372         LogFlow(("%s: vusbUrbSubmitBufferedRead: No buffered URB available!\n", pBufferedUrb->pszDesc));
     385        LogFlow(("vusbUrbSubmitBufferedRead: No buffered URB available!\n"));
    373386    }
    374387    return VINF_SUCCESS;
     
    377390/* Read-ahead start/stop functions, used primarily to keep the PVUSBREADAHEADARGS struct private to this module. */
    378391
    379 void vusbReadAheadStart(PVUSBDEV pDev, PVUSBPIPE pPipe)
     392VUSBREADAHEAD vusbReadAheadStart(PVUSBDEV pDev, PVUSBPIPE pPipe)
    380393{
    381394    int rc;
    382     PVUSBREADAHEADARGS pArgs = (PVUSBREADAHEADARGS)RTMemTmpAlloc(sizeof(*pArgs));
    383 
    384     if (pArgs)
     395    PVUSBREADAHEADINT pThis = (PVUSBREADAHEADINT)RTMemTmpAlloc(sizeof(VUSBREADAHEADINT));
     396
     397    if (pThis)
    385398    {
    386399        PVUSBROOTHUB pRh = vusbDevGetRh(pDev);
    387         pArgs->pDev  = pDev;
    388         pArgs->pPipe = pPipe;
    389         pArgs->fTerminate = false;
    390         pArgs->fHighSpeed = pRh && ((pRh->fHcVersions & VUSB_STDVER_20) != 0);
    391         if (pArgs->fHighSpeed)
    392             rc = RTThreadCreate(&pPipe->ReadAheadThread, vusbDevReadAheadThread, pArgs, 0, RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "USBISOC");
    393         else
    394             rc = VERR_VUSB_DEVICE_NOT_ATTACHED; // No buffering for low/full-speed devices at the moment, needs testing.
     400        pThis->pDev         = pDev;
     401        pThis->pPipe        = pPipe;
     402        pThis->fTerminate   = false;
     403        pThis->fHighSpeed   = pRh && ((pRh->fHcVersions & VUSB_STDVER_20) != 0);
     404        pThis->cUrbsMax     = 120;
     405        pThis->pBuffUrbHead = NULL;
     406        pThis->pBuffUrbTail = NULL;
     407        pThis->cBuffered    = 0;
     408        pThis->cSubmitted   = 0;
     409        rc = RTCritSectInit(&pThis->CritSectBuffUrbList);
    395410        if (RT_SUCCESS(rc))
    396411        {
    397             Log(("vusb: created isochronous read-ahead thread\n"));
    398         }
    399         else
    400         {
    401             Log(("vusb: isochronous read-ahead thread creation failed, rc=%d\n", rc));
    402             pPipe->ReadAheadThread = NIL_RTTHREAD;
    403             RTMemTmpFree(pArgs);
    404         }
    405     }
     412            if (pThis->fHighSpeed)
     413                rc = RTThreadCreate(&pThis->hReadAheadThread, vusbDevReadAheadThread, pThis, 0, RTTHREADTYPE_IO, 0 /* fFlags */, "USBISOC");
     414            else
     415                rc = VERR_VUSB_DEVICE_NOT_ATTACHED; // No buffering for low/full-speed devices at the moment, needs testing.
     416            if (RT_SUCCESS(rc))
     417            {
     418                Log(("vusb: created isochronous read-ahead thread\n"));
     419                return pThis;
     420            }
     421            else
     422                Log(("vusb: isochronous read-ahead thread creation failed, rc=%d\n", rc));
     423
     424            rc = RTCritSectDelete(&pThis->CritSectBuffUrbList);
     425            AssertRC(rc);
     426        }
     427
     428        RTMemTmpFree(pThis);
     429    }
     430
    406431    /* If thread creation failed for any reason, simply fall back to standard processing. */
    407 }
    408 
    409 void vusbReadAheadStop(void *pvReadAheadArgs)
    410 {
    411     PVUSBREADAHEADARGS  pArgs = (PVUSBREADAHEADARGS)pvReadAheadArgs;
     432    return NULL;
     433}
     434
     435void vusbReadAheadStop(VUSBREADAHEAD hReadAhead)
     436{
     437    PVUSBREADAHEADINT pThis = hReadAhead;
    412438    Log(("vusb: terminating read-ahead thread for endpoint\n"));
    413     pArgs->fTerminate = true;
     439    ASMAtomicXchgBool(&pThis->fTerminate, true);
    414440}
    415441
  • trunk/src/VBox/Devices/USB/VUSBUrb.cpp

    r52148 r52254  
    11201120#endif
    11211121
    1122     /** @todo explain why we do this pDev change. */
    1123     PVUSBDEV pTmp = pUrb->VUsb.pDev;
    1124     pUrb->VUsb.pDev = &pRh->Hub.Dev;
    11251122    pRh->pIRhPort->pfnXferCompletion(pRh->pIRhPort, pUrb);
    1126     pUrb->VUsb.pDev = pTmp;
    11271123    if (pUrb->enmState == VUSBURBSTATE_REAPED)
    11281124    {
     
    12051201    }
    12061202
     1203    RTCritSectEnter(&pRh->CritSect);
     1204    int rc = pUrb->pUsbIns->pReg->pfnUrbQueue(pUrb->pUsbIns, pUrb);
     1205    if (RT_FAILURE(rc))
     1206    {
     1207        LogFlow(("%s: vusbUrbQueueAsyncRh: returns %Rrc (queue_urb)\n", pUrb->pszDesc, rc));
     1208        RTCritSectLeave(&pRh->CritSect);
     1209        return rc;
     1210    }
     1211
    12071212    ASMAtomicIncU32(&pDev->aPipes[pUrb->EndPt].async);
    12081213
    12091214    /* Queue the pUrb on the roothub */
    1210     RTCritSectEnter(&pRh->CritSect);
    12111215    pUrb->VUsb.pNext = pRh->pAsyncUrbHead;
    12121216    if (pRh->pAsyncUrbHead)
     
    12151219    pUrb->VUsb.ppPrev = &pRh->pAsyncUrbHead;
    12161220    RTCritSectLeave(&pRh->CritSect);
    1217 
    1218     RTQueueAtomicInsert(&pDev->QueueUrb, &pUrb->Dev.QueueItem);
    1219     vusbDevUrbIoThreadWakeup(pDev);
    12201221
    12211222    return VINF_SUCCESS;
     
    18811882
    18821883#ifdef VBOX_WITH_USB
    1883     if (pPipe && pPipe->pBuffUrbHead)
    1884     {
    1885         rc = vusbUrbSubmitBufferedRead(pUrb, pPipe);
     1884    if (pPipe && pPipe->hReadAhead)
     1885    {
     1886        rc = vusbUrbSubmitBufferedRead(pUrb, pPipe->hReadAhead);
    18861887        return rc;
    18871888    }
     
    21252126void vusbUrbCancel(PVUSBURB pUrb, CANCELMODE mode)
    21262127{
    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);
     2128    int rc = vusbDevIoThreadExecSync(pUrb->VUsb.pDev, (PFNRT)vusbUrbCancelWorker, 2, pUrb, mode);
     2129    AssertRC(rc);
    21402130}
    21412131
  • trunk/src/VBox/Devices/USB/darwin/USBProxyDevice-darwin.cpp

    r50234 r52254  
    233233    /** The list of free Darwin URBs. Singly linked. */
    234234    PUSBPROXYURBOSX         pFreeHead;
    235     /** The list of active Darwin URBs. Doubly linked.
    236      * Only the split head will appear in this list. */
    237     PUSBPROXYURBOSX         pInFlightHead;
    238235    /** The list of landed Darwin URBs. Doubly linked.
    239236     * Only the split head will appear in this list. */
     
    241238    /** The tail of the landed Darwin URBs. */
    242239    PUSBPROXYURBOSX         pTaxingTail;
    243     /* Runloop source for waking up the reaper thread. */
     240    /** Last reaper runloop reference, there can be only one runloop at a time. */
     241    CFRunLoopRef            hRunLoopReapingLast;
     242    /** Runloop source for waking up the reaper thread. */
    244243    CFRunLoopSourceRef      hRunLoopSrcWakeRef;
    245244    /** List of threads used for reaping which can be woken up. */
     
    290289
    291290/**
     291 * Kicks the reaper thread if it sleeps currently to respond to state changes
     292 * or to pick up completed URBs.
     293 *
     294 * @returns nothing.
     295 * @param   pDevOsX    The darwin device instance data.
     296 */
     297static void usbProxyDarwinReaperKick(PUSBPROXYDEVOSX pDevOsX)
     298{
     299    CFRunLoopRef hRunLoopWake = (CFRunLoopRef)ASMAtomicReadPtr((void * volatile *)&pDevOsX->hRunLoopReaping);
     300    if (hRunLoopWake)
     301    {
     302        LogFlowFunc(("Waking runloop %p\n", hRunLoopWake));
     303        CFRunLoopSourceSignal(pDevOsX->hRunLoopSrcWakeRef);
     304        CFRunLoopWakeUp(hRunLoopWake);
     305    }
     306}
     307
     308/**
    292309 * Adds Source ref to current run loop and adds it the list of runloops.
    293310 */
     
    368385    pUrbOsX = pDevOsX->pFreeHead;
    369386    if (pUrbOsX)
     387    {
    370388        pDevOsX->pFreeHead = pUrbOsX->pNext;
     389        RTCritSectLeave(&pDevOsX->CritSect);
     390    }
    371391    else
    372392    {
     
    375395        if (!pUrbOsX)
    376396            return NULL;
    377         RTCritSectEnter(&pDevOsX->CritSect);
    378397    }
    379398    pUrbOsX->pVUsbUrb = NULL;
     
    381400    pUrbOsX->enmType = VUSBXFERTYPE_INVALID;
    382401
    383     /*
    384      * Link it into the active list
    385      */
    386     pUrbOsX->pPrev = NULL;
    387     pUrbOsX->pNext = pDevOsX->pInFlightHead;
    388     if (pUrbOsX->pNext)
    389         pUrbOsX->pNext->pPrev = pUrbOsX;
    390     pDevOsX->pInFlightHead = pUrbOsX;
    391 
    392     RTCritSectLeave(&pDevOsX->CritSect);
    393402    return pUrbOsX;
    394403}
     
    500509{
    501510    RTCritSectEnter(&pDevOsX->CritSect);
    502 
    503     /*
    504      * Remove from the active or taxing list.
    505      */
    506     if (pUrbOsX->pNext)
    507         pUrbOsX->pNext->pPrev   = pUrbOsX->pPrev;
    508     else if (pDevOsX->pTaxingTail == pUrbOsX)
    509         pDevOsX->pTaxingTail    = pUrbOsX->pPrev;
    510 
    511     if (pUrbOsX->pPrev)
    512         pUrbOsX->pPrev->pNext   = pUrbOsX->pNext;
    513     else if (pDevOsX->pTaxingHead == pUrbOsX)
    514         pDevOsX->pTaxingHead    = pUrbOsX->pNext;
    515     else if (pDevOsX->pInFlightHead == pUrbOsX)
    516         pDevOsX->pInFlightHead  = pUrbOsX->pNext;
    517     else
    518         AssertFailed();
    519511
    520512#ifdef USE_LOW_LATENCY_API
     
    595587    PUSBPROXYDEVOSX pDevOsX = pUrbOsX->pDevOsX;
    596588    const uint32_t cb = (uintptr_t)Size;
    597 
    598     RTCritSectEnter(&pDevOsX->CritSect);
    599589
    600590    /*
     
    646636    }
    647637
    648     /*
    649      * Remove from the active list.
    650      */
    651     if (pUrbOsX->pNext)
    652         pUrbOsX->pNext->pPrev = pUrbOsX->pPrev;
    653     if (pUrbOsX->pPrev)
    654         pUrbOsX->pPrev->pNext = pUrbOsX->pNext;
    655     else
    656     {
    657         Assert(pDevOsX->pInFlightHead == pUrbOsX);
    658         pDevOsX->pInFlightHead = pUrbOsX->pNext;
    659     }
     638    RTCritSectEnter(&pDevOsX->CritSect);
    660639
    661640    /*
     
    683662static void usbProxyDarwinReleaseAllInterfaces(PUSBPROXYDEVOSX pDevOsX)
    684663{
     664    RTCritSectEnter(&pDevOsX->CritSect);
     665
     666    /* Kick the reaper thread out of sleep. */
     667    usbProxyDarwinReaperKick(pDevOsX);
     668
    685669    PUSBPROXYIFOSX pIf = pDevOsX->pIfHead;
    686670    pDevOsX->pIfHead = pDevOsX->pIfTail = NULL;
     
    728712        pIf = pNext;
    729713    }
     714    RTCritSectLeave(&pDevOsX->CritSect);
    730715}
    731716
     
    808793{
    809794    PUSBPROXYDEV pProxyDev = pDevOsX->pProxyDev;
     795
     796    RTCritSectEnter(&pDevOsX->CritSect);
    810797
    811798    /*
     
    968955        rc = VERR_GENERAL_FAILURE;
    969956    }
     957
     958    RTCritSectLeave(&pDevOsX->CritSect);
    970959    return rc;
    971960}
     
    10741063    return;
    10751064}
     1065
    10761066
    10771067/* -=-=-=-=-=- The exported methods -=-=-=-=-=- */
     
    12401230                if (RT_SUCCESS(vrc))
    12411231                {
    1242                     pDevOsX->USBDevice = USBDevice;
    1243                     pDevOsX->ppDevI = ppDevI;
    1244                     pDevOsX->pProxyDev = pProxyDev;
     1232                    pDevOsX->USBDevice           = USBDevice;
     1233                    pDevOsX->ppDevI              = ppDevI;
     1234                    pDevOsX->pProxyDev           = pProxyDev;
     1235                    pDevOsX->pTaxingHead         = NULL;
     1236                    pDevOsX->pTaxingTail         = NULL;
     1237                    pDevOsX->hRunLoopReapingLast = NULL;
    12451238
    12461239                    /*
     
    14091402
    14101403    PUSBPROXYURBOSX pUrbOsX;
    1411     while ((pUrbOsX = pDevOsX->pInFlightHead) != NULL)
    1412     {
    1413         pDevOsX->pInFlightHead = pUrbOsX->pNext;
    1414         //RTMemFree(pUrbOsX); - leak these for now, fix later.
    1415     }
    1416 
    14171404    while ((pUrbOsX = pDevOsX->pFreeHead) != NULL)
    14181405    {
     
    16221609    if (pUrb->EndPt)
    16231610    {
     1611        /* Make sure the interface is there. */
    16241612        const uint8_t EndPt = pUrb->EndPt | (pUrb->enmDir == VUSBDIRECTION_IN ? 0x80 : 0);
    16251613        pIf = usbProxyDarwinGetInterfaceForEndpoint(pDevOsX, EndPt, &u8PipeRef, &pPipe);
     
    16301618            return VERR_NOT_FOUND;
    16311619        }
    1632 
    1633         if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pIf->RunLoopSrcRef, g_pRunLoopMode))
    1634             usbProxyDarwinAddRunLoopRef(&pIf->HeadOfRunLoopLst, pIf->RunLoopSrcRef);
    1635 
    16361620    }
    16371621    /* else: pIf == NULL -> default control pipe.*/
    1638 
    1639     if (!CFRunLoopContainsSource(CFRunLoopGetCurrent(), pDevOsX->RunLoopSrcRef, g_pRunLoopMode))
    1640         usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef);
    16411622
    16421623    /*
     
    18001781        case kIOUSBPipeStalled:
    18011782        {
     1783            /* Increment in flight counter because the completion handler will decrease it always. */
    18021784            usbProxyDarwinUrbAsyncComplete(pUrbOsX, kIOUSBPipeStalled, 0);
    18031785            Log(("%s: usbProxyDarwinUrbQueue: pProxyDev=%s EndPt=%d cbData=%d - failed irc=%#x! (stall)\n",
     
    18071789    }
    18081790
     1791    usbProxyDarwinUrbFree(pDevOsX, pUrbOsX);
    18091792    Log(("%s: usbProxyDarwinUrbQueue: pProxyDev=%s EndPt=%d cbData=%d - failed irc=%#x!\n",
    18101793         pUrb->pszDesc, pProxyDev->pUsbIns->pszName, pUrb->EndPt, pUrb->cbData, irc));
     
    18291812    Assert(!pDevOsX->hRunLoopReaping);
    18301813
    1831     if (!CFRunLoopContainsSource(hRunLoopRef, pDevOsX->hRunLoopSrcWakeRef, g_pRunLoopMode))
    1832         usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopWakeLst, pDevOsX->hRunLoopSrcWakeRef);
     1814    /*
     1815     * If the last seen runloop for reaping differs we have to check whether the
     1816     * the runloop sources are in the new runloop.
     1817     */
     1818    if (pDevOsX->hRunLoopReapingLast != hRunLoopRef)
     1819    {
     1820        RTCritSectEnter(&pDevOsX->CritSect);
     1821
     1822        /* Every pipe. */
     1823        if (!pDevOsX->pIfHead)
     1824            usbProxyDarwinSeizeAllInterfaces(pDevOsX, true /* make the best out of it */);
     1825
     1826        PUSBPROXYIFOSX pIf;
     1827        for (pIf = pDevOsX->pIfHead; pIf; pIf = pIf->pNext)
     1828        {
     1829            if (!CFRunLoopContainsSource(hRunLoopRef, pIf->RunLoopSrcRef, g_pRunLoopMode))
     1830                usbProxyDarwinAddRunLoopRef(&pIf->HeadOfRunLoopLst, pIf->RunLoopSrcRef);
     1831        }
     1832
     1833        /* Default control pipe. */
     1834        if (!CFRunLoopContainsSource(hRunLoopRef, pDevOsX->RunLoopSrcRef, g_pRunLoopMode))
     1835            usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopLst, pDevOsX->RunLoopSrcRef);
     1836
     1837        /* Runloop wakeup source. */
     1838        if (!CFRunLoopContainsSource(hRunLoopRef, pDevOsX->hRunLoopSrcWakeRef, g_pRunLoopMode))
     1839            usbProxyDarwinAddRunLoopRef(&pDevOsX->HeadOfRunLoopWakeLst, pDevOsX->hRunLoopSrcWakeRef);
     1840        RTCritSectLeave(&pDevOsX->CritSect);
     1841
     1842        pDevOsX->hRunLoopReapingLast = hRunLoopRef;
     1843    }
    18331844
    18341845    ASMAtomicXchgPtr((void * volatile *)&pDevOsX->hRunLoopReaping, hRunLoopRef);
     
    18421853
    18431854    /*
    1844      * If we've got any in-flight URBs, excercise the runloop.
    1845      */
    1846     if (pDevOsX->pInFlightHead)
    1847         CFRunLoopRunInMode(g_pRunLoopMode, 0.0, false);
    1848 
     1855     * Excercise the runloop until we get an URB or we time out.
     1856     */
    18491857    if (    !pDevOsX->pTaxingHead
    18501858        &&  cMillies)
     
    18651873        if (pUrbOsX)
    18661874        {
     1875            /*
     1876             * Remove from the taxing list.
     1877             */
     1878            if (pUrbOsX->pNext)
     1879                pUrbOsX->pNext->pPrev   = pUrbOsX->pPrev;
     1880            else if (pDevOsX->pTaxingTail == pUrbOsX)
     1881                pDevOsX->pTaxingTail    = pUrbOsX->pPrev;
     1882
     1883            if (pUrbOsX->pPrev)
     1884                pUrbOsX->pPrev->pNext   = pUrbOsX->pNext;
     1885            else if (pDevOsX->pTaxingHead == pUrbOsX)
     1886                pDevOsX->pTaxingHead    = pUrbOsX->pNext;
     1887            else
     1888                AssertFailed();
     1889
    18671890            pUrb = pUrbOsX->pVUsbUrb;
    18681891            if (pUrb)
     
    19381961
    19391962    ASMAtomicXchgBool(&pDevOsX->fReapingThreadWake, true);
    1940 
    1941     CFRunLoopRef hRunLoopWake = (CFRunLoopRef)ASMAtomicReadPtr((void * volatile *)&pDevOsX->hRunLoopReaping);
    1942     if (hRunLoopWake)
    1943     {
    1944         LogFlow(("usbProxyDarwinWakeup: Waking runloop %p\n", hRunLoopWake));
    1945         CFRunLoopSourceSignal(pDevOsX->hRunLoopSrcWakeRef);
    1946         CFRunLoopWakeUp(hRunLoopWake);
    1947     }
    1948 
     1963    usbProxyDarwinReaperKick(pDevOsX);
    19491964    return VINF_SUCCESS;
    19501965}
  • trunk/src/VBox/Devices/USB/linux/USBProxyDevice-linux.cpp

    r50234 r52254  
    7676# define RTCRITSECT          void *
    7777static inline int rtcsNoop() { return VINF_SUCCESS; }
     78static inline bool rtcsTrue() { return true; }
    7879# define RTCritSectInit(a)   rtcsNoop()
    7980# define RTCritSectDelete(a) rtcsNoop()
    8081# define RTCritSectEnter(a)  rtcsNoop()
    8182# define RTCritSectLeave(a)  rtcsNoop()
     83# define RTCritSectIsOwner(a) rtcsTrue()
    8284#endif
    8385#include <VBox/err.h>
     
    9193#include <iprt/stream.h>
    9294#include <iprt/string.h>
     95#include <iprt/list.h>
    9396#if defined(NO_PORT_RESET) && !defined(NO_LOGICAL_RECONNECT)
    9497# include <iprt/thread.h>
     
    107110{
    108111    /** The kernel URB data */
    109     struct usbdevfs_urb     KUrb;
     112    struct usbdevfs_urb             KUrb;
    110113    /** Space filler for the isochronous packets. */
    111114    struct usbdevfs_iso_packet_desc aIsocPktsDonUseTheseUseTheOnesInKUrb[8];
    112     /** The millisecond timestamp when this URB was submitted. */
    113     uint64_t                u64SubmitTS;
    114     /** Pointer to the next linux URB. */
    115     struct USBPROXYURBLNX  *pNext;
    116     /** Pointer to the previous linux URB. */
    117     struct USBPROXYURBLNX  *pPrev;
     115    /** Node to link the URB in of the existing lists. */
     116    RTLISTNODE                      NodeList;
    118117    /** If we've split the VUSBURB up into multiple linux URBs, this is points to the head. */
    119     struct USBPROXYURBLNX  *pSplitHead;
     118    struct USBPROXYURBLNX           *pSplitHead;
    120119    /** The next linux URB if split up. */
    121     struct USBPROXYURBLNX  *pSplitNext;
    122     /** Whether it has timed out and should be shot down on the next failing reap call. */
    123     bool                    fTimedOut;
    124     /** Indicates that this URB has been canceled by timeout and should return an CRC error. */
    125     bool                    fCanceledByTimedOut;
     120    struct USBPROXYURBLNX           *pSplitNext;
    126121    /** Don't report these back. */
    127     bool                    fCanceledBySubmit;
     122    bool                             fCanceledBySubmit;
    128123    /** This split element is reaped. */
    129     bool                    fSplitElementReaped;
     124    bool                             fSplitElementReaped;
    130125    /** Size to transfer in remaining fragments of a split URB */
    131     uint32_t                cbSplitRemaining;
     126    uint32_t                         cbSplitRemaining;
    132127} USBPROXYURBLNX, *PUSBPROXYURBLNX;
    133128
     
    139134    /** The open file. */
    140135    RTFILE              hFile;
    141     /** Critical section protecting the two lists. */
     136    /** Critical section protecting the lists. */
    142137    RTCRITSECT          CritSect;
    143     /** The list of free linux URBs. Singly linked. */
    144     PUSBPROXYURBLNX     pFreeHead;
    145     /** The list of active linux URBs. Doubly linked.
     138    /** The list of free linux URBs (USBPROXYURBLNX). */
     139    RTLISTANCHOR        ListFree;
     140    /** The list of active linux URBs.
    146141     * We must maintain this so we can properly reap URBs of a detached device.
    147      * Only the split head will appear in this list. */
    148     PUSBPROXYURBLNX     pInFlightHead;
     142     * Only the split head will appear in this list. (USBPROXYURBLNX) */
     143    RTLISTANCHOR        ListInFlight;
    149144    /** The list of landed linux URBs. Doubly linked.
    150      * Only the split head will appear in this list. */
    151     PUSBPROXYURBLNX     pTaxingHead;
    152     /** The tail of the landed linux URBs. */
    153     PUSBPROXYURBLNX     pTaxingTail;
     145     * Only the split head will appear in this list. (USBPROXYURBLNX) */
     146    RTLISTANCHOR        ListTaxing;
    154147    /** Are we using sysfs to find the active configuration? */
    155148    bool                fUsingSysfs;
     
    233226    pProxyDev->fDetached = true;
    234227
    235     PUSBPROXYURBLNX pUrbTaxing = NULL;
    236     PUSBPROXYURBLNX pUrbLnx = pDevLnx->pInFlightHead;
    237     pDevLnx->pInFlightHead = NULL;
    238     while (pUrbLnx)
    239     {
    240         PUSBPROXYURBLNX pCur = pUrbLnx;
    241         pUrbLnx = pUrbLnx->pNext;
    242 
    243         ioctl(RTFileToNative(pDevLnx->hFile), USBDEVFS_DISCARDURB, &pCur->KUrb); /* not sure if this is required.. */
    244         if (!pCur->KUrb.status)
    245             pCur->KUrb.status = -ENODEV;
     228    PUSBPROXYURBLNX pUrbLnx;
     229    PUSBPROXYURBLNX pUrbLnxNext;
     230
     231    RTListForEachSafe(&pDevLnx->ListInFlight, pUrbLnx, pUrbLnxNext, USBPROXYURBLNX, NodeList)
     232    {
     233        RTListNodeRemove(&pUrbLnx->NodeList);
     234
     235        ioctl(RTFileToNative(pDevLnx->hFile), USBDEVFS_DISCARDURB, &pUrbLnx->KUrb); /* not sure if this is required.. */
     236        if (!pUrbLnx->KUrb.status)
     237            pUrbLnx->KUrb.status = -ENODEV;
    246238
    247239        /* insert into the taxing list. */
    248         pCur->pPrev = NULL;
    249         if (    !pCur->pSplitHead
    250             ||  pCur == pCur->pSplitHead)
    251         {
    252             pCur->pNext = pUrbTaxing;
    253             if (pUrbTaxing)
    254                 pUrbTaxing->pPrev = pCur;
    255             pUrbTaxing = pCur;
    256         }
    257         else
    258             pCur->pNext = NULL;
    259     }
    260 
    261     /* Append the URBs we shot down to the taxing queue. */
    262     if (pUrbTaxing)
    263     {
    264         pUrbTaxing->pPrev = pDevLnx->pTaxingTail;
    265         if (pUrbTaxing->pPrev)
    266             pUrbTaxing->pPrev->pNext = pUrbTaxing;
    267         else
    268             pDevLnx->pTaxingTail = pDevLnx->pTaxingHead = pUrbTaxing;
     240        if (    !pUrbLnx->pSplitHead
     241            ||  pUrbLnx == pUrbLnx->pSplitHead)
     242            RTListAppend(&pDevLnx->ListTaxing, &pUrbLnx->NodeList);
    269243    }
    270244
     
    299273
    300274/**
     275 * Links the given URB into the in flight list.
     276 *
     277 * @returns nothing.
     278 * @param   pDevLnx         The proxy device instance - Linux specific data.
     279 * @param   pUrbLnx         The URB to link into the in flight list.
     280 */
     281static void usbProxyLinuxUrbLinkInFlight(PUSBPROXYDEVLNX pDevLnx, PUSBPROXYURBLNX pUrbLnx)
     282{
     283    Assert(RTCritSectIsOwner(&pDevLnx->CritSect));
     284    Assert(!pUrbLnx->pSplitHead);
     285    RTListAppend(&pDevLnx->ListInFlight, &pUrbLnx->NodeList);
     286}
     287
     288/**
     289 * Unlinks the given URB from the in flight list.
     290 * @returns nothing.
     291 * @param   pDevLnx         The proxy device instance - Linux specific data.
     292 * @param   pUrbLnx         The URB to link into the in flight list.
     293 */
     294static void usbProxyLinuxUrbUnlinkInFlight(PUSBPROXYDEVLNX pDevLnx, PUSBPROXYURBLNX pUrbLnx)
     295{
     296    RTCritSectEnter(&pDevLnx->CritSect);
     297
     298    /*
     299     * Remove from the active list.
     300     */
     301    Assert(!pUrbLnx->pSplitHead || pUrbLnx->pSplitHead == pUrbLnx);
     302
     303    RTListNodeRemove(&pUrbLnx->NodeList);
     304    pUrbLnx->pSplitHead = pUrbLnx->pSplitNext = NULL;
     305
     306    RTCritSectLeave(&pDevLnx->CritSect);
     307}
     308
     309/**
    301310 * Allocates a linux URB request structure.
    302311 * @returns Pointer to an active URB request.
     
    315324     * Try remove a linux URB from the free list, if none there allocate a new one.
    316325     */
    317     pUrbLnx = pDevLnx->pFreeHead;
     326    pUrbLnx = RTListGetFirst(&pDevLnx->ListFree, USBPROXYURBLNX, NodeList);
    318327    if (pUrbLnx)
    319         pDevLnx->pFreeHead = pUrbLnx->pNext;
     328    {
     329        RTListNodeRemove(&pUrbLnx->NodeList);
     330        RTCritSectLeave(&pDevLnx->CritSect);
     331    }
    320332    else
    321333    {
     
    324336        if (!pUrbLnx)
    325337            return NULL;
    326         RTCritSectEnter(&pDevLnx->CritSect);
    327     }
     338    }
     339
    328340    pUrbLnx->pSplitHead = pSplitHead;
    329341    pUrbLnx->pSplitNext = NULL;
    330     pUrbLnx->fTimedOut = false;
    331     pUrbLnx->fCanceledByTimedOut = false;
    332342    pUrbLnx->fCanceledBySubmit = false;
    333343    pUrbLnx->fSplitElementReaped = false;
    334 
    335     /*
    336      * Link it into the active list
    337      */
    338     if (!pSplitHead)
    339     {
    340         pUrbLnx->pPrev = NULL;
    341         pUrbLnx->pNext = pDevLnx->pInFlightHead;
    342         if (pUrbLnx->pNext)
    343             pUrbLnx->pNext->pPrev = pUrbLnx;
    344         pDevLnx->pInFlightHead = pUrbLnx;
    345     }
    346     else
    347         pUrbLnx->pPrev = pUrbLnx->pNext = (PUSBPROXYURBLNX)0xdead;
    348 
    349     RTCritSectLeave(&pDevLnx->CritSect);
    350344    return pUrbLnx;
    351345}
     
    365359
    366360    /*
    367      * Remove from the active list.
    368      */
    369     if (    !pUrbLnx->pSplitHead
    370         ||  pUrbLnx->pSplitHead == pUrbLnx)
    371     {
    372         if (pUrbLnx->pNext)
    373             pUrbLnx->pNext->pPrev = pUrbLnx->pPrev;
    374         if (pUrbLnx->pPrev)
    375             pUrbLnx->pPrev->pNext = pUrbLnx->pNext;
    376         else
    377             pDevLnx->pInFlightHead  = pUrbLnx->pNext;
    378     }
    379     pUrbLnx->pSplitHead = pUrbLnx->pSplitNext = NULL;
    380 
    381     /*
    382361     * Link it into the free list.
    383362     */
    384     pUrbLnx->pPrev = NULL;
    385     pUrbLnx->pNext = pDevLnx->pFreeHead;
    386     pDevLnx->pFreeHead = pUrbLnx;
     363    RTListAppend(&pDevLnx->ListFree, &pUrbLnx->NodeList);
    387364
    388365    RTCritSectLeave(&pDevLnx->CritSect);
     
    409386        pUrbLnx = pUrbLnx->pSplitNext;
    410387        Assert(pFree->pSplitHead);
     388        pFree->pSplitHead = pFree->pSplitNext = NULL;
    411389        usbProxyLinuxUrbFree(pProxyDev, pFree);
    412390    }
     
    665643         */
    666644        PUSBPROXYDEVLNX pDevLnx = USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVLNX);
     645
     646        RTListInit(&pDevLnx->ListFree);
     647        RTListInit(&pDevLnx->ListInFlight);
     648        RTListInit(&pDevLnx->ListTaxing);
    667649        pDevLnx->pszPath = RTStrDupN(pszPath, cchPath);
    668650        if (pDevLnx->pszPath)
     
    782764
    783765    PUSBPROXYURBLNX pUrbLnx;
    784     while ((pUrbLnx = pDevLnx->pInFlightHead) != NULL)
    785     {
    786         pDevLnx->pInFlightHead = pUrbLnx->pNext;
     766    PUSBPROXYURBLNX pUrbLnxNext;
     767    RTListForEachSafe(&pDevLnx->ListInFlight, pUrbLnx, pUrbLnxNext, USBPROXYURBLNX, NodeList)
     768    {
     769        RTListNodeRemove(&pUrbLnx->NodeList);
     770
    787771        if (    usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pUrbLnx->KUrb, false, UINT32_MAX)
    788772            &&  errno != ENODEV
    789773            &&  errno != ENOENT)
    790774            AssertMsgFailed(("errno=%d\n", errno));
     775
    791776        if (pUrbLnx->pSplitHead)
    792777        {
     
    809794    }
    810795
    811     while ((pUrbLnx = pDevLnx->pFreeHead) != NULL)
    812     {
    813         pDevLnx->pFreeHead = pUrbLnx->pNext;
     796    RTListForEachSafe(&pDevLnx->ListFree, pUrbLnx, pUrbLnxNext, USBPROXYURBLNX, NodeList)
     797    {
     798        RTListNodeRemove(&pUrbLnx->NodeList);
    814799        RTMemFree(pUrbLnx);
    815800    }
     
    12991284             pUrb, errno, pCur->KUrb.type, pCur->KUrb.endpoint, pCur->KUrb.buffer_length, cTries));
    13001285        if (errno != EBUSY && ++cTries < 3) /* this doesn't work for the floppy :/ */
    1301         {
    1302             pCur->u64SubmitTS = RTTimeMilliTS();
    13031286            continue;
    1304         }
     1287
    13051288        return RTErrConvertFromErrno(errno);
    13061289    }
     
    13301313        return NULL;
    13311314    }
    1332     Assert(pHead->pNext != pNew); Assert(pHead->pPrev != pNew); Assert(pNew->pNext == pNew->pPrev);
    13331315    Assert(pNew->pSplitHead == pHead);
    13341316    Assert(pNew->pSplitNext == NULL);
     
    14331415            if (RT_FAILURE(rc))
    14341416                break;
     1417            usbProxyLinuxUrbLinkInFlight(USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVLNX), pCur);
    14351418        }
    14361419    }
     
    14391422    {
    14401423        pUrb->Dev.pvPrivate = pUrbLnx;
     1424        usbProxyLinuxUrbLinkInFlight(USBPROXYDEV_2_DATA(pProxyDev, PUSBPROXYDEVLNX), pUrbLnx);
    14411425        LogFlow(("usbProxyLinuxUrbQueueSplit: ok\n"));
    14421426        return VINF_SUCCESS;
     
    15131497
    15141498    /*
     1499     * We have to serialize access by using the critial section here because this
     1500     * thread might be suspended after submitting the URB but before linking it into
     1501     * the in flight list. This would get us in trouble when reaping the URB on another
     1502     * thread while it isn't in the in flight list.
     1503     *
     1504     * Linking the URB into the list before submitting it like it was done in the past is not
     1505     * possible either because submitting the URB might fail here because the device gets
     1506     * detached. The reaper thread gets this event too and might race this thread before we
     1507     * can unlink the URB from the active list and the common code might end up freeing
     1508     * the common URB structure twice.
     1509     */
     1510    RTCritSectEnter(&pDevLnx->CritSect);
     1511    /*
    15151512     * Submit it.
    15161513     */
     
    15251522            if (pUrb->enmType == VUSBXFERTYPE_MSG)
    15261523                usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
     1524
     1525            RTCritSectLeave(&pDevLnx->CritSect);
    15271526            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
    1528 
    15291527            usbProxLinuxUrbUnplugged(pProxyDev);
    15301528            return RTErrConvertFromErrno(errno);
     
    15411539        if (    errno == EINVAL
    15421540            &&  pUrb->cbData >= 8*_1K)
     1541        {
     1542            RTCritSectLeave(&pDevLnx->CritSect);
    15431543            return usbProxyLinuxUrbQueueSplit(pProxyDev, pUrbLnx, pUrb);
     1544        }
    15441545
    15451546        Log(("usb-linux: Queue URB %p -> %d!!! type=%d ep=%#x buffer_length=%#x cTries=%d\n",
     
    15481549            continue;
    15491550
     1551        RTCritSectLeave(&pDevLnx->CritSect);
    15501552        rc = RTErrConvertFromErrno(errno);
    1551 
    1552 l_err:
    15531553        if (pUrb->enmType == VUSBXFERTYPE_MSG)
    15541554            usbProxyLinuxUrbSwapSetup((PVUSBSETUP)pUrb->abData);
     
    15561556        return rc;
    15571557    }
    1558     pUrbLnx->u64SubmitTS = RTTimeMilliTS();
     1558
     1559    usbProxyLinuxUrbLinkInFlight(pDevLnx, pUrbLnx);
     1560    RTCritSectLeave(&pDevLnx->CritSect);
    15591561
    15601562    LogFlow(("usbProxyLinuxUrbQueue: ok\n"));
    15611563    pUrb->Dev.pvPrivate = pUrbLnx;
    15621564    return rc;
    1563 }
    1564 
    1565 
    1566 /**
    1567  * Check if any or the in-flight URBs are taking too long and should be cancelled.
    1568  *
    1569  * Cancelling is done in three turns, first a URB is marked for timeout if it's
    1570  * exceeding a certain time limit. Then the next time it's encountered it is actually
    1571  * cancelled. The idea now is that it's supposed to be reaped and returned in the next
    1572  * round of calls.
    1573  *
    1574  * @param   pProxyDev   The proxy device.
    1575  * @param   pDevLnx     The linux backend data.
    1576  *
    1577  * @todo    Make the HCI do proper timeout handling! Current timeout is 3 min and 20 seconds
    1578  *          as not to break bloomberg which queues IN packages with 3 min timeouts.
    1579  */
    1580 static void vusbProxyLinuxUrbDoTimeouts(PUSBPROXYDEV pProxyDev, PUSBPROXYDEVLNX pDevLnx)
    1581 {
    1582     RTCritSectEnter(&pDevLnx->CritSect);
    1583     uint64_t u64MilliTS = RTTimeMilliTS();
    1584     PUSBPROXYURBLNX pCur;
    1585     for (pCur = pDevLnx->pInFlightHead;
    1586          pCur;
    1587          pCur = pCur->pNext)
    1588     {
    1589         if (pCur->fTimedOut)
    1590         {
    1591             if (pCur->pSplitHead)
    1592             {
    1593                 /* split */
    1594                 Assert(pCur == pCur->pSplitHead);
    1595                 unsigned cFailures = 0;
    1596                 PUSBPROXYURBLNX pCur2;
    1597                 for (pCur2 = pCur; pCur2; pCur2 = pCur2->pSplitNext)
    1598                 {
    1599                     if (pCur2->fSplitElementReaped)
    1600                         continue;
    1601 
    1602                     if (    !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pCur2->KUrb, true, UINT32_MAX)
    1603                         ||  errno == ENOENT)
    1604                         pCur2->fCanceledByTimedOut = true;
    1605                     else if (errno != ENODEV)
    1606                         Log(("vusbProxyLinuxUrbDoTimeouts: pUrb=%p failed errno=%d (!!split!!)\n", pCur2->KUrb.usercontext, errno));
    1607                     else
    1608                         goto l_leave; /* ENODEV means break and everything cancelled elsewhere. */
    1609                 }
    1610                 LogRel(("USB: Cancelled URB (%p) after %llums!! (cFailures=%d)\n",
    1611                         pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS, cFailures));
    1612             }
    1613             else
    1614             {
    1615                 /* unsplit */
    1616                 if (    !usbProxyLinuxDoIoCtl(pProxyDev, USBDEVFS_DISCARDURB, &pCur->KUrb, true, UINT32_MAX)
    1617                     ||  errno == -ENOENT)
    1618                 {
    1619                     pCur->fCanceledByTimedOut = true;
    1620                     LogRel(("USB: Cancelled URB (%p) after %llums!!\n", pCur->KUrb.usercontext, (long long unsigned) u64MilliTS - pCur->u64SubmitTS));
    1621                 }
    1622                 else if (errno != ENODEV)
    1623                     LogFlow(("vusbProxyLinuxUrbDoTimeouts: pUrb=%p failed errno=%d\n", pCur->KUrb.usercontext, errno));
    1624                 else
    1625                     goto l_leave; /* ENODEV means break and everything cancelled elsewhere. */
    1626             }
    1627         }
    1628 #if 0
    1629         /* Disabled for the time being as some USB devices have URBs pending for an unknown amount of time.
    1630          * One example is the OmniKey CardMan 3821. */
    1631         else if (u64MilliTS - pCur->u64SubmitTS >= 200*1000 /* 200 sec (180 sec has been observed with XP) */)
    1632             pCur->fTimedOut = true;
    1633 #endif
    1634     }
    1635 
    1636 l_leave:
    1637     RTCritSectLeave(&pDevLnx->CritSect);
    16381565}
    16391566
     
    16951622static VUSBSTATUS vusbProxyLinuxUrbGetStatus(PUSBPROXYURBLNX pUrbLnx)
    16961623{
    1697     if (    pUrbLnx->fCanceledByTimedOut
    1698         &&  pUrbLnx->KUrb.status == 0)
    1699         return VUSBSTATUS_CRC;
    17001624    return vusbProxyLinuxStatusToVUsbStatus(pUrbLnx->KUrb.status);
    17011625}
     
    17181642     * Any URBs pending delivery?
    17191643     */
    1720     if (pDevLnx->pTaxingHead)
     1644    if (!RTListIsEmpty(&pDevLnx->ListTaxing))
    17211645    {
    17221646        RTCritSectEnter(&pDevLnx->CritSect);
    1723         pUrbLnx = pDevLnx->pTaxingHead;
     1647        pUrbLnx = RTListGetFirst(&pDevLnx->ListTaxing, USBPROXYURBLNX, NodeList);
    17241648        if (pUrbLnx)
    17251649        {
    17261650            /* unlink from the pending delivery list */
    1727             if (pUrbLnx->pNext)
    1728             {
    1729                 pUrbLnx->pNext->pPrev = NULL;
    1730                 pDevLnx->pTaxingHead = pUrbLnx->pNext;
    1731             }
    1732             else
    1733                 pDevLnx->pTaxingHead = pDevLnx->pTaxingTail = NULL;
     1651            RTListNodeRemove(&pDevLnx->ListTaxing);
    17341652
    17351653            /* temporarily into the active list, so free works right. */
    1736             pUrbLnx->pPrev = NULL;
    1737             pUrbLnx->pNext = pDevLnx->pInFlightHead;
    1738             if (pUrbLnx->pNext)
    1739                 pUrbLnx->pNext->pPrev = pUrbLnx;
    1740             pDevLnx->pInFlightHead = pUrbLnx;
     1654            RTListAppend(&pDevLnx->ListInFlight, &pUrbLnx->NodeList);
    17411655        }
    17421656        RTCritSectLeave(&pDevLnx->CritSect);
     
    17441658    if (!pUrbLnx)
    17451659    {
    1746         /*
    1747          * Don't block if nothing is in the air.
    1748          */
    1749         if (!pDevLnx->pInFlightHead)
    1750         {
    1751             int cMilliesWait = cMillies == RT_INDEFINITE_WAIT ? -1 : cMillies;
    1752 
    1753             LogFlow(("Nothing in flight, going to sleep\n"));
    1754 
    1755             struct pollfd pfd;
    1756 
    1757             pfd.fd = RTPipeToNative(pDevLnx->hPipeWakeupR);
    1758             pfd.events = POLLIN | POLLHUP;
    1759             pfd.revents = 0;
    1760 
    1761             int rc = poll(&pfd, 1, cMilliesWait);
    1762             Log(("usbProxyLinuxUrbReap: poll rc = %d\n", rc));
    1763             if (rc >= 1)
    1764             {
    1765                 /* Drain pipe. */
    1766                uint8_t bRead;
    1767                size_t cbIgnored = 0;
    1768                RTPipeRead(pDevLnx->hPipeWakeupR, &bRead, 1, &cbIgnored);
    1769             }
    1770             return NULL;
    1771         }
    1772 
    17731660        /*
    17741661         * Block for requested period.
     
    18071694                    break;
    18081695                }
    1809                 if (rc >= 0 /*|| errno == ETIMEOUT*/)
    1810                 {
    1811                     vusbProxyLinuxUrbDoTimeouts(pProxyDev, pDevLnx);
     1696                if (rc >= 0)
    18121697                    return NULL;
    1813                 }
     1698
    18141699                if (errno != EAGAIN)
    18151700                {
     
    18321717                    if (errno == ENODEV)
    18331718                        usbProxLinuxUrbUnplugged(pProxyDev);
    1834                     else if (errno == EAGAIN)
    1835                         vusbProxyLinuxUrbDoTimeouts(pProxyDev, pDevLnx);
    18361719                    else
    18371720                        Log(("usb-linux: Reap URB. errno=%d pProxyDev=%s\n", errno, usbProxyGetName(pProxyDev)));
     
    19221805                }
    19231806            }
     1807            usbProxyLinuxUrbUnlinkInFlight(pDevLnx, pUrbLnx);
    19241808            usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
    19251809        }
     
    19351819    else
    19361820    {
     1821        usbProxyLinuxUrbUnlinkInFlight(pDevLnx, pUrbLnx);
    19371822        usbProxyLinuxUrbFree(pProxyDev, pUrbLnx);
    19381823        pUrb = NULL;
  • trunk/src/VBox/Devices/USB/win/USBProxyDevice-win.cpp

    r51738 r52254  
    22/** @file
    33 * USBPROXY - USB proxy, Win32 backend
    4  *
    5  * NOTE: This code assumes only one thread will use it at a time!!
    6  * bird: usbProxyWinReset() will be called in a separate thread because it
    7  *       will usually take >=10ms. So, the assumption is broken.
    84 */
    95
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