VirtualBox

Changeset 24751 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 18, 2009 1:13:11 AM (15 years ago)
Author:
vboxsync
Message:

DrvSCSI: Converted to async reset, suspend and power off notification handling.

File:
1 edited

Legend:

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

    r24678 r24751  
    9191    /** Request that we've left pending on wakeup or reset. */
    9292    PRTREQ                  pPendingDummyReq;
     93    /** Indicates whether PDMDrvHlpAsyncNotificationCompleted should be called by
     94     * any of the dummy functions. */
     95    bool volatile           fDummySignal;
    9396    /** Release statistics: number of bytes written. */
    9497    STAMCOUNTER             StatBytesWritten;
     
    676679 * to complete prior to the device reset.
    677680 *
     681 * @param   pThis           Pointer to the instace data.
    678682 * @returns VINF_SUCCESS.
    679683 */
    680 static int drvscsiAsyncIOLoopSyncCallback(void)
    681 {
     684static int drvscsiAsyncIOLoopSyncCallback(PDRVSCSI pThis)
     685{
     686    if (pThis->fDummySignal)
     687        PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
    682688    return VINF_SUCCESS;
    683689}
     
    686692 * Request function to wakeup the thread.
    687693 *
     694 * @param   pThis           Pointer to the instace data.
    688695 * @returns VWRN_STATE_CHANGED.
    689696 */
    690 static int drvscsiAsyncIOLoopWakeupFunc(void)
    691 {
     697static int drvscsiAsyncIOLoopWakeupFunc(PDRVSCSI pThis)
     698{
     699    if (pThis->fDummySignal)
     700        PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns);
    692701    return VWRN_STATE_CHANGED;
    693702}
     
    697706 *
    698707 * @returns VBox status code.
    699  * @param   pDrvIns    Pointer to the device instance data.
     708 * @param   pDrvIns    Pointer to the driver instance data.
    700709 * @param   pThread    Pointer to the thread instance data.
    701710 */
     
    753762    }
    754763
    755     rc = RTReqCall(pThis->pQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 0);
     764    rc = RTReqCall(pThis->pQueueRequests, &pReq, 10000 /* 10 sec. */, (PFNRT)drvscsiAsyncIOLoopWakeupFunc, 1, pThis);
    756765    if (RT_SUCCESS(rc))
    757766        RTReqFree(pReq);
     
    805814 * Worker for drvscsiReset, drvscsiSuspend and drvscsiPowerOff.
    806815 *
    807  * @param   pThis               The instance data.
    808  * @param   pszEvent            The notification event (for logging).
    809  */
    810 static void drvscsiWaitForPendingRequests(PDRVSCSI pThis, const char *pszEvent)
    811 {
    812     /*
    813      * Try make sure any pending I/O has completed now.
    814      */
    815     if (pThis->pQueueRequests)
    816     {
    817         if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 20000 /*ms*/))
     816 * @param   pDrvIns         The driver instance.
     817 * @param   pfnAsyncNotify  The async callback.
     818 */
     819static void drvscsiR3ResetOrSuspendOrPowerOff(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
     820{
     821    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
     822
     823    if (!pThis->pQueueRequests)
     824        return;
     825
     826    ASMAtomicWriteBool(&pThis->fDummySignal, true);
     827    if (drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))
     828    {
     829        if (!RTReqIsBusy(pThis->pQueueRequests))
    818830        {
    819             LogRel(("drvscsi%s#%u: previous dummy request is still pending\n", pszEvent, pThis->pDrvIns->iInstance));
     831            ASMAtomicWriteBool(&pThis->fDummySignal, false);
    820832            return;
    821833        }
    822834
    823         if (RTReqIsBusy(pThis->pQueueRequests))
     835        PRTREQ pReq;
     836        int rc = RTReqCall(pThis->pQueueRequests, &pReq, 0 /*ms*/, (PFNRT)drvscsiAsyncIOLoopSyncCallback, 1, pThis);
     837        if (RT_SUCCESS(rc))
    824838        {
    825             PRTREQ pReq;
    826             int rc = RTReqCall(pThis->pQueueRequests, &pReq, 20000 /*ms*/, (PFNRT)drvscsiAsyncIOLoopSyncCallback, 0);
    827             if (RT_SUCCESS(rc))
    828                 RTReqFree(pReq);
    829             else
    830             {
    831                 pThis->pPendingDummyReq = pReq;
    832                 LogRel(("drvscsi%s#%u: %Rrc pReq=%p\n", pszEvent, pThis->pDrvIns->iInstance, rc, pReq));
    833             }
     839            ASMAtomicWriteBool(&pThis->fDummySignal, false);
     840            RTReqFree(pReq);
     841            return;
    834842        }
    835     }
    836 /** @todo r=bird: this is a deadlock trap. We're EMT(0), if there are
    837  *        outstanding requests they may require EMT interaction because of
    838  *        physical write backs around lsilogicDeviceSCSIRequestCompleted...
    839  *
    840  *        I have some more generic solution for delayed suspend, reset and
    841  *        poweroff handling that I'm considering.  The idea is that the
    842  *        notification callback returns a status indicating that it didn't
    843  *        complete and needs to be called again or something.  EMT continues on
    844  *        the next device and when it's done, it processes incoming requests and
    845  *        does another notification round... This way we could combine the waits
    846  *        in the I/O controllers and reduce the time it takes to suspend a VM a
    847  *        wee bit...
    848  */
     843
     844        pThis->pPendingDummyReq = pReq;
     845    }
     846    PDMDrvHlpSetAsyncNotification(pDrvIns, pfnAsyncNotify);
     847}
     848
     849/**
     850 * Callback employed by drvscsiSuspend and drvscsiPowerOff.
     851 *
     852 * @returns true if we've quiesced, false if we're still working.
     853 * @param   pDrvIns     The driver instance.
     854 */
     855static DECLCALLBACK(bool) drvscsiIsAsyncSuspendOrPowerOffDone(PPDMDRVINS pDrvIns)
     856{
     857    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
     858
     859    if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))
     860        return false;
     861    ASMAtomicWriteBool(&pThis->fDummySignal, false);
     862    PDMR3ThreadSuspend(pThis->pAsyncIOThread);
     863    return true;
    849864}
    850865
     
    854869static DECLCALLBACK(void) drvscsiPowerOff(PPDMDRVINS pDrvIns)
    855870{
     871    drvscsiR3ResetOrSuspendOrPowerOff(pDrvIns, drvscsiIsAsyncSuspendOrPowerOffDone);
     872}
     873
     874/**
     875 * @copydoc FNPDMDRVSUSPEND
     876 */
     877static DECLCALLBACK(void) drvscsiSuspend(PPDMDRVINS pDrvIns)
     878{
     879    drvscsiR3ResetOrSuspendOrPowerOff(pDrvIns, drvscsiIsAsyncSuspendOrPowerOffDone);
     880}
     881
     882/**
     883 * Callback employed by drvscsiReset.
     884 *
     885 * @returns true if we've quiesced, false if we're still working.
     886 * @param   pDrvIns     The driver instance.
     887 */
     888static DECLCALLBACK(bool) drvscsiIsAsyncResetDone(PPDMDRVINS pDrvIns)
     889{
    856890    PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    857     PDMR3ThreadSuspend(pThis->pAsyncIOThread);
    858 }
    859 
    860 /**
    861  * @copydoc FNPDMDRVSUSPEND
    862  */
    863 static DECLCALLBACK(void) drvscsiSuspend(PPDMDRVINS pDrvIns)
    864 {
    865     PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    866     PDMR3ThreadSuspend(pThis->pAsyncIOThread);
     891
     892    if (!drvscsiAsyncIOLoopNoPendingDummy(pThis, 0 /*ms*/))
     893        return false;
     894    ASMAtomicWriteBool(&pThis->fDummySignal, false);
     895    return true;
    867896}
    868897
     
    872901static DECLCALLBACK(void) drvscsiReset(PPDMDRVINS pDrvIns)
    873902{
    874     PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI);
    875     drvscsiWaitForPendingRequests(pThis, "Reset");
     903    drvscsiR3ResetOrSuspendOrPowerOff(pDrvIns, drvscsiIsAsyncResetDone);
    876904}
    877905
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