- Timestamp:
- May 8, 2009 6:12:33 PM (16 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/TM.cpp
r19537 r19538 1327 1327 1328 1328 return NULL; 1329 } 1330 1331 1332 /** 1333 * Destroy a timer 1334 * 1335 * @returns VBox status. 1336 * @param pTimer Timer handle as returned by one of the create functions. 1337 */ 1338 VMMR3DECL(int) TMR3TimerDestroy(PTMTIMER pTimer) 1339 { 1340 /* 1341 * Be extra careful here. 1342 */ 1343 if (!pTimer) 1344 return VINF_SUCCESS; 1345 AssertPtr(pTimer); 1346 Assert((unsigned)pTimer->enmClock < (unsigned)TMCLOCK_MAX); 1347 1348 PVM pVM = pTimer->CTX_SUFF(pVM); 1349 PTMTIMERQUEUE pQueue = &pVM->tm.s.CTX_SUFF(paTimerQueues)[pTimer->enmClock]; 1350 bool fActive = false; 1351 bool fPending = false; 1352 1353 /* 1354 * The rest of the game happens behind the lock, just 1355 * like create does. All the work is done here. 1356 */ 1357 tmLock(pVM); 1358 for (int cRetries = 1000;; cRetries--) 1359 { 1360 /* 1361 * Change to the DESTROY state. 1362 */ 1363 TMTIMERSTATE enmState = pTimer->enmState; 1364 TMTIMERSTATE enmNewState = enmState; 1365 Log2(("TMTimerDestroy: %p:{.enmState=%s, .pszDesc='%s'} cRetries=%d\n", 1366 pTimer, tmTimerState(enmState), R3STRING(pTimer->pszDesc), cRetries)); 1367 switch (enmState) 1368 { 1369 case TMTIMERSTATE_STOPPED: 1370 case TMTIMERSTATE_EXPIRED: 1371 break; 1372 1373 case TMTIMERSTATE_ACTIVE: 1374 fActive = true; 1375 break; 1376 1377 case TMTIMERSTATE_PENDING_STOP: 1378 case TMTIMERSTATE_PENDING_STOP_SCHEDULE: 1379 case TMTIMERSTATE_PENDING_RESCHEDULE: 1380 fActive = true; 1381 fPending = true; 1382 break; 1383 1384 case TMTIMERSTATE_PENDING_SCHEDULE: 1385 fPending = true; 1386 break; 1387 1388 /* 1389 * This shouldn't happen as the caller should make sure there are no races. 1390 */ 1391 case TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE: 1392 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE: 1393 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc)); 1394 tmUnlock(pVM); 1395 if (!RTThreadYield()) 1396 RTThreadSleep(1); 1397 AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc), 1398 VERR_TM_UNSTABLE_STATE); 1399 tmLock(pVM); 1400 continue; 1401 1402 /* 1403 * Invalid states. 1404 */ 1405 case TMTIMERSTATE_FREE: 1406 case TMTIMERSTATE_DESTROY: 1407 tmUnlock(pVM); 1408 AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE); 1409 1410 default: 1411 AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc))); 1412 tmUnlock(pVM); 1413 return VERR_TM_UNKNOWN_STATE; 1414 } 1415 1416 /* 1417 * Try switch to the destroy state. 1418 * This should always succeed as the caller should make sure there are no race. 1419 */ 1420 bool fRc; 1421 TM_TRY_SET_STATE(pTimer, TMTIMERSTATE_DESTROY, enmState, fRc); 1422 if (fRc) 1423 break; 1424 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc)); 1425 tmUnlock(pVM); 1426 AssertMsgReturn(cRetries > 0, ("Failed waiting for stable state. state=%d (%s)\n", pTimer->enmState, pTimer->pszDesc), 1427 VERR_TM_UNSTABLE_STATE); 1428 tmLock(pVM); 1429 } 1430 1431 /* 1432 * Unlink from the active list. 1433 */ 1434 if (fActive) 1435 { 1436 const PTMTIMER pPrev = TMTIMER_GET_PREV(pTimer); 1437 const PTMTIMER pNext = TMTIMER_GET_NEXT(pTimer); 1438 if (pPrev) 1439 TMTIMER_SET_NEXT(pPrev, pNext); 1440 else 1441 { 1442 TMTIMER_SET_HEAD(pQueue, pNext); 1443 pQueue->u64Expire = pNext ? pNext->u64Expire : INT64_MAX; 1444 } 1445 if (pNext) 1446 TMTIMER_SET_PREV(pNext, pPrev); 1447 pTimer->offNext = 0; 1448 pTimer->offPrev = 0; 1449 } 1450 1451 /* 1452 * Unlink from the schedule list by running it. 1453 */ 1454 if (fPending) 1455 { 1456 Log3(("TMR3TimerDestroy: tmTimerQueueSchedule\n")); 1457 STAM_PROFILE_START(&pVM->tm.s.CTXALLSUFF(StatScheduleOne), a); 1458 Assert(pQueue->offSchedule); 1459 tmTimerQueueSchedule(pVM, pQueue); 1460 } 1461 1462 /* 1463 * Read to move the timer from the created list and onto the free list. 1464 */ 1465 Assert(!pTimer->offNext); Assert(!pTimer->offPrev); Assert(!pTimer->offScheduleNext); 1466 1467 /* unlink from created list */ 1468 if (pTimer->pBigPrev) 1469 pTimer->pBigPrev->pBigNext = pTimer->pBigNext; 1470 else 1471 pVM->tm.s.pCreated = pTimer->pBigNext; 1472 if (pTimer->pBigNext) 1473 pTimer->pBigNext->pBigPrev = pTimer->pBigPrev; 1474 pTimer->pBigNext = 0; 1475 pTimer->pBigPrev = 0; 1476 1477 /* free */ 1478 Log2(("TM: Inserting %p into the free list ahead of %p!\n", pTimer, pVM->tm.s.pFree)); 1479 TM_SET_STATE(pTimer, TMTIMERSTATE_FREE); 1480 pTimer->pBigNext = pVM->tm.s.pFree; 1481 pVM->tm.s.pFree = pTimer; 1482 1483 #ifdef VBOX_STRICT 1484 tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy"); 1485 #endif 1486 tmUnlock(pVM); 1487 return VINF_SUCCESS; 1329 1488 } 1330 1489 -
trunk/src/VBox/VMM/VMMAll/TMAll.cpp
r19537 r19538 535 535 return (PTMTIMERRC)MMHyperCCToRC(pTimer->CTX_SUFF(pVM), pTimer); 536 536 } 537 538 539 #ifdef IN_RING3 /* Kept here until properly cleaned up to not use any of the local functions. */540 /**541 * Destroy a timer542 *543 * @returns VBox status.544 * @param pTimer Timer handle as returned by one of the create functions.545 */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, just563 * like create does. All the work is done here.564 */565 tmLock(pVM);566 for (int cRetries = 1000;; cRetries--)567 {568 /*569 * Change to the DESTROY state.570 */571 TMTIMERSTATE enmState = pTimer->enmState;572 TMTIMERSTATE enmNewState = enmState;573 Log2(("TMTimerDestroy: %p:{.enmState=%s, .pszDesc='%s'} cRetries=%d\n",574 pTimer, tmTimerState(enmState), R3STRING(pTimer->pszDesc), cRetries));575 switch (enmState)576 {577 case TMTIMERSTATE_STOPPED:578 case TMTIMERSTATE_EXPIRED:579 break;580 581 case TMTIMERSTATE_ACTIVE:582 fActive = true;583 break;584 585 case TMTIMERSTATE_PENDING_STOP:586 case TMTIMERSTATE_PENDING_STOP_SCHEDULE:587 case TMTIMERSTATE_PENDING_RESCHEDULE:588 fActive = true;589 fPending = true;590 break;591 592 case TMTIMERSTATE_PENDING_SCHEDULE:593 fPending = true;594 break;595 596 /*597 * This shouldn't happen as the caller should make sure there are no races.598 */599 case TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE:600 case TMTIMERSTATE_PENDING_RESCHEDULE_SET_EXPIRE:601 AssertMsgFailed(("%p:.enmState=%s %s\n", pTimer, tmTimerState(enmState), pTimer->pszDesc));602 tmUnlock(pVM);603 if (!RTThreadYield())604 RTThreadSleep(1);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;609 610 /*611 * Invalid states.612 */613 case TMTIMERSTATE_FREE:614 case TMTIMERSTATE_DESTROY:615 tmUnlock(pVM);616 AssertLogRelMsgFailedReturn(("pTimer=%p %s\n", pTimer, tmTimerState(enmState)), VERR_TM_INVALID_STATE);617 618 default:619 AssertMsgFailed(("Unknown timer state %d (%s)\n", enmState, R3STRING(pTimer->pszDesc)));620 tmUnlock(pVM);621 return VERR_TM_UNKNOWN_STATE;622 }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 else647 {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 else677 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_STRICT690 tmTimerQueuesSanityChecks(pVM, "TMR3TimerDestroy");691 #endif692 tmUnlock(pVM);693 return VINF_SUCCESS;694 }695 #endif /* IN_RING3 */696 537 697 538
Note:
See TracChangeset
for help on using the changeset viewer.