Changeset 24096 in vbox for trunk/src/VBox/Devices
- Timestamp:
- Oct 26, 2009 10:35:29 PM (15 years ago)
- Location:
- trunk/src/VBox/Devices/Storage
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/ATAController.cpp
r23417 r24096 248 248 rc = RTSemMutexRelease(pCtl->AsyncIORequestMutex); 249 249 AssertRC(rc); 250 LogBird(("ata: %x: signalling\n", pCtl->IOPortBase1));251 250 rc = PDMR3CritSectScheduleExitEvent(&pCtl->lock, pCtl->AsyncIOSem); 252 251 if (RT_FAILURE(rc)) 253 252 { 254 LogBird(("ata: %x: schedule failed, rc=%Rrc\n", pCtl->IOPortBase1, rc));255 253 rc = RTSemEventSignal(pCtl->AsyncIOSem); 256 254 AssertRC(rc); … … 3083 3081 { 3084 3082 uint64_t u64Start; 3083 bool fRc; 3084 3085 /* Hope for the simple way out... */ 3086 if (ataAsyncIOIsIdle(pCtl, false /*fStrict*/)) 3087 return true; 3085 3088 3086 3089 /* 3087 * Wait for any pending async operation to finish3090 * Have to wait. Do the setup while owning the mutex to avoid races. 3088 3091 */ 3092 RTSemMutexRequest(pCtl->AsyncIORequestMutex, RT_INDEFINITE_WAIT); 3093 3094 RTThreadUserReset(pCtl->AsyncIOThread); 3095 ASMAtomicWriteBool(&pCtl->fSignalIdle, true); 3096 3097 RTSemMutexRelease(pCtl->AsyncIORequestMutex); 3098 3089 3099 u64Start = RTTimeMilliTS(); 3090 3100 for (;;) 3091 3101 { 3092 if (ataAsyncIOIsIdle(pCtl, false)) 3093 return true; 3102 fRc = ataAsyncIOIsIdle(pCtl, false /*fStrict*/); 3103 if (fRc) 3104 break; 3105 3094 3106 if (RTTimeMilliTS() - u64Start >= cMillies) 3095 3107 break; 3096 3108 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; 3102 3118 } 3103 3119 … … 3830 3846 } 3831 3847 3848 3849 /** 3850 * Signal ataWaitForAsyncIOIsIdle that we're idle (if we actually are). 3851 * 3852 * @param pCtl The controller. 3853 */ 3854 static 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 3832 3870 /** Asynch I/O thread for an interface. Once upon a time this was readable 3833 3871 * code with several loops and a different semaphore for each purpose. But … … 3850 3888 while (pCtl->fRedoIdle) 3851 3889 { 3890 if (pCtl->fSignalIdle) 3891 ataAsyncSignalIdle(pCtl); 3852 3892 rc = RTSemEventWait(pCtl->SuspendIOSem, RT_INDEFINITE_WAIT); 3853 3893 if (RT_FAILURE(rc) || pCtl->fShutdown) … … 3860 3900 if (pReq == NULL) 3861 3901 { 3862 LogBird(("ata: %x: going to sleep...\n", pCtl->IOPortBase1)); 3902 if (pCtl->fSignalIdle) 3903 ataAsyncSignalIdle(pCtl); 3863 3904 rc = RTSemEventWait(pCtl->AsyncIOSem, RT_INDEFINITE_WAIT); 3864 LogBird(("ata: %x: waking up\n", pCtl->IOPortBase1));3865 3905 if (RT_FAILURE(rc) || pCtl->fShutdown) 3866 3906 break; … … 3892 3932 { 3893 3933 STAM_PROFILE_START(&pCtl->StatLockWait, a); 3894 LogBird(("ata: %x: entering critsect\n", pCtl->IOPortBase1));3895 3934 PDMCritSectEnter(&pCtl->lock, VINF_SUCCESS); 3896 LogBird(("ata: %x: entered\n", pCtl->IOPortBase1));3897 3935 STAM_PROFILE_STOP(&pCtl->StatLockWait, a); 3898 3936 } … … 4291 4329 } 4292 4330 4293 LogBird(("ata: %x: leaving critsect\n", pCtl->IOPortBase1));4294 4331 PDMCritSectLeave(&pCtl->lock); 4295 4332 } 4296 4333 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 4308 4337 /* Do not destroy request mutex yet, still needed for proper shutdown. */ 4309 4338 pCtl->fShutdown = false; 4310 /* This must be last, as it also signals thread exit to EMT. */4311 pCtl->AsyncIOThread = NIL_RTTHREAD;4312 4339 4313 4340 Log2(("%s: Ctl: return %Rrc\n", __FUNCTION__, rc)); … … 4606 4633 else 4607 4634 AssertMsgFailed(("ataIOPortWrite1: unsupported write to port %x val=%x size=%d\n", Port, u32, cb)); 4608 LogBird(("ata: leaving critsect\n"));4609 4635 PDMCritSectLeave(&pCtl->lock); 4610 LogBird(("ata: left critsect\n"));4611 4636 return rc; 4612 4637 } … … 4861 4886 4862 4887 /* 4863 * Terminate all async helper threads4888 * Terminate the async helper thread and wait for it to finish up. 4864 4889 */ 4865 4890 if (pCtl->AsyncIOThread != NIL_RTTHREAD) 4866 4891 { 4867 ASMAtomic XchgU32(&pCtl->fShutdown, true);4892 ASMAtomicWriteU32(&pCtl->fShutdown, true); 4868 4893 rc = RTSemEventSignal(pCtl->AsyncIOSem); 4869 4894 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; 4897 4899 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)); 4899 4903 } 4900 4904 … … 4902 4906 * Now the request mutexes are no longer needed. Free resources. 4903 4907 */ 4904 if (pCtl->AsyncIORequestMutex )4908 if (pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX) 4905 4909 { 4906 4910 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 } 4908 4933 } 4909 4934 … … 5475 5500 pCtl->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 5476 5501 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; 5477 5506 5478 5507 for (uint32_t j = 0; j < RT_ELEMENTS(pCtl->aIfs); j++) … … 5505 5534 pCtl->uAsyncIOState = AHCIATA_AIO_NEW; 5506 5535 rc = RTSemEventCreate(&pCtl->AsyncIOSem); 5507 AssertRC (rc);5536 AssertRCReturn(rc, rc); 5508 5537 rc = RTSemEventCreate(&pCtl->SuspendIOSem); 5509 AssertRC (rc);5538 AssertRCReturn(rc, rc); 5510 5539 rc = RTSemMutexCreate(&pCtl->AsyncIORequestMutex); 5511 AssertRC (rc);5540 AssertRCReturn(rc, rc); 5512 5541 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); 5515 5545 Assert(pCtl->AsyncIOThread != NIL_RTTHREAD && pCtl->AsyncIOSem != NIL_RTSEMEVENT && pCtl->SuspendIOSem != NIL_RTSEMEVENT && pCtl->AsyncIORequestMutex != NIL_RTSEMMUTEX); 5516 5546 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 366 366 /** The position at which to get a new request for the AIO thread. */ 367 367 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. */ 369 372 /** Magic delay before triggering interrupts in DMA mode. */ 370 373 uint32_t DelayIRQMillies; -
trunk/src/VBox/Devices/Storage/DevAHCI.cpp
r24072 r24096 574 574 PDMCRITSECT lock; 575 575 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 576 582 /** Bitmask of ports which asserted an interrupt. */ 577 583 uint32_t u32PortsInterrupted; … … 586 592 /** If the new async interface is used if available. */ 587 593 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]; 588 598 589 599 /** Number of usable ports on this controller. */ … … 591 601 592 602 #if HC_ARCH_BITS == 64 593 uint32_t Alignment 7;603 uint32_t Alignment9; 594 604 #endif 595 605 … … 4917 4927 __FUNCTION__, pInterface, pvUser, pAhciPortTaskState->uTag)); 4918 4928 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; 4920 4934 } 4921 4935 … … 5374 5388 5375 5389 ASMAtomicXchgBool(&pAhciPort->fAsyncIOThreadIdle, true); 5390 if (pAhci->fSignalIdle) 5391 RTSemEventSignal(pAhci->hEvtIdle); 5376 5392 5377 5393 rc = RTSemEventWait(pAhciPort->AsyncIORequestSem, 1000); … … 5637 5653 } 5638 5654 5655 if (pAhci->fSignalIdle) 5656 RTSemEventSignal(pAhci->hEvtIdle); 5657 5639 5658 /* Free task state memory */ 5640 5659 if (pAhciPortTaskState->pSGListHead) … … 5768 5787 ataControllerDestroy(&pAhci->aCts[i]); 5769 5788 5789 RTSemEventDestroy(pAhci->hEvtIdle); 5790 pAhci->hEvtIdle = NIL_RTSEMEVENT; 5791 5770 5792 PDMR3CritSectDelete(&pAhci->lock); 5771 5793 } … … 5882 5904 bool fAllFinished; 5883 5905 5906 ASMAtomicWriteBool(&pAhci->fSignalIdle, true); 5884 5907 u64Start = RTTimeMilliTS(); 5885 5908 for (;;) … … 5905 5928 break; 5906 5929 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); 5910 5936 return fAllFinished; 5911 5937 } … … 6502 6528 pThis->pDevInsR0 = PDMDEVINS_2_R0PTR(pDevIns); 6503 6529 pThis->pDevInsRC = PDMDEVINS_2_RCPTR(pDevIns); 6530 pThis->hEvtIdle = NIL_RTSEMEVENT; 6504 6531 6505 6532 PCIDevSetVendorId (&pThis->dev, 0x8086); /* Intel */ … … 6582 6609 return rc; 6583 6610 } 6611 6612 rc = RTSemEventCreate(&pThis->hEvtIdle); 6613 AssertRCReturn(rc, rc); 6584 6614 6585 6615 /* Create the timer for command completion coalescing feature. */
Note:
See TracChangeset
for help on using the changeset viewer.