Changeset 20750 in vbox
- Timestamp:
- Jun 21, 2009 9:14:52 PM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 48866
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vm.h
r20663 r20750 926 926 struct TM s; 927 927 #endif 928 char padding[ 1920]; /* multiple of 32 */928 char padding[2048]; /* multiple of 32 */ 929 929 } tm; 930 930 -
trunk/src/VBox/VMM/TM.cpp
r20733 r20750 578 578 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRZ, STAMTYPE_PROFILE, "/TM/TimerSetRZ", STAMUNIT_TICKS_PER_CALL, "Profiling TMTimerSet calls made in ring-0 / RC."); 579 579 580 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeR3, STAMTYPE_PROFILE, "/TM/TimerSetRelativeR3", STAMUNIT_TICKS_PER_CALL, "Profiling TMTimerSetRelative calls made in ring-3."); 581 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeRZ, STAMTYPE_PROFILE, "/TM/TimerSetRelativeRZ", STAMUNIT_TICKS_PER_CALL, "Profiling TMTimerSetReltaive calls made in ring-0 / RC."); 580 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelative, STAMTYPE_COUNTER, "/TM/TimerSetRelative", STAMUNIT_OCCURENCES, "Calls"); 581 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeR3, STAMTYPE_PROFILE, "/TM/TimerSetRelative/R3", STAMUNIT_TICKS_PER_CALL, "Profiling TMTimerSetRelative calls made in ring-3."); 582 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeRZ, STAMTYPE_PROFILE, "/TM/TimerSetRelative/RZ", STAMUNIT_TICKS_PER_CALL, "Profiling TMTimerSetReltaive calls made in ring-0 / RC."); 583 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeRacyVirtSync, STAMTYPE_COUNTER, "/TM/TimerSetRelative/RacyVirtSync", STAMUNIT_OCCURENCES, "Potentially racy virtual sync timer update."); 584 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeOpt, STAMTYPE_COUNTER, "/TM/TimerSetRelative/Opt", STAMUNIT_OCCURENCES, "Optimized path taken."); 585 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStActive, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StActive", STAMUNIT_OCCURENCES, "ACTIVE"); 586 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStExpDeliver, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StExpDeliver", STAMUNIT_OCCURENCES, "EXPIRED_DELIVER"); 587 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStOther, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StOther", STAMUNIT_OCCURENCES, "Other states"); 588 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStPendStop, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StPendStop", STAMUNIT_OCCURENCES, "PENDING_STOP"); 589 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStPendStopSched, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StPendStopSched",STAMUNIT_OCCURENCES, "PENDING_STOP_SCHEDULE"); 590 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStPendSched, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StPendSched", STAMUNIT_OCCURENCES, "PENDING_SCHEDULE"); 591 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStPendResched, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StPendResched", STAMUNIT_OCCURENCES, "PENDING_RESCHEDULE"); 592 STAM_REG(pVM, &pVM->tm.s.StatTimerSetRelativeStStopped, STAMTYPE_COUNTER, "/TM/TimerSetRelative/StStopped", STAMUNIT_OCCURENCES, "STOPPED"); 582 593 583 594 STAM_REG(pVM, &pVM->tm.s.StatTimerStopR3, STAMTYPE_PROFILE, "/TM/TimerStopR3", STAMUNIT_TICKS_PER_CALL, "Profiling TMTimerStop calls made in ring-3."); -
trunk/src/VBox/VMM/TMInternal.h
r20733 r20750 487 487 /** TMTimerSetRelative 488 488 * @{ */ 489 STAMCOUNTER StatTimerSetRelative; 489 490 STAMPROFILE StatTimerSetRelativeRZ; 490 491 STAMPROFILE StatTimerSetRelativeR3; 492 STAMCOUNTER StatTimerSetRelativeOpt; 493 STAMCOUNTER StatTimerSetRelativeRacyVirtSync; 494 STAMCOUNTER StatTimerSetRelativeStStopped; 495 STAMCOUNTER StatTimerSetRelativeStExpDeliver; 496 STAMCOUNTER StatTimerSetRelativeStActive; 497 STAMCOUNTER StatTimerSetRelativeStPendStop; 498 STAMCOUNTER StatTimerSetRelativeStPendStopSched; 499 STAMCOUNTER StatTimerSetRelativeStPendSched; 500 STAMCOUNTER StatTimerSetRelativeStPendResched; 501 STAMCOUNTER StatTimerSetRelativeStOther; 491 502 /** @} */ 492 503 /** TMTimerStop -
trunk/src/VBox/VMM/VMMAll/TMAll.cpp
r20733 r20750 743 743 744 744 /** 745 * Links a timer into the active list of a timer queue. 746 * 747 * The caller must have taken the TM semaphore before calling this function. 748 * 749 * @param pQueue The queue. 750 * @param pTimer The timer. 751 * @param u64Expire The timer expiration time. 752 */ 753 DECL_FORCE_INLINE(void) tmTimerActiveLink(PTMTIMERQUEUE pQueue, PTMTIMER pTimer, uint64_t u64Expire) 754 { 755 PTMTIMER pCur = TMTIMER_GET_HEAD(pQueue); 756 if (pCur) 757 { 758 for (;; pCur = TMTIMER_GET_NEXT(pCur)) 759 { 760 if (pCur->u64Expire > u64Expire) 761 { 762 const PTMTIMER pPrev = TMTIMER_GET_PREV(pCur); 763 TMTIMER_SET_NEXT(pTimer, pCur); 764 TMTIMER_SET_PREV(pTimer, pPrev); 765 if (pPrev) 766 TMTIMER_SET_NEXT(pPrev, pTimer); 767 else 768 { 769 TMTIMER_SET_HEAD(pQueue, pTimer); 770 pQueue->u64Expire = u64Expire; 771 } 772 TMTIMER_SET_PREV(pCur, pTimer); 773 return; 774 } 775 if (!pCur->offNext) 776 { 777 TMTIMER_SET_NEXT(pCur, pTimer); 778 TMTIMER_SET_PREV(pTimer, pCur); 779 return; 780 } 781 } 782 } 783 else 784 { 785 TMTIMER_SET_HEAD(pQueue, pTimer); 786 pQueue->u64Expire = u64Expire; 787 } 788 } 789 790 791 /** 745 792 * Arm a timer with a (new) expire time. 746 793 * … … 884 931 885 932 /** 933 * Optimized TMTimerSetRelative code path. 934 * 935 * @returns VBox status code. 936 * 937 * @param pVM The VM handle. 938 * @param pTimer The timer handle. 939 * @param cTicksToNext Clock ticks until the next time expiration. 940 * @param pu64Now Where to return the current time stamp used. 941 * Optional. 942 */ 943 static int tmTimerSetRelativeOptimizedStart(PVM pVM, PTMTIMER pTimer, uint64_t cTicksToNext, uint64_t *pu64Now) 944 { 945 Assert(!pTimer->offPrev); 946 Assert(!pTimer->offNext); 947 Assert(pTimer->enmState == TMTIMERSTATE_ACTIVE); 948 949 /* 950 * Calculate and set the expiration time. 951 */ 952 TMCLOCK const enmClock = pTimer->enmClock; 953 uint64_t const u64Expire = cTicksToNext + tmTimerSetRelativeNowWorker(pVM, enmClock, pu64Now); 954 pTimer->u64Expire = u64Expire; 955 Log2(("tmTimerSetRelativeOptimizedStart: %p:{.pszDesc='%s', .u64Expire=%'RU64} cTicksToNext=%'RU64\n", pTimer, R3STRING(pTimer->pszDesc), u64Expire, cTicksToNext)); 956 957 /* 958 * Link the timer into the active list. 959 */ 960 tmTimerActiveLink(&pVM->tm.s.CTX_SUFF(paTimerQueues)[enmClock], pTimer, u64Expire); 961 962 STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeOpt); 963 tmUnlock(pVM); 964 return VINF_SUCCESS; 965 } 966 967 968 /** 886 969 * Arm a timer with a expire time relative to the current time. 887 970 * … … 896 979 STAM_PROFILE_START(&pTimer->CTX_SUFF(pVM)->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a); 897 980 TMTIMER_ASSERT_CRITSECT(pTimer); 898 PVM pVM = pTimer->CTX_SUFF(pVM); 899 TMCLOCK enmClock = pTimer->enmClock; 900 bool fOwnLock = false; 901 int rc; 902 903 /** @todo find the most frequently used paths and make them skip tmSchedule and tmTimerTryWithLink. */ 981 PVM pVM = pTimer->CTX_SUFF(pVM); 982 int rc; 983 984 #ifdef VBOX_WITH_STATISTICS 985 /* Gather optimization info. */ 986 STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelative); 987 TMTIMERSTATE enmOrgState = pTimer->enmState; 988 switch (enmOrgState) 989 { 990 case TMTIMERSTATE_STOPPED: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStStopped); break; 991 case TMTIMERSTATE_EXPIRED_DELIVER: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStExpDeliver); break; 992 case TMTIMERSTATE_ACTIVE: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStActive); break; 993 case TMTIMERSTATE_PENDING_STOP: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStPendStop); break; 994 case TMTIMERSTATE_PENDING_STOP_SCHEDULE: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStPendStopSched); break; 995 case TMTIMERSTATE_PENDING_SCHEDULE: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStPendSched); break; 996 case TMTIMERSTATE_PENDING_RESCHEDULE: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStPendResched); break; 997 default: STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeStOther); break; 998 } 999 #endif 1000 1001 /* 1002 * Try to take the TM lock and optimize the common cases. 1003 * 1004 * With the TM lock we can safely make optimizations like immediate 1005 * scheduling and we can also be 100% sure that we're not racing the 1006 * running of the timer queues. As an additional restraint we require the 1007 * timer to have a critical section associated with to be 100% there aren't 1008 * concurrent operations on the timer. (This latter isn't necessary any 1009 * longer as this isn't supported for any timers, critsect or not.) 1010 * 1011 * Note! Lock ordering doesn't apply when we only tries to 1012 * get the innermost locks. 1013 */ 1014 bool fOwnTMLock = RT_SUCCESS(tmTryLock(pVM)); 1015 #if 1 1016 if ( fOwnTMLock 1017 && pTimer->pCritSect) 1018 { 1019 TMTIMERSTATE enmState = pTimer->enmState; 1020 if (RT_LIKELY( ( enmState == TMTIMERSTATE_EXPIRED_DELIVER 1021 || enmState == TMTIMERSTATE_STOPPED) 1022 && tmTimerTry(pTimer, TMTIMERSTATE_ACTIVE, enmState))) 1023 { 1024 tmTimerSetRelativeOptimizedStart(pVM, pTimer, cTicksToNext, pu64Now); 1025 STAM_PROFILE_STOP(&pTimer->CTX_SUFF(pVM)->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a); 1026 return VINF_SUCCESS; 1027 } 1028 1029 /* Optimize other states when it becomes necessary. */ 1030 } 1031 #endif 1032 1033 /* 1034 * Unoptimized path. 1035 */ 1036 TMCLOCK const enmClock = pTimer->enmClock; 1037 bool fOwnVirtSyncLock; 1038 fOwnVirtSyncLock = !fOwnTMLock 1039 && enmClock == TMCLOCK_VIRTUAL_SYNC 1040 && RT_SUCCESS(tmVirtualSyncTryLock(pVM)); 904 1041 for (int cRetries = 1000; ; cRetries--) 905 1042 { 906 /*907 * Try to take the appropriate lock to increase the likelyhood908 * that we don't race timer queue running and to some extend909 * clock queries.910 */911 if (!fOwnLock)912 {913 if (enmClock == TMCLOCK_VIRTUAL_SYNC)914 fOwnLock = RT_SUCCESS(tmVirtualSyncTryLock(pVM));915 else916 fOwnLock = RT_SUCCESS(tmTryLock(pVM));917 }918 919 1043 /* 920 1044 * Change to any of the SET_EXPIRE states if valid and then to SCHEDULE or RESCHEDULE. 921 1045 */ 922 TMTIMERSTATE 1046 TMTIMERSTATE enmState = pTimer->enmState; 923 1047 switch (enmState) 924 1048 { 1049 case TMTIMERSTATE_STOPPED: 1050 if (tmClock == TMCLOCK_VIRTUAL_SYNC) 1051 { 1052 /** @todo To fix assertion in tmR3TimerQueueRunVirtualSync: 1053 * Figure a safe way of activating this timer while the queue is 1054 * being run. 1055 * (99.9% sure this that the assertion is caused by DevAPIC.cpp 1056 * re-starting the timer in respons to a initial_count write.) */ 1057 } 1058 /* fall thru */ 925 1059 case TMTIMERSTATE_EXPIRED_DELIVER: 926 case TMTIMERSTATE_STOPPED:927 1060 if (tmTimerTryWithLink(pTimer, TMTIMERSTATE_PENDING_SCHEDULE_SET_EXPIRE, enmState)) 928 1061 { … … 1029 1162 break; 1030 1163 } 1164 1165 /* 1166 * Retry to gain locks. 1167 */ 1168 if (!fOwnTMLock) 1169 { 1170 fOwnTMLock = RT_SUCCESS(tmTryLock(pVM)); 1171 if ( !fOwnTMLock 1172 && enmClock == TMCLOCK_VIRTUAL_SYNC 1173 && !fOwnVirtSyncLock) 1174 fOwnVirtSyncLock = RT_SUCCESS(tmVirtualSyncTryLock(pVM)); 1175 } 1176 1031 1177 } /* for (;;) */ 1032 1178 … … 1034 1180 * Clean up and return. 1035 1181 */ 1036 if (fOwnLock) 1037 { 1038 if (enmClock == TMCLOCK_VIRTUAL_SYNC) 1039 tmVirtualSyncUnlock(pVM); 1040 else 1041 tmUnlock(pVM); 1042 } 1182 if (fOwnVirtSyncLock) 1183 tmVirtualSyncUnlock(pVM); 1184 if (fOwnTMLock) 1185 tmUnlock(pVM); 1186 1187 if ( !fOwnTMLock 1188 && !fOwnVirtSyncLock 1189 && enmClock == TMCLOCK_VIRTUAL_SYNC) 1190 STAM_COUNTER_INC(&pVM->tm.s.StatTimerSetRelativeRacyVirtSync); 1043 1191 1044 1192 STAM_PROFILE_STOP(&pTimer->CTX_SUFF(pVM)->tm.s.CTX_SUFF_Z(StatTimerSetRelative), a);
Note:
See TracChangeset
for help on using the changeset viewer.