Changeset 24751 in vbox for trunk/src/VBox
- Timestamp:
- Nov 18, 2009 1:13:11 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DrvSCSI.cpp
r24678 r24751 91 91 /** Request that we've left pending on wakeup or reset. */ 92 92 PRTREQ pPendingDummyReq; 93 /** Indicates whether PDMDrvHlpAsyncNotificationCompleted should be called by 94 * any of the dummy functions. */ 95 bool volatile fDummySignal; 93 96 /** Release statistics: number of bytes written. */ 94 97 STAMCOUNTER StatBytesWritten; … … 676 679 * to complete prior to the device reset. 677 680 * 681 * @param pThis Pointer to the instace data. 678 682 * @returns VINF_SUCCESS. 679 683 */ 680 static int drvscsiAsyncIOLoopSyncCallback(void) 681 { 684 static int drvscsiAsyncIOLoopSyncCallback(PDRVSCSI pThis) 685 { 686 if (pThis->fDummySignal) 687 PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns); 682 688 return VINF_SUCCESS; 683 689 } … … 686 692 * Request function to wakeup the thread. 687 693 * 694 * @param pThis Pointer to the instace data. 688 695 * @returns VWRN_STATE_CHANGED. 689 696 */ 690 static int drvscsiAsyncIOLoopWakeupFunc(void) 691 { 697 static int drvscsiAsyncIOLoopWakeupFunc(PDRVSCSI pThis) 698 { 699 if (pThis->fDummySignal) 700 PDMDrvHlpAsyncNotificationCompleted(pThis->pDrvIns); 692 701 return VWRN_STATE_CHANGED; 693 702 } … … 697 706 * 698 707 * @returns VBox status code. 699 * @param pDrvIns Pointer to the d eviceinstance data.708 * @param pDrvIns Pointer to the driver instance data. 700 709 * @param pThread Pointer to the thread instance data. 701 710 */ … … 753 762 } 754 763 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); 756 765 if (RT_SUCCESS(rc)) 757 766 RTReqFree(pReq); … … 805 814 * Worker for drvscsiReset, drvscsiSuspend and drvscsiPowerOff. 806 815 * 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 */ 819 static 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)) 818 830 { 819 LogRel(("drvscsi%s#%u: previous dummy request is still pending\n", pszEvent, pThis->pDrvIns->iInstance));831 ASMAtomicWriteBool(&pThis->fDummySignal, false); 820 832 return; 821 833 } 822 834 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)) 824 838 { 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; 834 842 } 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 */ 855 static 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; 849 864 } 850 865 … … 854 869 static DECLCALLBACK(void) drvscsiPowerOff(PPDMDRVINS pDrvIns) 855 870 { 871 drvscsiR3ResetOrSuspendOrPowerOff(pDrvIns, drvscsiIsAsyncSuspendOrPowerOffDone); 872 } 873 874 /** 875 * @copydoc FNPDMDRVSUSPEND 876 */ 877 static 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 */ 888 static DECLCALLBACK(bool) drvscsiIsAsyncResetDone(PPDMDRVINS pDrvIns) 889 { 856 890 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; 867 896 } 868 897 … … 872 901 static DECLCALLBACK(void) drvscsiReset(PPDMDRVINS pDrvIns) 873 902 { 874 PDRVSCSI pThis = PDMINS_2_DATA(pDrvIns, PDRVSCSI); 875 drvscsiWaitForPendingRequests(pThis, "Reset"); 903 drvscsiR3ResetOrSuspendOrPowerOff(pDrvIns, drvscsiIsAsyncResetDone); 876 904 } 877 905
Note:
See TracChangeset
for help on using the changeset viewer.