Changeset 20663 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Jun 17, 2009 12:47:55 PM (16 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/EM.cpp
r20408 r20663 3320 3320 { 3321 3321 /* 3322 * EMT Rendezvous (must be serviced before termination). 3323 */ 3324 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS)) 3325 VMMR3EmtRendezvousFF(pVM, pVCpu); 3326 3327 /* 3322 3328 * Termination request. 3323 3329 */ … … 3374 3380 3375 3381 /* check that we got them all */ 3376 AssertCompile(VM_FF_NORMAL_PRIORITY_POST_MASK == (VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_PGM_NO_MEMORY ));3382 AssertCompile(VM_FF_NORMAL_PRIORITY_POST_MASK == (VM_FF_TERMINATE | VM_FF_DBGF | VM_FF_RESET | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS)); 3377 3383 AssertCompile(VMCPU_FF_NORMAL_PRIORITY_POST_MASK == VMCPU_FF_CSAM_SCAN_PAGE); 3378 3384 } … … 3395 3401 if (VM_FF_IS_PENDING_EXCEPT(pVM, VM_FF_PDM_DMA, VM_FF_PGM_NO_MEMORY)) 3396 3402 PDMR3DmaRun(pVM); 3403 3404 /* 3405 * EMT Rendezvous (make sure they are handled before the requests). 3406 */ 3407 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS)) 3408 VMMR3EmtRendezvousFF(pVM, pVCpu); 3397 3409 3398 3410 /* … … 3421 3433 3422 3434 /* check that we got them all */ 3423 AssertCompile(VM_FF_NORMAL_PRIORITY_MASK == (VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_REM_HANDLER_NOTIFY ));3435 AssertCompile(VM_FF_NORMAL_PRIORITY_MASK == (VM_FF_REQUEST | VM_FF_PDM_QUEUES | VM_FF_PDM_DMA | VM_FF_REM_HANDLER_NOTIFY | VM_FF_EMT_RENDEZVOUS)); 3424 3436 } 3425 3437 … … 3536 3548 3537 3549 /* 3550 * EMT Rendezvous (must be serviced before termination). 3551 */ 3552 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS)) 3553 VMMR3EmtRendezvousFF(pVM, pVCpu); 3554 3555 /* 3538 3556 * Termination request. 3539 3557 */ … … 3578 3596 3579 3597 /* check that we got them all */ 3580 AssertCompile(VM_FF_HIGH_PRIORITY_PRE_MASK == (VM_FF_TM_VIRTUAL_SYNC | VM_FF_DBGF | VM_FF_TERMINATE | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY ));3598 AssertCompile(VM_FF_HIGH_PRIORITY_PRE_MASK == (VM_FF_TM_VIRTUAL_SYNC | VM_FF_DBGF | VM_FF_TERMINATE | VM_FF_DEBUG_SUSPEND | VM_FF_PGM_NEED_HANDY_PAGES | VM_FF_PGM_NO_MEMORY | VM_FF_EMT_RENDEZVOUS)); 3581 3599 AssertCompile(VMCPU_FF_HIGH_PRIORITY_PRE_MASK == (VMCPU_FF_TIMER | VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC | VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL | VMCPU_FF_SELM_SYNC_TSS | VMCPU_FF_TRPM_SYNC_IDT | VMCPU_FF_SELM_SYNC_GDT | VMCPU_FF_SELM_SYNC_LDT | VMCPU_FF_INHIBIT_INTERRUPTS)); 3582 3600 } -
trunk/src/VBox/VMM/VMEmt.cpp
r20593 r20663 155 155 break; 156 156 } 157 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS)) 158 VMMR3EmtRendezvousFF(pVM, &pVM->aCpus[idCpu]); 157 159 if (pUVM->vm.s.pReqs) 158 160 { … … 203 205 if ( rc == VINF_EM_TERMINATE 204 206 || pUVM->vm.s.fTerminateEMT 205 || ( pUVM->pVM 207 || ( pUVM->pVM /* pVM may have become invalid by now. */ 206 208 && VM_FF_ISSET(pUVM->pVM, VM_FF_TERMINATE))) 207 209 break; … … 1086 1088 1087 1089 /** 1090 * Rendezvous callback that will be called once. 1091 * 1092 * @returns VBox status code. 1093 * @param pVM VM handle. 1094 * @param pVCpu The VMCPU handle for the calling EMT. 1095 * @param pvUser The new g_aHaltMethods index. 1096 */ 1097 static DECLCALLBACK(int) vmR3SetHaltMethodCallback(PVM pVM, PVMCPU pVCpu, void *pvUser) 1098 { 1099 PUVM pUVM = pVM->pUVM; 1100 uintptr_t i = (uintptr_t)pvUser; 1101 Assert(i < RT_ELEMENTS(g_aHaltMethods)); 1102 NOREF(pVCpu); 1103 1104 /* 1105 * Terminate the old one. 1106 */ 1107 if ( pUVM->vm.s.enmHaltMethod != VMHALTMETHOD_INVALID 1108 && g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnTerm) 1109 { 1110 g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnTerm(pUVM); 1111 pUVM->vm.s.enmHaltMethod = VMHALTMETHOD_INVALID; 1112 } 1113 1114 /* Assert that the failure fallback is where we expect. */ 1115 Assert(g_aHaltMethods[0].enmHaltMethod == VMHALTMETHOD_BOOTSTRAP); 1116 Assert(!g_aHaltMethods[0].pfnTerm && !g_aHaltMethods[0].pfnInit); 1117 1118 /* 1119 * Init the new one. 1120 */ 1121 int rc = VINF_SUCCESS; 1122 memset(&pUVM->vm.s.Halt, 0, sizeof(pUVM->vm.s.Halt)); 1123 if (g_aHaltMethods[i].pfnInit) 1124 { 1125 rc = g_aHaltMethods[i].pfnInit(pUVM); 1126 if (RT_FAILURE(rc)) 1127 { 1128 /* Fall back on the bootstrap method. This requires no 1129 init/term (see assertion above), and will always work. */ 1130 AssertLogRelRC(rc); 1131 i = 0; 1132 } 1133 } 1134 1135 /* 1136 * Commit it. 1137 */ 1138 pUVM->vm.s.enmHaltMethod = g_aHaltMethods[i].enmHaltMethod; 1139 ASMAtomicWriteU32(&pUVM->vm.s.iHaltMethod, i); 1140 1141 return rc; 1142 } 1143 1144 1145 /** 1088 1146 * Changes the halt method. 1089 1147 * … … 1131 1189 1132 1190 /* 1133 * Terminate the old one. 1134 */ 1135 if ( pUVM->vm.s.enmHaltMethod != VMHALTMETHOD_INVALID 1136 && g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnTerm) 1137 { 1138 g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnTerm(pUVM); 1139 pUVM->vm.s.enmHaltMethod = VMHALTMETHOD_INVALID; 1140 } 1141 1142 /** @todo SMP: Need rendezvous thing here, the other EMTs must not be 1143 * sleeping when we switch the notification method or we'll never 1144 * manage to wake them up properly and end up relying on timeouts... */ 1145 1146 /* 1147 * Init the new one. 1148 */ 1149 memset(&pUVM->vm.s.Halt, 0, sizeof(pUVM->vm.s.Halt)); 1150 if (g_aHaltMethods[i].pfnInit) 1151 { 1152 int rc = g_aHaltMethods[i].pfnInit(pUVM); 1153 AssertRCReturn(rc, rc); 1154 } 1155 pUVM->vm.s.enmHaltMethod = enmHaltMethod; 1156 1157 ASMAtomicWriteU32(&pUVM->vm.s.iHaltMethod, i); 1158 return VINF_SUCCESS; 1159 } 1160 1191 * This needs to be done while the other EMTs are not sleeping or otherwise messing around. 1192 */ 1193 return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, vmR3SetHaltMethodCallback, (void *)(uintptr_t)i); 1194 } 1195 -
trunk/src/VBox/VMM/VMM.cpp
r20566 r20663 88 88 #include <iprt/asm.h> 89 89 #include <iprt/time.h> 90 #include <iprt/semaphore.h> 90 91 #include <iprt/stream.h> 91 92 #include <iprt/string.h> … … 136 137 */ 137 138 pVM->vmm.s.offVM = RT_OFFSETOF(VM, vmm); 139 pVM->vmm.s.hEvtRendezvousEnterOneByOne = NIL_RTSEMEVENT; 140 pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce = NIL_RTSEMEVENTMULTI; 141 pVM->vmm.s.hEvtMulRendezvousDone = NIL_RTSEMEVENTMULTI; 142 pVM->vmm.s.hEvtRendezvousDoneCaller = NIL_RTSEMEVENT; 138 143 int rc = CFGMR3QueryU32(CFGMR3GetRoot(pVM), "YieldEMTInterval", &pVM->vmm.s.cYieldEveryMillies); 139 144 if (rc == VERR_CFGM_VALUE_NOT_FOUND) … … 144 149 145 150 /* 146 * Initialize the VMM sync critical section .151 * Initialize the VMM sync critical section and semaphores. 147 152 */ 148 153 rc = RTCritSectInit(&pVM->vmm.s.CritSectSync); 154 AssertRCReturn(rc, rc); 155 rc = RTSemEventCreate(&pVM->vmm.s.hEvtRendezvousEnterOneByOne); 156 AssertRCReturn(rc, rc); 157 rc = RTSemEventMultiCreate(&pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce); 158 AssertRCReturn(rc, rc); 159 rc = RTSemEventMultiCreate(&pVM->vmm.s.hEvtMulRendezvousDone); 160 AssertRCReturn(rc, rc); 161 rc = RTSemEventCreate(&pVM->vmm.s.hEvtRendezvousDoneCaller); 149 162 AssertRCReturn(rc, rc); 150 163 … … 649 662 650 663 RTCritSectDelete(&pVM->vmm.s.CritSectSync); 664 RTSemEventDestroy(pVM->vmm.s.hEvtRendezvousEnterOneByOne); 665 pVM->vmm.s.hEvtRendezvousEnterOneByOne = NIL_RTSEMEVENT; 666 RTSemEventMultiDestroy(pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce); 667 pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce = NIL_RTSEMEVENTMULTI; 668 RTSemEventMultiDestroy(pVM->vmm.s.hEvtMulRendezvousDone); 669 pVM->vmm.s.hEvtMulRendezvousDone = NIL_RTSEMEVENTMULTI; 670 RTSemEventDestroy(pVM->vmm.s.hEvtRendezvousDoneCaller); 671 pVM->vmm.s.hEvtRendezvousDoneCaller = NIL_RTSEMEVENT; 651 672 652 673 #ifdef VBOX_STRICT_VMM_STACK … … 1298 1319 * @param pfnHandler Callback handler 1299 1320 * @param pvUser User specified parameter 1321 * 1322 * @thread EMT 1300 1323 */ 1301 1324 VMMR3DECL(int) VMMR3AtomicExecuteHandler(PVM pVM, PFNATOMICHANDLER pfnHandler, void *pvUser) … … 1325 1348 rc = pfnHandler(pVM, pvUser); 1326 1349 RTCritSectLeave(&pVM->vmm.s.CritSectSync); 1350 return rc; 1351 } 1352 1353 1354 /** 1355 * Count returns and have the last non-caller EMT wake up the caller. 1356 * 1357 * @param pVM The VM handle. 1358 */ 1359 DECL_FORCE_INLINE(void) vmmR3EmtRendezvousNonCallerReturn(PVM pVM) 1360 { 1361 uint32_t cReturned = ASMAtomicIncU32(&pVM->vmm.s.cRendezvousEmtsReturned); 1362 if (cReturned == pVM->cCPUs - 1U) 1363 { 1364 int rc = RTSemEventSignal(pVM->vmm.s.hEvtRendezvousDoneCaller); 1365 AssertLogRelRC(rc); 1366 } 1367 } 1368 1369 1370 /** 1371 * Common worker for VMMR3EmtRendezvous and VMMR3EmtRendezvousFF. 1372 * 1373 * @param pVM The VM handle. 1374 * @param pVCpu The VMCPU structure for the calling EMT. 1375 * @param fIsCaller Whether we're the VMMR3EmtRendezvous caller or 1376 * not. 1377 * @param fFlags The flags. 1378 * @param pfnRendezvous The callback. 1379 * @param pvUser The user argument for the callback. 1380 */ 1381 static void vmmR3EmtRendezvousCommon(PVM pVM, PVMCPU pVCpu, bool fIsCaller, 1382 uint32_t fFlags, PFNVMMEMTRENDEZVOUS pfnRendezvous, void *pvUser) 1383 { 1384 int rc; 1385 1386 /* 1387 * Enter, the last EMT triggers the next callback phase. 1388 */ 1389 uint32_t cEntered = ASMAtomicIncU32(&pVM->vmm.s.cRendezvousEmtsEntered); 1390 if (cEntered != pVM->cCPUs) 1391 { 1392 if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE) 1393 { 1394 /* Wait for our turn. */ 1395 rc = RTSemEventWait(pVM->vmm.s.hEvtRendezvousEnterOneByOne, RT_INDEFINITE_WAIT); 1396 AssertLogRelRC(rc); 1397 } 1398 else if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE) 1399 { 1400 /* Wait for the last EMT to arrive and wake everyone up. */ 1401 rc = RTSemEventMultiWait(pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce, RT_INDEFINITE_WAIT); 1402 AssertLogRelRC(rc); 1403 } 1404 else 1405 { 1406 Assert((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE); 1407 1408 /* 1409 * The execute once is handled specially to optimize the code flow. 1410 * 1411 * The last EMT to arrive will perform the callback and the other 1412 * EMTs will wait on the Done/DoneCaller semaphores (instead of 1413 * the EnterOneByOne/AllAtOnce) in the meanwhile. When the callback 1414 * returns, that EMT will initiate the normal return sequence. 1415 */ 1416 if (!fIsCaller) 1417 { 1418 rc = RTSemEventMultiWait(pVM->vmm.s.hEvtMulRendezvousDone, RT_INDEFINITE_WAIT); 1419 AssertLogRelRC(rc); 1420 1421 vmmR3EmtRendezvousNonCallerReturn(pVM); 1422 } 1423 return; 1424 } 1425 } 1426 else 1427 { 1428 /* 1429 * All EMTs are waiting, clear the FF and take action according to the 1430 * execution method. 1431 */ 1432 VM_FF_CLEAR(pVM, VM_FF_EMT_RENDEZVOUS); 1433 1434 if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ALL_AT_ONCE) 1435 { 1436 /* Wake up everyone. */ 1437 rc = RTSemEventMultiSignal(pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce); 1438 AssertLogRelRC(rc); 1439 } 1440 /* else: execute the handler on the current EMT and wake up one or more threads afterwards. */ 1441 } 1442 1443 1444 /* 1445 * Do the callback and update the status if necessary. 1446 */ 1447 rc = pfnRendezvous(pVM, pVCpu, pvUser); 1448 if (rc != VINF_SUCCESS) 1449 { 1450 int32_t i32RendezvousStatus; 1451 do 1452 { 1453 i32RendezvousStatus = ASMAtomicUoReadS32(&pVM->vmm.s.i32RendezvousStatus); 1454 if ( RT_FAILURE(i32RendezvousStatus) 1455 || ( i32RendezvousStatus != VINF_SUCCESS 1456 && RT_SUCCESS(rc))) 1457 break; 1458 } while (!ASMAtomicCmpXchgS32(&pVM->vmm.s.i32RendezvousStatus, rc, i32RendezvousStatus)); 1459 } 1460 1461 /* 1462 * Increment the done counter and take action depending on whether we're 1463 * the last to finish callback execution. 1464 */ 1465 uint32_t cDone = ASMAtomicIncU32(&pVM->vmm.s.cRendezvousEmtsDone); 1466 if ( cDone != pVM->cCPUs 1467 && (fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) != VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE) 1468 { 1469 /* Signal the next EMT? */ 1470 if ((fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) == VMMEMTRENDEZVOUS_FLAGS_TYPE_ONE_BY_ONE) 1471 { 1472 rc = RTSemEventSignal(pVM->vmm.s.hEvtRendezvousEnterOneByOne); 1473 AssertLogRelRC(rc); 1474 } 1475 1476 /* Wait for the rest to finish (the caller waits on hEvtRendezvousDoneCaller). */ 1477 if (!fIsCaller) 1478 { 1479 rc = RTSemEventMultiWait(pVM->vmm.s.hEvtMulRendezvousDone, RT_INDEFINITE_WAIT); 1480 AssertLogRelRC(rc); 1481 } 1482 } 1483 else 1484 { 1485 /* Callback execution is all done, tell the rest to return. */ 1486 rc = RTSemEventMultiSignal(pVM->vmm.s.hEvtMulRendezvousDone); 1487 AssertLogRelRC(rc); 1488 } 1489 1490 if (!fIsCaller) 1491 vmmR3EmtRendezvousNonCallerReturn(pVM); 1492 } 1493 1494 1495 /** 1496 * Called in response to VM_FF_EMT_RENDEZVOUS. 1497 * 1498 * @param pVM The VM handle 1499 * @param pVCpu The handle of the calling EMT. 1500 * 1501 * @thread EMT 1502 */ 1503 VMMR3DECL(void) VMMR3EmtRendezvousFF(PVM pVM, PVMCPU pVCpu) 1504 { 1505 vmmR3EmtRendezvousCommon(pVM, pVCpu, false /* fIsCaller */, pVM->vmm.s.fRendezvousFlags, 1506 pVM->vmm.s.pfnRendezvous, pVM->vmm.s.pvRendezvousUser); 1507 } 1508 1509 1510 /** 1511 * EMT rendezvous. 1512 * 1513 * Gathers all the EMTs and execute some code on each of them, either in a one 1514 * by one fashion or all at once. 1515 * 1516 * @returns VBox status code. This will be the first error or, if all succeed, 1517 * the first informational status code. 1518 * @retval VERR_VM_THREAD_NOT_EMT if the caller is not an EMT. 1519 * 1520 * @param pVM The VM handle. 1521 * @param fFlags Flags indicating execution methods. See 1522 * grp_VMMR3EmtRendezvous_fFlags. 1523 * @param pfnRendezvous The callback. 1524 * @param pvUser User argument for the callback. 1525 * 1526 * @thread EMT 1527 */ 1528 VMMR3DECL(int) VMMR3EmtRendezvous(PVM pVM, uint32_t fFlags, PFNVMMEMTRENDEZVOUS pfnRendezvous, void *pvUser) 1529 { 1530 /* 1531 * Validate input. 1532 */ 1533 PVMCPU pVCpu = VMMGetCpu(pVM); 1534 AssertReturn(pVCpu, VERR_VM_THREAD_NOT_EMT); 1535 AssertMsg( (fFlags & VMMEMTRENDEZVOUS_FLAGS_TYPE_MASK) != VMMEMTRENDEZVOUS_FLAGS_TYPE_INVALID 1536 && !(fFlags & ~VMMEMTRENDEZVOUS_FLAGS_VALID_MASK), ("%#x\n", fFlags)); 1537 1538 int rc; 1539 if (pVM->cCPUs == 1) 1540 /* 1541 * Shortcut for the single EMT case. 1542 */ 1543 rc = pfnRendezvous(pVM, pVCpu, pvUser); 1544 else 1545 { 1546 /* 1547 * Spin lock. If busy, wait for the other EMT to finish while keeping a 1548 * lookout of the RENDEZVOUS FF. 1549 */ 1550 while (!ASMAtomicCmpXchgU32(&pVM->vmm.s.u32RendezvousLock, 0x77778888, 0)) 1551 { 1552 if (VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS)) 1553 VMMR3EmtRendezvousFF(pVM, pVCpu); 1554 } 1555 Assert(!VM_FF_ISPENDING(pVM, VM_FF_EMT_RENDEZVOUS)); 1556 1557 /* 1558 * Clear the slate. This is a semaphore ping-pong orgy. :-) 1559 */ 1560 rc = RTSemEventWait(pVM->vmm.s.hEvtRendezvousEnterOneByOne, 0); AssertLogRelMsg(rc == VERR_TIMEOUT || rc == VINF_SUCCESS, ("%Rrc\n", rc)); 1561 rc = RTSemEventMultiReset(pVM->vmm.s.hEvtMulRendezvousEnterAllAtOnce); AssertLogRelRC(rc); 1562 rc = RTSemEventMultiReset(pVM->vmm.s.hEvtMulRendezvousDone); AssertLogRelRC(rc); 1563 rc = RTSemEventWait(pVM->vmm.s.hEvtRendezvousDoneCaller, 0); AssertLogRelMsg(rc == VERR_TIMEOUT || rc == VINF_SUCCESS, ("%Rrc\n", rc)); 1564 ASMAtomicWriteU32(&pVM->vmm.s.cRendezvousEmtsEntered, 0); 1565 ASMAtomicWriteU32(&pVM->vmm.s.cRendezvousEmtsDone, 0); 1566 ASMAtomicWriteU32(&pVM->vmm.s.cRendezvousEmtsReturned, 0); 1567 ASMAtomicWriteS32(&pVM->vmm.s.i32RendezvousStatus, VINF_SUCCESS); 1568 ASMAtomicWritePtr((void * volatile *)&pVM->vmm.s.pfnRendezvous, (void *)(uintptr_t)pfnRendezvous); 1569 ASMAtomicWritePtr(&pVM->vmm.s.pvRendezvousUser, pvUser); 1570 ASMAtomicWriteU32(&pVM->vmm.s.fRendezvousFlags, fFlags); 1571 1572 /* 1573 * Set the FF and poke the other EMTs. 1574 */ 1575 VM_FF_SET(pVM, VM_FF_EMT_RENDEZVOUS); 1576 VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_POKE); 1577 1578 /* 1579 * Do the same ourselves. 1580 */ 1581 vmmR3EmtRendezvousCommon(pVM, pVCpu, true /* fIsCaller */, fFlags, pfnRendezvous, pvUser); 1582 1583 /* 1584 * The caller waits for the other EMTs to be done and return before doing 1585 * the cleanup. This makes away with wakeup / reset races we would otherwise 1586 * risk in the multiple release event semaphore code (hEvtRendezvousDoneCaller). 1587 */ 1588 rc = RTSemEventWait(pVM->vmm.s.hEvtRendezvousDoneCaller, RT_INDEFINITE_WAIT); 1589 AssertLogRelRC(rc); 1590 1591 /* 1592 * Get the return code and clean up a little bit. 1593 */ 1594 rc = pVM->vmm.s.i32RendezvousStatus; 1595 ASMAtomicWritePtr((void * volatile *)&pVM->vmm.s.pfnRendezvous, NULL); 1596 1597 ASMAtomicWriteU32(&pVM->vmm.s.u32RendezvousLock, 0); 1598 } 1599 1327 1600 return rc; 1328 1601 } … … 1760 2033 PRINT_FLAG(VM_FF_,TERMINATE); 1761 2034 PRINT_FLAG(VM_FF_,RESET); 2035 PRINT_FLAG(VM_FF_,EMT_RENDEZVOUS); 1762 2036 PRINT_FLAG(VM_FF_,PGM_NEED_HANDY_PAGES); 1763 2037 PRINT_FLAG(VM_FF_,PGM_NO_MEMORY); -
trunk/src/VBox/VMM/VMMInternal.h
r20545 r20663 267 267 * Use for synchronizing all VCPUs 268 268 */ 269 RTCRITSECT CritSectSync; 269 RTCRITSECT CritSectSync; 270 271 /** @name EMT Rendezvous 272 * @{ */ 273 /** Semaphore to wait on upon entering for one-by-one execution. */ 274 RTSEMEVENT hEvtRendezvousEnterOneByOne; 275 /** Semaphore to wait on upon entering for all-at-once execution. */ 276 RTSEMEVENTMULTI hEvtMulRendezvousEnterAllAtOnce; 277 /** Semaphore to wait on when done. */ 278 RTSEMEVENTMULTI hEvtMulRendezvousDone; 279 /** Semaphore the VMMR3EmtRendezvous caller waits on at the end. */ 280 RTSEMEVENT hEvtRendezvousDoneCaller; 281 /** Callback. */ 282 R3PTRTYPE(PFNVMMEMTRENDEZVOUS) volatile pfnRendezvous; 283 /** The user argument for the callback. */ 284 RTR3PTR volatile pvRendezvousUser; 285 /** Flags. */ 286 volatile uint32_t fRendezvousFlags; 287 /** The number of EMTs that has entered. */ 288 volatile uint32_t cRendezvousEmtsEntered; 289 /** The number of EMTs that has done their job. */ 290 volatile uint32_t cRendezvousEmtsDone; 291 /** The number of EMTs that has returned. */ 292 volatile uint32_t cRendezvousEmtsReturned; 293 /** The status code. */ 294 volatile int32_t i32RendezvousStatus; 295 /** Spin lock. */ 296 volatile uint32_t u32RendezvousLock; 297 /** @} */ 270 298 271 299 /** Buffer for storing the standard assertion message for a ring-0 assertion. -
trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
r20530 r20663 882 882 GEN_CHECK_OFF(VMM, pfnCPUMRCResumeGuest); 883 883 GEN_CHECK_OFF(VMM, pfnCPUMRCResumeGuestV86); 884 GEN_CHECK_OFF(VMM, pRCLoggerRC); 885 GEN_CHECK_OFF(VMM, pRCLoggerR3); 886 GEN_CHECK_OFF(VMM, cbRCLogger); 887 GEN_CHECK_OFF(VMM, pYieldTimer); 888 GEN_CHECK_OFF(VMM, cYieldResumeMillies); 889 GEN_CHECK_OFF(VMM, cYieldEveryMillies); 890 GEN_CHECK_OFF(VMM, CritSectSync); 891 GEN_CHECK_OFF(VMM, hEvtRendezvousEnterOneByOne); 892 GEN_CHECK_OFF(VMM, hEvtMulRendezvousEnterAllAtOnce); 893 GEN_CHECK_OFF(VMM, hEvtMulRendezvousDone); 894 GEN_CHECK_OFF(VMM, hEvtRendezvousDoneCaller); 895 GEN_CHECK_OFF(VMM, pfnRendezvous); 896 GEN_CHECK_OFF(VMM, pvRendezvousUser); 897 GEN_CHECK_OFF(VMM, fRendezvousFlags); 898 GEN_CHECK_OFF(VMM, cRendezvousEmtsEntered); 899 GEN_CHECK_OFF(VMM, cRendezvousEmtsDone); 900 GEN_CHECK_OFF(VMM, cRendezvousEmtsReturned); 901 GEN_CHECK_OFF(VMM, i32RendezvousStatus); 902 GEN_CHECK_OFF(VMM, u32RendezvousLock); 903 GEN_CHECK_OFF(VMM, szRing0AssertMsg1); 904 GEN_CHECK_OFF(VMM, szRing0AssertMsg2); 905 GEN_CHECK_OFF(VMM, StatRunRC); 906 GEN_CHECK_OFF(VMM, StatRZCallPGMLock); 884 907 GEN_CHECK_OFF(VMMCPU, iLastGZRc); 885 908 GEN_CHECK_OFF(VMMCPU, pbEMTStackR3); 886 909 GEN_CHECK_OFF(VMMCPU, pbEMTStackRC); 887 910 GEN_CHECK_OFF(VMMCPU, pbEMTStackBottomRC); 888 GEN_CHECK_OFF(VMM, pRCLoggerRC);889 GEN_CHECK_OFF(VMM, pRCLoggerR3);890 911 #ifdef LOG_ENABLED 891 912 GEN_CHECK_OFF(VMMCPU, pR0LoggerR0); 892 913 GEN_CHECK_OFF(VMMCPU, pR0LoggerR3); 893 914 #endif 894 GEN_CHECK_OFF(VMM, cbRCLogger);895 GEN_CHECK_OFF(VMM, pYieldTimer);896 GEN_CHECK_OFF(VMM, cYieldResumeMillies);897 GEN_CHECK_OFF(VMM, cYieldEveryMillies);898 915 GEN_CHECK_OFF(VMMCPU, enmCallHostOperation); 899 916 GEN_CHECK_OFF(VMMCPU, rcCallHost); … … 902 919 GEN_CHECK_OFF(VMMCPU, CallHostR0JmpBuf.SpCheck); 903 920 GEN_CHECK_OFF(VMMCPU, CallHostR0JmpBuf.SpResume); 904 GEN_CHECK_OFF(VMM, StatRunRC);905 GEN_CHECK_OFF(VMM, StatRZCallPGMLock);906 921 907 922 GEN_CHECK_SIZE(RTPINGPONG);
Note:
See TracChangeset
for help on using the changeset viewer.