VirtualBox

Changeset 19537 in vbox for trunk/src/VBox/VMM


Ignore:
Timestamp:
May 8, 2009 6:09:57 PM (16 years ago)
Author:
vboxsync
Message:

TMR3TimerDestroy: rewrite to ring-3 only.

Location:
trunk/src/VBox/VMM
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/TM.cpp

    r19507 r19537  
    19571957
    19581958        case TMTIMERSTATE_EXPIRED:
    1959         case TMTIMERSTATE_PENDING_DESTROY:
    1960         case TMTIMERSTATE_PENDING_STOP_DESTROY:
     1959        case TMTIMERSTATE_DESTROY:
    19611960        case TMTIMERSTATE_FREE:
    19621961            AssertMsgFailed(("Invalid timer state %d %s (%s)\n", pTimer->enmState, tmTimerState(pTimer->enmState), pTimer->pszDesc));
  • trunk/src/VBox/VMM/TMInternal.h

    r19499 r19537  
    9191     * Currently in the ScheduleTimers list and the active list. */
    9292    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,
    10095    /** Timer is free. */
    10196    TMTIMERSTATE_FREE
  • trunk/src/VBox/VMM/VMMAll/TMAll.cpp

    r19507 r19537  
    544544 * @param   pTimer          Timer handle as returned by one of the create functions.
    545545 */
    546 VMMR3DECL(int) TMR3TimerDestroy(PTMTIMER pTimer)
    547 {
    548     int cRetries = 1000;
    549     do
     546VMMR3DECL(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--)
    550567    {
    551568        /*
    552          * Change to any of the DESTROY states if valid.
     569         * Change to the DESTROY state.
    553570         */
    554         TMTIMERSTATE enmState = pTimer->enmState;
     571        TMTIMERSTATE enmState    = pTimer->enmState;
     572        TMTIMERSTATE enmNewState = enmState;
    555573        Log2(("TMTimerDestroy: %p:{.enmState=%s, .pszDesc='%s'} cRetries=%d\n",
    556574              pTimer, tmTimerState(enmState), R3STRING(pTimer->pszDesc), cRetries));
    557575        switch (enmState)
    558576        {
     577            case TMTIMERSTATE_STOPPED:
    559578            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                 }
    572579                break;
    573580
    574581            case TMTIMERSTATE_ACTIVE:
    575                 if (tmTimerTryWithLink(pTimer, TMTIMERSTATE_PENDING_STOP_DESTROY, enmState))
    576                 {
    577                     tmSchedule(pTimer);
    578                     return VINF_SUCCESS;
    579                 }
     582                fActive     = true;
    580583                break;
    581584
    582585            case TMTIMERSTATE_PENDING_STOP:
    583586            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;
    589590                break;
    590591
    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;
    602594                break;
    603595
    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             */
    612599            case TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE:
    613600            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);
    615603                if (!RTThreadYield())
    616604                    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;
    619609
    620610            /*
     
    622612             */
    623613            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
    626618            default:
    627619                AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc)));
     620                tmUnlock(pVM);
    628621                return VERR_TM_UNKNOWN_STATE;
    629622        }
    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;
    634694}
    635695#endif /* IN_RING3 */
     
    727787             * Invalid states.
    728788             */
    729             case TMTIMERSTATE_PENDING_DESTROY:
    730             case TMTIMERSTATE_PENDING_STOP_DESTROY:
     789            case TMTIMERSTATE_DESTROY:
    731790            case TMTIMERSTATE_FREE:
    732791                AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc)));
     
    918977             * Invalid states.
    919978             */
    920             case TMTIMERSTATE_PENDING_DESTROY:
    921             case TMTIMERSTATE_PENDING_STOP_DESTROY:
     979            case TMTIMERSTATE_DESTROY:
    922980            case TMTIMERSTATE_FREE:
    923981                AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc)));
     
    12731331             * Invalid states.
    12741332             */
    1275             case TMTIMERSTATE_PENDING_DESTROY:
    1276             case TMTIMERSTATE_PENDING_STOP_DESTROY:
     1333            case TMTIMERSTATE_DESTROY:
    12771334            case TMTIMERSTATE_FREE:
    12781335                AssertMsgFailed(("Invalid timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc)));
     
    13251382         * Invalid states.
    13261383         */
    1327         case TMTIMERSTATE_PENDING_DESTROY:
    1328         case TMTIMERSTATE_PENDING_STOP_DESTROY:
     1384        case TMTIMERSTATE_DESTROY:
    13291385        case TMTIMERSTATE_FREE:
    13301386            AssertMsgFailed(("Invalid timer state %s (%s)\n", tmTimerState(enmState), R3STRING(pTimer->pszDesc)));
     
    13621418        CASE( 8,PENDING_RESCHEDULE_SET_EXPIRE);
    13631419        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);
    13671422        default:
    13681423            AssertMsgFailed(("Invalid state enmState=%d\n", enmState));
     
    14961551
    14971552            /*
    1498              * Stop & destroy the timer.
     1553             * The timer is pending destruction by TMR3TimerDestroy, our caller.
     1554             * Nothing to do here.
    14991555             */
    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;
    15451558
    15461559            /*
     
    16421655                    break;
    16431656                case TMTIMERSTATE_PENDING_STOP:
    1644                 case TMTIMERSTATE_PENDING_STOP_DESTROY:
    16451657                case TMTIMERSTATE_PENDING_RESCHEDULE:
    16461658                case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:
     
    16691681            case TMTIMERSTATE_ACTIVE:
    16701682            case TMTIMERSTATE_PENDING_STOP:
    1671             case TMTIMERSTATE_PENDING_STOP_DESTROY:
    16721683            case TMTIMERSTATE_PENDING_RESCHEDULE:
    16731684            case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:
     
    16811692            }
    16821693
    1683             case TMTIMERSTATE_PENDING_DESTROY:
    16841694            case TMTIMERSTATE_PENDING_SCHEDULE:
    16851695            case TMTIMERSTATE_PENDING_STOP_SCHEDULE:
     
    17051715
    17061716            /* shouldn't get here! */
     1717            case TMTIMERSTATE_DESTROY:
    17071718            default:
    17081719                AssertMsgFailed(("Invalid state enmState=%d %s\n", enmState, tmTimerState(enmState)));
  • trunk/src/VBox/VMM/testcase/tstVMM.cpp

    r19500 r19537  
    108108                &&  TMTimerIsActive(pTimer))
    109109            {
    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));
    112112            }
    113113            else
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette