Changeset 19537 in vbox for trunk/src/VBox/VMM
- Timestamp:
- May 8, 2009 6:09:57 PM (16 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/TM.cpp
r19507 r19537 1957 1957 1958 1958 case TMTIMERSTATE_EXPIRED: 1959 case TMTIMERSTATE_PENDING_DESTROY: 1960 case TMTIMERSTATE_PENDING_STOP_DESTROY: 1959 case TMTIMERSTATE_DESTROY: 1961 1960 case TMTIMERSTATE_FREE: 1962 1961 AssertMsgFailed(("Invalid timer state %d %s (%s)\n", pTimer->enmState, tmTimerState(pTimer->enmState), pTimer->pszDesc)); -
trunk/src/VBox/VMM/TMInternal.h
r19499 r19537 91 91 * Currently in the ScheduleTimers list and the active list. */ 92 92 TMTIMERSTATE_PENDING_RESCHEDULE, 93 /** Timer is destroyed but needs to be replaced from the 94 * active to the free list. 95 * Currently in the ScheduleTimers list and the active list. */ 96 TMTIMERSTATE_PENDING_STOP_DESTROY, 97 /** Timer is destroyed but needs moving to the free list. 98 * Currently in the ScheduleTimers list. */ 99 TMTIMERSTATE_PENDING_DESTROY, 93 /** Timer is being destroyed. */ 94 TMTIMERSTATE_DESTROY, 100 95 /** Timer is free. */ 101 96 TMTIMERSTATE_FREE -
trunk/src/VBox/VMM/VMMAll/TMAll.cpp
r19507 r19537 544 544 * @param pTimer Timer handle as returned by one of the create functions. 545 545 */ 546 VMMR3DECL(int) TMR3TimerDestroy(PTMTIMER pTimer) 547 { 548 int cRetries = 1000; 549 do 546 VMMR3DECL(int) TMR3TimerDestroy(TMTIMER *pTimer) 547 { 548 /* 549 * Be extra careful here. 550 */ 551 if (!pTimer) 552 return VINF_SUCCESS; 553 AssertPtr(pTimer); 554 Assert((unsigned)pTimer->enmClock < (unsigned)TMCLOCK_MAX); 555 556 PVM pVM = pTimer->CTX_SUFF(pVM); 557 PTMTIMERQUEUE pQueue = &pVM->tm.s.CTX_SUFF(paTimerQueues)[pTimer->enmClock]; 558 bool fActive = false; 559 bool fPending = false; 560 561 /* 562 * The rest of the game happens behind the lock, just 563 * like create does. All the work is done here. 564 */ 565 tmLock(pVM); 566 for (int cRetries = 1000;; cRetries--) 550 567 { 551 568 /* 552 * Change to any of the DESTROY states if valid.569 * Change to the DESTROY state. 553 570 */ 554 TMTIMERSTATE enmState = pTimer->enmState; 571 TMTIMERSTATE enmState = pTimer->enmState; 572 TMTIMERSTATE enmNewState = enmState; 555 573 Log2(("TMTimerDestroy: %p:{.enmState=%s, .pszDesc='%s'} cRetries=%d\n", 556 574 pTimer, tmTimerState(enmState), R3STRING(pTimer->pszDesc), cRetries)); 557 575 switch (enmState) 558 576 { 577 case TMTIMERSTATE_STOPPED: 559 578 case TMTIMERSTATE_EXPIRED: 560 if (!VM_IS_EMT(pTimer->CTX_SUFF(pVM)))561 {562 AssertMsgFailed(("Attempted timer destruction from other thread while expire pending! (%s)\n", R3STRING(pTimer->pszDesc)));563 return VERR_INVALID_PARAMETER;564 }565 /* fall thru */566 case TMTIMERSTATE_STOPPED:567 if (tmTimerTryWithLink(pTimer, TMTIMERSTATE_PENDING_DESTROY, enmState))568 {569 tmSchedule(pTimer);570 return VINF_SUCCESS;571 }572 579 break; 573 580 574 581 case TMTIMERSTATE_ACTIVE: 575 if (tmTimerTryWithLink(pTimer, TMTIMERSTATE_PENDING_STOP_DESTROY, enmState)) 576 { 577 tmSchedule(pTimer); 578 return VINF_SUCCESS; 579 } 582 fActive = true; 580 583 break; 581 584 582 585 case TMTIMERSTATE_PENDING_STOP: 583 586 case TMTIMERSTATE_PENDING_STOP_SCHEDULE: 584 if (tmTimerTry(pTimer, TMTIMERSTATE_PENDING_STOP_DESTROY, enmState)) 585 { 586 tmSchedule(pTimer); 587 return VINF_SUCCESS; 588 } 587 case TMTIMERSTATE_PENDING_RESCHEDULE: 588 fActive = true; 589 fPending = true; 589 590 break; 590 591 591 case TMTIMERSTATE_PENDING_DESTROY: 592 case TMTIMERSTATE_PENDING_STOP_DESTROY: 593 AssertMsgFailed(("How many times do you think you can destroy the same timer... (%s)\n", R3STRING(pTimer->pszDesc))); 594 return VERR_INVALID_PARAMETER; 595 596 case TMTIMERSTATE_PENDING_RESCHEDULE: 597 if (tmTimerTry(pTimer, TMTIMERSTATE_PENDING_STOP_DESTROY, enmState)) 598 { 599 tmSchedule(pTimer); 600 return VINF_SUCCESS; 601 } 592 case TMTIMERSTATE_PENDING_SCHEDULE: 593 fPending = true; 602 594 break; 603 595 604 case TMTIMERSTATE_PENDING_SCHEDULE: 605 if (tmTimerTry(pTimer, TMTIMERSTATE_PENDING_DESTROY, enmState)) 606 { 607 tmSchedule(pTimer); 608 return VINF_SUCCESS; 609 } 610 break; 611 596 /* 597 * This shouldn't happen as the caller should make sure there are no races. 598 */ 612 599 case TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE: 613 600 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: 614 #ifdef IN_RING3 601 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc)); 602 tmUnlock(pVM); 615 603 if (!RTThreadYield()) 616 604 RTThreadSleep(1); 617 #endif 618 break; 605 AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc), 606 VERR_TM_UNSTABLE_STATE); 607 tmLock(pVM); 608 continue; 619 609 620 610 /* … … 622 612 */ 623 613 case TMTIMERSTATE_FREE: 624 AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); 625 return VERR_TM_INVALID_STATE; 614 case TMTIMERSTATE_DESTROY: 615 tmUnlock(pVM); 616 AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE); 617 626 618 default: 627 619 AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); 620 tmUnlock(pVM); 628 621 return VERR_TM_UNKNOWN_STATE; 629 622 } 630 } while (cRetries-- > 0); 631 632 AssertMsgFailed(("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, R3STRING(pTimer->pszDesc))); 633 return VERR_INTERNAL_ERROR; 623 624 /* 625 * Try switch to the destroy state. 626 * This should always succeed as the caller should make sure there are no race. 627 */ 628 if (tmTimerTry(pTimer, TMTIMERSTATE_DESTROY, enmState)) 629 break; 630 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc)); 631 tmUnlock(pVM); 632 AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc), 633 VERR_TM_UNSTABLE_STATE); 634 tmLock(pVM); 635 } 636 637 /* 638 * Unlink from the active list. 639 */ 640 if (fActive) 641 { 642 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 643 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 644 if (pPrev) 645 TMTIMER_SET_NEXT(pPrev, pNext); 646 else 647 { 648 TMTIMER_SET_HEAD(pQueue, pNext); 649 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 650 } 651 if (pNext) 652 TMTIMER_SET_PREV(pNext, pPrev); 653 pTimer->offNext = 0; 654 pTimer->offPrev = 0; 655 } 656 657 /* 658 * Unlink from the schedule list by running it. 659 */ 660 if (fPending) 661 { 662 Log3(("TMR3TimerDestroy: tmTimerQueueSchedule\n")); 663 STAM_PROFILE_START(&pVM->tm.s.CTXALLSUFF(StatScheduleOne), a); 664 Assert(pQueue->offSchedule); 665 tmTimerQueueSchedule(pVM, pQueue); 666 } 667 668 /* 669 * Read to move the timer from the created list and onto the free list. 670 */ 671 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); Assert(!pTimer->offScheduleNext); 672 673 /* unlink from created list */ 674 if (pTimer->pBigPrev) 675 pTimer->pBigPrev->pBigNext = pTimer->pBigNext; 676 else 677 pVM->tm.s.pCreated = pTimer->pBigNext; 678 if (pTimer->pBigNext) 679 pTimer->pBigNext->pBigPrev = pTimer->pBigPrev; 680 pTimer->pBigNext = 0; 681 pTimer->pBigPrev = 0; 682 683 /* free */ 684 Log2(("TM: Inserting %p into the free list ahead of %p!\n", pTimer, pVM->tm.s.pFree)); 685 TM_SET_STATE(pTimer, TMTIMERSTATE_FREE); 686 pTimer->pBigNext = pVM->tm.s.pFree; 687 pVM->tm.s.pFree = pTimer; 688 689 #ifdef VBOX_STRICT 690 tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy"); 691 #endif 692 tmUnlock(pVM); 693 return VINF_SUCCESS; 634 694 } 635 695 #endif /* IN_RING3 */ … … 727 787 * Invalid states. 728 788 */ 729 case TMTIMERSTATE_PENDING_DESTROY: 730 case TMTIMERSTATE_PENDING_STOP_DESTROY: 789 case TMTIMERSTATE_DESTROY: 731 790 case TMTIMERSTATE_FREE: 732 791 AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); … … 918 977 * Invalid states. 919 978 */ 920 case TMTIMERSTATE_PENDING_DESTROY: 921 case TMTIMERSTATE_PENDING_STOP_DESTROY: 979 case TMTIMERSTATE_DESTROY: 922 980 case TMTIMERSTATE_FREE: 923 981 AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); … … 1273 1331 * Invalid states. 1274 1332 */ 1275 case TMTIMERSTATE_PENDING_DESTROY: 1276 case TMTIMERSTATE_PENDING_STOP_DESTROY: 1333 case TMTIMERSTATE_DESTROY: 1277 1334 case TMTIMERSTATE_FREE: 1278 1335 AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); … … 1325 1382 * Invalid states. 1326 1383 */ 1327 case TMTIMERSTATE_PENDING_DESTROY: 1328 case TMTIMERSTATE_PENDING_STOP_DESTROY: 1384 case TMTIMERSTATE_DESTROY: 1329 1385 case TMTIMERSTATE_FREE: 1330 1386 AssertMsgFailed(("Invalid timer state %s (%s)\n", tmTimerState(enmState), R3STRING(pTimer->pszDesc))); … … 1362 1418 CASE( 8,PENDING_RESCHEDULE_SET_EXPIRE); 1363 1419 CASE( 9,PENDING_RESCHEDULE); 1364 CASE(10,PENDING_STOP_DESTROY); 1365 CASE(11,PENDING_DESTROY); 1366 CASE(12,FREE); 1420 CASE(10,DESTROY); 1421 CASE(11,FREE); 1367 1422 default: 1368 1423 AssertMsgFailed(("Invalid state enmState=%d\n", enmState)); … … 1496 1551 1497 1552 /* 1498 * Stop & destroy the timer. 1553 * The timer is pending destruction by TMR3TimerDestroy, our caller. 1554 * Nothing to do here. 1499 1555 */ 1500 case TMTIMERSTATE_PENDING_STOP_DESTROY: 1501 { 1502 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1503 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1504 if (pPrev) 1505 TMTIMER_SET_NEXT(pPrev, pNext); 1506 else 1507 { 1508 TMTIMER_SET_HEAD(pQueue, pNext); 1509 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1510 } 1511 if (pNext) 1512 TMTIMER_SET_PREV(pNext, pPrev); 1513 pTimer->offNext = 0; 1514 pTimer->offPrev = 0; 1515 /* fall thru */ 1516 } 1517 1518 /* 1519 * Destroy the timer. 1520 */ 1521 case TMTIMERSTATE_PENDING_DESTROY: 1522 { 1523 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); 1524 PVM pVM = pTimer->CTX_SUFF(pVM); 1525 const PTMTIMER pBigPrev = (PTMTIMER)(pTimer->pBigPrev ? MMHyperR3ToCC(pVM, pTimer->pBigPrev) : NULL); 1526 const PTMTIMER pBigNext = (PTMTIMER)(pTimer->pBigNext ? MMHyperR3ToCC(pVM, pTimer->pBigNext) : NULL); 1527 1528 /* unlink from created list */ 1529 if (pBigPrev) 1530 pBigPrev->pBigNext = pTimer->pBigNext; 1531 else 1532 pVM->tm.s.pCreated = pTimer->pBigNext; 1533 if (pBigNext) 1534 pBigNext->pBigPrev = pTimer->pBigPrev; 1535 pTimer->pBigNext = 0; 1536 pTimer->pBigPrev = 0; 1537 1538 /* free */ 1539 Log2(("TM: Inserting %p into the free list ahead of %p!\n", pTimer, pVM->tm.s.pFree)); 1540 pTimer->pBigNext = pVM->tm.s.pFree; 1541 pVM->tm.s.pFree = (PTMTIMERR3)MMHyperCCToR3(pVM, pTimer); 1542 TM_SET_STATE(pTimer, TMTIMERSTATE_FREE); 1543 return; 1544 } 1556 case TMTIMERSTATE_DESTROY: 1557 break; 1545 1558 1546 1559 /* … … 1642 1655 break; 1643 1656 case TMTIMERSTATE_PENDING_STOP: 1644 case TMTIMERSTATE_PENDING_STOP_DESTROY:1645 1657 case TMTIMERSTATE_PENDING_RESCHEDULE: 1646 1658 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: … … 1669 1681 case TMTIMERSTATE_ACTIVE: 1670 1682 case TMTIMERSTATE_PENDING_STOP: 1671 case TMTIMERSTATE_PENDING_STOP_DESTROY:1672 1683 case TMTIMERSTATE_PENDING_RESCHEDULE: 1673 1684 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: … … 1681 1692 } 1682 1693 1683 case TMTIMERSTATE_PENDING_DESTROY:1684 1694 case TMTIMERSTATE_PENDING_SCHEDULE: 1685 1695 case TMTIMERSTATE_PENDING_STOP_SCHEDULE: … … 1705 1715 1706 1716 /* shouldn't get here! */ 1717 case TMTIMERSTATE_DESTROY: 1707 1718 default: 1708 1719 AssertMsgFailed(("Invalid state enmState=%d %s\n", enmState, tmTimerState(enmState))); -
trunk/src/VBox/VMM/testcase/tstVMM.cpp
r19500 r19537 108 108 && TMTimerIsActive(pTimer)) 109 109 { 110 //rc = TMTimerStop(pTimer);111 //RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerStop: %Rrc\n", rc));110 rc = TMTimerStop(pTimer); 111 RTTEST_CHECK_MSG(hTest, RT_SUCCESS(rc), (hTest, "TMTimerStop: %Rrc\n", rc)); 112 112 } 113 113 else
Note:
See TracChangeset
for help on using the changeset viewer.