VirtualBox

Changeset 24096 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Oct 26, 2009 10:35:29 PM (15 years ago)
Author:
vboxsync
Message:

DevAHCI: Try avoid the 100ms timeouts during suspend and shutdown. Ported over some of the ATA changes stuff.

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

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Storage/ATAController.cpp

    r23417 r24096  
    248248    rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex);
    249249    AssertRC(rc);
    250     LogBird(("ata: %x: signalling\n", pCtl->IOPortBase1));
    251250    rc = PDMR3CritSectScheduleExitEvent(&pCtl->lock, pCtl->AsyncIOSem);
    252251    if (RT_FAILURE(rc))
    253252    {
    254         LogBird(("ata: %x: schedule failed, rc=%Rrc\n", pCtl->IOPortBase1, rc));
    255253        rc = RTSemEventSignal(pCtl->AsyncIOSem);
    256254        AssertRC(rc);
     
    30833081{
    30843082    uint64_t        u64Start;
     3083    bool            fRc;
     3084
     3085    /* Hope for the simple way out...  */
     3086    if (ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
     3087        return true;
    30853088
    30863089    /*
    3087      * Wait for any pending async operation to finish
     3090     * Have to wait. Do the setup while owning the mutex to avoid races.
    30883091     */
     3092    RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT);
     3093
     3094    RTThreadUserReset(pCtl->AsyncIOThread);
     3095    ASMAtomicWriteBool(&pCtl->fSignalIdle, true);
     3096
     3097    RTSemMutexRelease(pCtl->AsyncIORequestMutex);
     3098
    30893099    u64Start = RTTimeMilliTS();
    30903100    for (;;)
    30913101    {
    3092         if (ataAsyncIOIsIdle(pCtl, false))
    3093             return true;
     3102        fRc = ataAsyncIOIsIdle(pCtl, false /*fStrict*/);
     3103        if (fRc)
     3104            break;
     3105
    30943106        if (RTTimeMilliTS() - u64Start >= cMillies)
    30953107            break;
    30963108
    3097         /* Sleep for a bit. */
    3098         RTThreadSleep(100);
    3099     }
    3100 
    3101     return false;
     3109        int rc = RTThreadUserWait(pCtl->AsyncIOThread, 100 /*ms*/);
     3110        AssertMsg(   (   RT_SUCCESS(rc)
     3111                      && ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
     3112                  || rc == VERR_TIMEOUT,
     3113                  ("rc=%Rrc irq=%u\n", rc, pCtl->irq));
     3114    }
     3115
     3116    ASMAtomicWriteBool(&pCtl->fSignalIdle, false);
     3117    return fRc;
    31023118}
    31033119
     
    38303846}
    38313847
     3848
     3849/**
     3850 * Signal ataWaitForAsyncIOIsIdle that we're idle (if we actually are).
     3851 *
     3852 * @param   pCtl        The controller.
     3853 */
     3854static void ataAsyncSignalIdle(PAHCIATACONTROLLER pCtl)
     3855{
     3856    /*
     3857     * Take the mutex here and recheck the idle indicator as there might be
     3858     * interesting races, like in the ataReset code.
     3859     */
     3860    int rc = RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT); AssertRC(rc);
     3861
     3862    if (    pCtl->fSignalIdle
     3863        &&  ataAsyncIOIsIdle(pCtl, false /*fStrict*/))
     3864        RTThreadUserSignal(pCtl->AsyncIOThread);
     3865
     3866    rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex); AssertRC(rc);
     3867}
     3868
     3869
    38323870/** Asynch I/O thread for an interface. Once upon a time this was readable
    38333871 * code with several loops and a different semaphore for each purpose. But
     
    38503888        while (pCtl->fRedoIdle)
    38513889        {
     3890            if (pCtl->fSignalIdle)
     3891                ataAsyncSignalIdle(pCtl);
    38523892            rc = RTSemEventWait(pCtl->SuspendIOSem, RT_INDEFINITE_WAIT);
    38533893            if (RT_FAILURE(rc) || pCtl->fShutdown)
     
    38603900        if (pReq == NULL)
    38613901        {
    3862             LogBird(("ata: %x: going to sleep...\n", pCtl->IOPortBase1));
     3902            if (pCtl->fSignalIdle)
     3903                ataAsyncSignalIdle(pCtl);
    38633904            rc = RTSemEventWait(pCtl->AsyncIOSem, RT_INDEFINITE_WAIT);
    3864             LogBird(("ata: %x: waking up\n", pCtl->IOPortBase1));
    38653905            if (RT_FAILURE(rc) || pCtl->fShutdown)
    38663906                break;
     
    38923932        {
    38933933        STAM_PROFILE_START(&pCtl->StatLockWait, a);
    3894         LogBird(("ata: %x: entering critsect\n", pCtl->IOPortBase1));
    38953934        PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS);
    3896         LogBird(("ata: %x: entered\n", pCtl->IOPortBase1));
    38973935        STAM_PROFILE_STOP(&pCtl->StatLockWait, a);
    38983936        }
     
    42914329        }
    42924330
    4293         LogBird(("ata: %x: leaving critsect\n", pCtl->IOPortBase1));
    42944331        PDMCritSectLeave(&pCtl->lock);
    42954332    }
    42964333
    4297     /* Cleanup the state.  */
    4298     if (pCtl->AsyncIOSem)
    4299     {
    4300         RTSemEventDestroy(pCtl->AsyncIOSem);
    4301         pCtl->AsyncIOSem = NIL_RTSEMEVENT;
    4302     }
    4303     if (pCtl->SuspendIOSem)
    4304     {
    4305         RTSemEventDestroy(pCtl->SuspendIOSem);
    4306         pCtl->SuspendIOSem = NIL_RTSEMEVENT;
    4307     }
     4334    /* Signal the ultimate idleness. */
     4335    RTThreadUserSignal(ThreadSelf);
     4336
    43084337    /* Do not destroy request mutex yet, still needed for proper shutdown. */
    43094338    pCtl->fShutdown = false;
    4310     /* This must be last, as it also signals thread exit to EMT. */
    4311     pCtl->AsyncIOThread = NIL_RTTHREAD;
    43124339
    43134340    Log2(("%s: Ctl: return %Rrc\n", __FUNCTION__, rc));
     
    46064633    else
    46074634        AssertMsgFailed(("ataIOPortWrite1: unsupported write to port %x val=%x size=%d\n", Port, u32, cb));
    4608     LogBird(("ata: leaving critsect\n"));
    46094635    PDMCritSectLeave(&pCtl->lock);
    4610     LogBird(("ata: left critsect\n"));
    46114636    return rc;
    46124637}
     
    48614886
    48624887    /*
    4863      * Terminate all async helper threads
     4888     * Terminate the async helper thread and wait for it to finish up.
    48644889     */
    48654890    if (pCtl->AsyncIOThread != NIL_RTTHREAD)
    48664891    {
    4867         ASMAtomicXchgU32(&pCtl->fShutdown, true);
     4892        ASMAtomicWriteU32(&pCtl->fShutdown, true);
    48684893        rc = RTSemEventSignal(pCtl->AsyncIOSem);
    48694894        AssertRC(rc);
    4870     }
    4871 
    4872     if (pCtl->CTX_SUFF(pDevIns))
    4873     {
    4874         /*
    4875          * Wait for them to complete whatever they are doing and then
    4876          * for them to terminate.
    4877          */
    4878         if (ataWaitForAllAsyncIOIsIdle(pCtl, 20000))
    4879         {
    4880             uint64_t    u64Start = RTTimeMilliTS();
    4881             bool        fAllDone;
    4882             for (;;)
    4883             {
    4884                 /* check */
    4885                 fAllDone = true;
    4886                 fAllDone &= (pCtl->AsyncIOThread == NIL_RTTHREAD);
    4887 
    4888                 if (    fAllDone
    4889                     ||  RTTimeMilliTS() - u64Start >= 500)
    4890                     break;
    4891 
    4892                 /* Sleep for a bit. */
    4893                 RTThreadSleep(100);
    4894             }
    4895             AssertMsg(fAllDone, ("Some of the async I/O threads are still running!\n"));
    4896         }
     4895
     4896        rc = RTThreadWait(pCtl->AsyncIOThread, 30000 /* 30 s*/, NULL);
     4897        if (RT_SUCCESS(rc))
     4898            pCtl->AsyncIOThread = NIL_RTTHREAD;
    48974899        else
    4898             AssertMsgFailed(("Async I/O is still busy!\n"));
     4900            LogRel(("PIIX3 ATA Dtor: Ctl/irq=%u is still executing, DevSel=%d AIOIf=%d CmdIf0=%#04x CmdIf1=%#04x rc=%Rrc\n",
     4901                    pCtl->irq, pCtl->iSelectedIf, pCtl->iAIOIf,
     4902                    pCtl->aIfs[0].uATARegCommand, pCtl->aIfs[1].uATARegCommand, rc));
    48994903    }
    49004904
     
    49024906     * Now the request mutexes are no longer needed. Free resources.
    49034907     */
    4904     if (pCtl->AsyncIORequestMutex)
     4908    if (pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX)
    49054909    {
    49064910        RTSemMutexDestroy(pCtl->AsyncIORequestMutex);
    4907         pCtl->AsyncIORequestMutex = NIL_RTSEMEVENT;
     4911        pCtl->AsyncIORequestMutex = NIL_RTSEMMUTEX;
     4912    }
     4913    if (pCtl->AsyncIOSem != NIL_RTSEMEVENT)
     4914    {
     4915        RTSemEventDestroy(pCtl->AsyncIOSem);
     4916        pCtl->AsyncIOSem = NIL_RTSEMEVENT;
     4917    }
     4918    if (pCtl->SuspendIOSem != NIL_RTSEMEVENT)
     4919    {
     4920        RTSemEventDestroy(pCtl->SuspendIOSem);
     4921        pCtl->SuspendIOSem = NIL_RTSEMEVENT;
     4922    }
     4923
     4924    /* try one final time */
     4925    if (pCtl->AsyncIOThread != NIL_RTTHREAD)
     4926    {
     4927        rc = RTThreadWait(pCtl->AsyncIOThread, 1 /*ms*/, NULL);
     4928        if (RT_SUCCESS(rc))
     4929        {
     4930            pCtl->AsyncIOThread = NIL_RTTHREAD;
     4931            LogRel(("AHCI ATA Dtor: Ctl/irq=%u actually completed.\n", pCtl->irq));
     4932        }
    49084933    }
    49094934
     
    54755500    pCtl->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    54765501    pCtl->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     5502    pCtl->AsyncIOSem = NIL_RTSEMEVENT;
     5503    pCtl->SuspendIOSem = NIL_RTSEMEVENT;
     5504    pCtl->AsyncIORequestMutex = NIL_RTSEMMUTEX;
     5505    pCtl->AsyncIOThread = NIL_RTTHREAD;
    54775506
    54785507    for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++)
     
    55055534    pCtl->uAsyncIOState = AHCIATA_AIO_NEW;
    55065535    rc = RTSemEventCreate(&pCtl->AsyncIOSem);
    5507     AssertRC(rc);
     5536    AssertRCReturn(rc, rc);
    55085537    rc = RTSemEventCreate(&pCtl->SuspendIOSem);
    5509     AssertRC(rc);
     5538    AssertRCReturn(rc, rc);
    55105539    rc = RTSemMutexCreate(&pCtl->AsyncIORequestMutex);
    5511     AssertRC(rc);
     5540    AssertRCReturn(rc, rc);
    55125541    ataAsyncIOClearRequests(pCtl);
    5513     rc = RTThreadCreate(&pCtl->AsyncIOThread, ataAsyncIOLoop, (void *)pCtl, 128*1024, RTTHREADTYPE_IO, 0, "ATA");
    5514     AssertRC(rc);
     5542    rc = RTThreadCreateF(&pCtl->AsyncIOThread, ataAsyncIOLoop, (void *)pCtl, 128*1024,
     5543                         RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "AHCI-ATA-%u", pCtl->irq);
     5544    AssertRCReturn(rc, rc);
    55155545    Assert(pCtl->AsyncIOThread != NIL_RTTHREAD && pCtl->AsyncIOSem != NIL_RTSEMEVENT && pCtl->SuspendIOSem != NIL_RTSEMEVENT && pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX);
    55165546    Log(("%s: controller AIO thread id %#x; sem %p susp_sem %p mutex %p\n", __FUNCTION__, pCtl->AsyncIOThread, pCtl->AsyncIOSem, pCtl->SuspendIOSem, pCtl->AsyncIORequestMutex));
  • trunk/src/VBox/Devices/Storage/ATAController.h

    r20374 r24096  
    366366    /** The position at which to get a new request for the AIO thread. */
    367367    uint8_t             AsyncIOReqTail;
    368     uint8_t             Alignment3[2]; /**< Explicit padding of the 2 byte gap. */
     368    /** Whether to call RTThreadUserSignal when idle.
     369     * Before setting this, call RTThreadUserReset. */
     370    bool volatile       fSignalIdle;
     371    uint8_t             Alignment3[1]; /**< Explicit padding of the 1 byte gap. */
    369372    /** Magic delay before triggering interrupts in DMA mode. */
    370373    uint32_t            DelayIRQMillies;
  • trunk/src/VBox/Devices/Storage/DevAHCI.cpp

    r24072 r24096  
    574574    PDMCRITSECT                     lock;
    575575
     576    /** Semaphore that gets set when fSignalIdle is set. */
     577    RTSEMEVENT                      hEvtIdle;
     578#if HC_ARCH_BITS == 32
     579    uint32_t                        Alignment7;
     580#endif
     581
    576582    /** Bitmask of ports which asserted an interrupt. */
    577583    uint32_t                        u32PortsInterrupted;
     
    586592    /** If the new async interface is used if available. */
    587593    bool                            fUseAsyncInterfaceIfAvailable;
     594    /** Indicates that hEvtIdle should be signalled when a port is entering the
     595     * idle state. */
     596    bool volatile                   fSignalIdle;
     597    bool                            afAlignment8[1];
    588598
    589599    /** Number of usable ports on this controller. */
     
    591601
    592602#if HC_ARCH_BITS == 64
    593     uint32_t                        Alignment7;
     603    uint32_t                        Alignment9;
    594604#endif
    595605
     
    49174927             __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag));
    49184928
    4919     return ahciTransferComplete(pAhciPort, pAhciPortTaskState);
     4929    int rc = ahciTransferComplete(pAhciPort, pAhciPortTaskState);
     4930
     4931    if (pAhciPort->uActTasksActive == 0 && pAhciPort->pAhciR3->fSignalIdle)
     4932        RTSemEventSignal(pAhciPort->pAhciR3->hEvtIdle);
     4933    return rc;
    49204934}
    49214935
     
    53745388
    53755389        ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, true);
     5390        if (pAhci->fSignalIdle)
     5391            RTSemEventSignal(pAhci->hEvtIdle);
    53765392
    53775393        rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, 1000);
     
    56375653    }
    56385654
     5655    if (pAhci->fSignalIdle)
     5656        RTSemEventSignal(pAhci->hEvtIdle);
     5657
    56395658    /* Free task state memory */
    56405659    if (pAhciPortTaskState->pSGListHead)
     
    57685787            ataControllerDestroy(&pAhci->aCts[i]);
    57695788
     5789        RTSemEventDestroy(pAhci->hEvtIdle);
     5790        pAhci->hEvtIdle = NIL_RTSEMEVENT;
     5791
    57705792        PDMR3CritSectDelete(&pAhci->lock);
    57715793    }
     
    58825904    bool      fAllFinished;
    58835905
     5906    ASMAtomicWriteBool(&pAhci->fSignalIdle, true);
    58845907    u64Start = RTTimeMilliTS();
    58855908    for (;;)
     
    59055928            break;
    59065929
    5907         /* Sleep a bit. */
    5908         RTThreadSleep(100); /** @todo wait on something which can be woken up. 100ms is too long for teleporting VMs! */
    5909     }
     5930        /* Wait for a port to signal idleness. */
     5931        int rc = RTSemEventWait(pAhci->hEvtIdle, 100 /*ms*/);
     5932        AssertMsg(RT_SUCCESS(rc) || rc == VERR_TIMEOUT, ("%Rrc\n", rc)); NOREF(rc);
     5933    }
     5934
     5935    ASMAtomicWriteBool(&pAhci->fSignalIdle, false);
    59105936    return fAllFinished;
    59115937}
     
    65026528    pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns);
    65036529    pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns);
     6530    pThis->hEvtIdle  = NIL_RTSEMEVENT;
    65046531
    65056532    PCIDevSetVendorId    (&pThis->dev, 0x8086); /* Intel */
     
    65826609        return rc;
    65836610    }
     6611
     6612    rc = RTSemEventCreate(&pThis->hEvtIdle);
     6613    AssertRCReturn(rc, rc);
    65846614
    65856615    /* Create the timer for command completion coalescing feature. */
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