Changeset 72588 in vbox for trunk/src/VBox
- Timestamp:
- Jun 17, 2018 6:28:31 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Storage/DevATA.cpp
r72587 r72588 47 47 #include <iprt/string.h> 48 48 #ifdef IN_RING3 49 # include <iprt/uuid.h> 49 # include <iprt/mem.h> 50 # include <iprt/mp.h> 50 51 # include <iprt/semaphore.h> 51 52 # include <iprt/thread.h> 52 53 # include <iprt/time.h> 53 # include <iprt/ alloc.h>54 # include <iprt/uuid.h> 54 55 #endif /* IN_RING3 */ 55 56 #include <iprt/critsect.h> … … 286 287 RCPTRTYPE(uint8_t *) pbIOBufferRC; 287 288 288 /** Counter for number of busy status seen in GC/R0 in a row. */289 uint32_t cBusyStatusHack;290 291 289 /* 292 290 * No data that is part of the saved state after this point!!!!! 293 291 */ 294 292 295 /* Release statistics: number of ATA DMA commands. */ 293 /** Counter for number of busy status seen in R3 in a row. */ 294 uint8_t cBusyStatusHackR3; 295 /** Counter for number of busy status seen in GC/R0 in a row. */ 296 uint8_t cBusyStatusHackRZ; 297 /** Defines the R3 yield rate by a mask (power of 2 minus one). 298 * Lower is more agressive. */ 299 uint8_t cBusyStatusHackR3Rate; 300 /** Defines the RZ yield rate by number of status requests before returning 301 * to ring-3 and yielding there. Lower is more agressive. */ 302 uint8_t cBusyStatusHackRZRate; 303 304 /** Release statistics: number of ATA DMA commands. */ 296 305 STAMCOUNTER StatATADMA; 297 /* Release statistics: number of ATA PIO commands. */306 /** Release statistics: number of ATA PIO commands. */ 298 307 STAMCOUNTER StatATAPIO; 299 /* Release statistics: number of ATAPI PIO commands. */308 /** Release statistics: number of ATAPI PIO commands. */ 300 309 STAMCOUNTER StatATAPIDMA; 301 /* Release statistics: number of ATAPI PIO commands. */310 /** Release statistics: number of ATAPI PIO commands. */ 302 311 STAMCOUNTER StatATAPIPIO; 303 312 #ifdef VBOX_INSTRUMENT_DMA_WRITES 304 /* Release statistics: number of DMA sector writes and the time spent. */313 /** Release statistics: number of DMA sector writes and the time spent. */ 305 314 STAMPROFILEADV StatInstrVDWrites; 306 315 #endif 316 /** Release statistics: Profiling RTThreadYield calls during status polling. */ 317 STAMPROFILEADV StatStatusYields; 307 318 308 319 /** Statistics: number of read operations and the time spent reading. */ … … 4469 4480 { 4470 4481 #ifdef IN_RING3 4471 s->cBusyStatusHack = 0; 4482 /* @bugref{1960}: Don't yield all the time, unless it's a reset (can be tricky). */ 4483 bool fYield = (s->cBusyStatusHackR3++ & s->cBusyStatusHackR3Rate) == 0 4484 || pCtl->fReset; 4485 4472 4486 ataR3LockLeave(pCtl); 4473 4487 4474 # ifndef RT_OS_WINDOWS4475 4488 /* 4476 * The thread might be stuck in an I/O operation 4477 * due to a high I/O load on the host. (see @bugref{3301})4478 * To perform the reset successfully4479 * we interrupt the operation by sending a signal to the thread4480 * if the thread didn't responded in 10ms.4481 * This works only on POSIX hosts (Windows has a CancelSynchronousIo function which4482 * does the same but it was introduced with Vista) but so far4483 * this hang was only observed on Linux and Mac OS X.4489 * The thread might be stuck in an I/O operation due to a high I/O 4490 * load on the host (see @bugref{3301}). To perform the reset 4491 * successfully we interrupt the operation by sending a signal to 4492 * the thread if the thread didn't responded in 10ms. 4493 * 4494 * This works only on POSIX hosts (Windows has a CancelSynchronousIo 4495 * function which does the same but it was introduced with Vista) but 4496 * so far this hang was only observed on Linux and Mac OS X. 4484 4497 * 4485 4498 * This is a workaround and needs to be solved properly. … … 4488 4501 { 4489 4502 uint64_t u64ResetTimeStop = RTTimeMilliTS(); 4490 4491 if ((u64ResetTimeStop - pCtl->u64ResetTime) >= 10) 4503 if (u64ResetTimeStop - pCtl->u64ResetTime >= 10) 4492 4504 { 4493 4505 LogRel(("PIIX3 ATA LUN#%d: Async I/O thread probably stuck in operation, interrupting\n", s->iLUN)); 4494 4506 pCtl->u64ResetTime = u64ResetTimeStop; 4507 # ifndef RT_OS_WINDOWS /* We've got this API on windows, but it doesn't necessarily interrupt I/O. */ 4495 4508 RTThreadPoke(pCtl->AsyncIOThread); 4509 # endif 4510 Assert(fYield); 4496 4511 } 4497 4512 } 4498 # endif 4499 4500 RTThreadYield(); 4513 4514 if (fYield) 4515 { 4516 STAM_REL_PROFILE_ADV_START(&s->StatStatusYields, a); 4517 RTThreadYield(); 4518 STAM_REL_PROFILE_ADV_STOP(&s->StatStatusYields, a); 4519 } 4520 ASMNopPause(); 4501 4521 4502 4522 ataR3LockEnter(pCtl); … … 4508 4528 * especially on SMP systems where we don't gain much by 4509 4529 * yielding the CPU to someone else. */ 4510 if (++s->cBusyStatusHack >= 20)4530 if (++s->cBusyStatusHackRZ >= s->cBusyStatusHackRZRate) 4511 4531 { 4512 s->cBusyStatusHack = 0; 4532 s->cBusyStatusHackRZ = 0; 4533 s->cBusyStatusHackR3 = 0; /* Forces a yield. */ 4513 4534 return VINF_IOM_R3_IOPORT_READ; 4514 4535 } … … 4516 4537 } 4517 4538 else 4518 s->cBusyStatusHack = 0; 4539 { 4540 s->cBusyStatusHackRZ = 0; 4541 s->cBusyStatusHackR3 = 0; 4542 } 4519 4543 ataUnsetIRQ(s); 4520 4544 break; … … 6496 6520 LogRel(("PIIX3 ATA: LUN#%d: TRIM enabled\n", pIf->iLUN)); 6497 6521 } 6522 6523 /* 6524 * Check if SMP system to adjust the agressiveness of the busy yield hack (@bugref{1960}). 6525 * 6526 * The hack is an ancient (2006?) one for dealing with UNI CPU systems where EMT 6527 * would potentially monopolise the CPU and starve I/O threads. It causes the EMT to 6528 * yield it's timeslice if the guest polls the status register during I/O. On modern 6529 * multicore and multithreaded systems, yielding EMT too often may have adverse 6530 * effects (slow grub) so we aim at avoiding repeating the yield there too often. 6531 */ 6532 RTCPUID cCpus = RTMpGetOnlineCount(); 6533 if (cCpus <= 1) 6534 { 6535 pIf->cBusyStatusHackR3Rate = 1; 6536 pIf->cBusyStatusHackRZRate = 8; 6537 } 6538 else if (cCpus <= 2) 6539 { 6540 pIf->cBusyStatusHackR3Rate = 3; 6541 pIf->cBusyStatusHackRZRate = 20; 6542 } 6543 else if (cCpus <= 4) 6544 { 6545 pIf->cBusyStatusHackR3Rate = 15; 6546 pIf->cBusyStatusHackRZRate = 32; 6547 } 6548 else 6549 { 6550 pIf->cBusyStatusHackR3Rate = 127; 6551 pIf->cBusyStatusHackRZRate = 128; 6552 } 6553 6498 6554 return rc; 6499 6555 }
Note:
See TracChangeset
for help on using the changeset viewer.