Changeset 32737 in vbox for trunk/src/VBox/Runtime
- Timestamp:
- Sep 23, 2010 4:20:05 PM (14 years ago)
- svn:sync-xref-src-repo-rev:
- 66176
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/linux/timer-r0drv-linux.c
r32711 r32737 123 123 /** The start of the current run (ns). 124 124 * This is used to calculate when the timer ought to fire the next time. */ 125 uint64_t u64StartTS;126 /** The start of the current run (ns).127 * This is used to calculate when the timer ought to fire the next time. */128 125 uint64_t u64NextTS; 129 126 /** The u64NextTS in jiffies. */ 130 127 unsigned long ulNextJiffies; 128 /** Set when starting or changing the timer so that u64StartTs 129 * and u64NextTS gets reinitialized (eliminating some jitter). */ 130 bool volatile fFirstAfterChg; 131 131 } Std; 132 132 } u; 133 /** The current tick number (since u.Std.u64StartTS). */133 /** The current tick number. */ 134 134 uint64_t iTick; 135 135 /** Restart the single shot timer at this specific time. … … 179 179 /** This is set to the number of jiffies between ticks if the interval is 180 180 * an exact number of jiffies. (Standard timers only.) */ 181 unsigned long cJiffies; 181 unsigned long volatile cJiffies; 182 /** The change interval spinlock for standard timers only. */ 183 spinlock_t ChgIntLock; 182 184 /** Sub-timers. 183 185 * Normally there is just one, but for RTTIMER_FLAGS_CPU_ALL this will contain … … 193 195 typedef struct RTTIMERLINUXSTARTONCPUARGS 194 196 { 195 /** The current time (RTTime NanoTS). */197 /** The current time (RTTimeSystemNanoTS). */ 196 198 uint64_t u64Now; 197 199 /** When to start firing (delta). */ … … 284 286 * Converts a nano second time stamp to ktime_t. 285 287 * 286 * ASSUMES RTTime NanoTS() is implemented using ktime_get_ts().288 * ASSUMES RTTimeSystemNanoTS() is implemented using ktime_get_ts(). 287 289 * 288 290 * @returns ktime_t. … … 298 300 * Converts ktime_t to a nano second time stamp. 299 301 * 300 * ASSUMES RTTime NanoTS() is implemented using ktime_get_ts().302 * ASSUMES RTTimeSystemNanoTS() is implemented using ktime_get_ts(). 301 303 * 302 304 * @returns nano second time stamp. … … 333 335 * 334 336 * @param pSubTimer The sub-timer to start. 335 * @param u64Now The current timestamp (RTTime NanoTS()).337 * @param u64Now The current timestamp (RTTimeSystemNanoTS()). 336 338 * @param u64First The interval from u64Now to the first time the timer should fire. 337 339 * @param fPinned true = timer pinned to a specific CPU, … … 348 350 uint64_t u64NextTS = u64Now + u64First; 349 351 if (fHighRes) 350 { 351 pSubTimer->u.Std.u64StartTS = u64NextTS; 352 pSubTimer->u.Std.u64NextTS = u64NextTS; 353 } 352 pSubTimer->u.Std.u64NextTS = u64NextTS; 354 353 dprintf(("startsubtimer %p\n", pSubTimer->pParent)); 355 354 … … 364 363 { 365 364 unsigned long cJiffies = !u64First ? 0 : rtTimerLnxNanoToJiffies(u64First); 366 pSubTimer->u.Std.ulNextJiffies = jiffies + cJiffies; 365 pSubTimer->u.Std.ulNextJiffies = jiffies + cJiffies; 366 pSubTimer->u.Std.fFirstAfterChg = true; 367 367 #ifdef CONFIG_SMP 368 368 if (fPinned) … … 697 697 { 698 698 /* 699 * Interval timer, calculate the next timeout and re-arm it.699 * Interval timer, calculate the next timeout. 700 700 * 701 * The first time around, we'll re-adjust the u.Std.u64 StartTS to701 * The first time around, we'll re-adjust the u.Std.u64NextTS to 702 702 * try prevent some jittering if we were started at a bad time. 703 703 */ 704 const uint64_t u64NanoInterval = pTimer->u64NanoInterval; 705 const uint64_t iTick = ++pSubTimer->iTick; 706 const uint64_t u64NanoTS = RTTimeNanoTS(); 707 708 if (RT_UNLIKELY(iTick == 1)) 709 { 710 pSubTimer->u.Std.u64StartTS = u64NanoTS; 711 pSubTimer->u.Std.u64NextTS = u64NanoTS; 712 pSubTimer->u.Std.ulNextJiffies = jiffies; 713 } 704 const uint64_t iTick = ++pSubTimer->iTick; 705 uint64_t u64NanoInterval; 706 unsigned long cJiffies; 707 unsigned long flFlags; 708 709 spin_lock_irqsave(&pTimer->ChgIntLock, flFlags); 710 u64NanoInterval = pTimer->u64NanoInterval; 711 cJiffies = pTimer->cJiffies; 712 if (RT_UNLIKELY(pSubTimer->u.Std.fFirstAfterChg)) 713 { 714 pSubTimer->u.Std.fFirstAfterChg = false; 715 pSubTimer->u.Std.u64NextTS = RTTimeSystemNanoTS(); 716 pSubTimer->u.Std.ulNextJiffies = jiffies; 717 } 718 spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags); 714 719 715 720 pSubTimer->u.Std.u64NextTS += u64NanoInterval; 716 if ( pTimer->cJiffies)717 { 718 pSubTimer->u.Std.ulNextJiffies += pTimer->cJiffies;721 if (cJiffies) 722 { 723 pSubTimer->u.Std.ulNextJiffies += cJiffies; 719 724 /* Prevent overflows when the jiffies counter wraps around. 720 725 * Special thanks to Ken Preslan for helping debugging! */ 721 726 while (time_before(pSubTimer->u.Std.ulNextJiffies, jiffies)) 722 727 { 723 pSubTimer->u.Std.ulNextJiffies += pTimer->cJiffies;728 pSubTimer->u.Std.ulNextJiffies += cJiffies; 724 729 pSubTimer->u.Std.u64NextTS += u64NanoInterval; 725 730 } … … 727 732 else 728 733 { 734 const uint64_t u64NanoTS = RTTimeSystemNanoTS(); 729 735 while (pSubTimer->u.Std.u64NextTS < u64NanoTS) 730 736 pSubTimer->u.Std.u64NextTS += u64NanoInterval; … … 732 738 } 733 739 734 #ifdef CONFIG_SMP735 if (pTimer->fSpecificCpu || pTimer->fAllCpus)736 mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);737 else738 #endif739 mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies);740 741 740 /* 742 * Run the timer. 741 * Run the timer and re-arm it unless the state changed . 742 * . 743 * We must re-arm it afterwards as we're not in a position to undo this . 744 * operation if for instance someone stopped or destroyed us while we . 745 * were in the callback. (Linux takes care of any races here.) 743 746 */ 744 747 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 745 748 if (RT_LIKELY(rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_CALLBACK))) 749 { 750 #ifdef CONFIG_SMP 751 if (pTimer->fSpecificCpu || pTimer->fAllCpus) 752 mod_timer_pinned(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies); 753 else 754 #endif 755 mod_timer(&pSubTimer->u.Std.LnxTimer, pSubTimer->u.Std.ulNextJiffies); 746 756 return; 757 } 747 758 } 748 759 else … … 762 773 * Some state change occured while we were in the callback routine. 763 774 */ 764 if (pTimer->u64NanoInterval)765 del_timer_sync(&pSubTimer->u.Std.LnxTimer);766 775 for (;;) 767 776 { … … 781 790 if (rtTimerLnxCmpXchgState(&pSubTimer->enmState, RTTIMERLNXSTATE_ACTIVE, RTTIMERLNXSTATE_CB_RESTARTING)) 782 791 { 783 const uint64_t u64NanoTS = RTTimeNanoTS(); 784 const uint64_t u64NextTS = pSubTimer->uNsRestartAt; 785 if (pTimer->fHighRes) 786 { 787 pSubTimer->u.Std.u64StartTS = u64NextTS; 788 pSubTimer->u.Std.u64NextTS = u64NextTS; 789 } 790 pSubTimer->iTick = 0; 791 pSubTimer->u.Std.ulNextJiffies = u64NextTS > u64NanoTS 792 ? jiffies + rtTimerLnxNanoToJiffies(u64NextTS - u64NanoTS) 793 : jiffies; 792 uint64_t u64NanoTS; 793 uint64_t u64NextTS; 794 unsigned long flFlags; 795 796 spin_lock_irqsave(&pTimer->ChgIntLock, flFlags); 797 u64NextTS = pSubTimer->uNsRestartAt; 798 u64NanoTS = RTTimeSystemNanoTS(); 799 pSubTimer->iTick = 0; 800 pSubTimer->u.Std.u64NextTS = u64NextTS; 801 pSubTimer->u.Std.fFirstAfterChg = true; 802 pSubTimer->u.Std.ulNextJiffies = u64NextTS > u64NanoTS 803 ? jiffies + rtTimerLnxNanoToJiffies(u64NextTS - u64NanoTS) 804 : jiffies; 805 spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags); 806 794 807 #ifdef CONFIG_SMP 795 808 if (pTimer->fSpecificCpu || pTimer->fAllCpus) … … 881 894 * do this without the cross calls). 882 895 */ 883 pArgs->u64Now = RTTime NanoTS();896 pArgs->u64Now = RTTimeSystemNanoTS(); 884 897 rc2 = RTMpOnAll(rtTimerLnxStartAllOnCpu, pTimer, pArgs); 885 898 AssertRC(rc2); /* screw this if it fails. */ … … 1054 1067 { 1055 1068 RTTIMERLINUXSTARTONCPUARGS Args; 1056 Args.u64Now = RTTime NanoTS();1069 Args.u64Now = RTTimeSystemNanoTS(); 1057 1070 Args.u64First = 0; 1058 1071 … … 1153 1166 * Simple timer - Pretty straight forward if it wasn't for restarting. 1154 1167 */ 1155 Args.u64Now = RTTime NanoTS();1168 Args.u64Now = RTTimeSystemNanoTS(); 1156 1169 ASMAtomicWriteU64(&pTimer->aSubTimers[0].uNsRestartAt, Args.u64Now + u64First); 1157 1170 for (;;) … … 1229 1242 { 1230 1243 case RTTIMERLNXSTATE_ACTIVE: 1231 if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState, RTTIMERLNXSTATE_ MP_STOPPING, RTTIMERLNXSTATE_ACTIVE))1244 if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState, RTTIMERLNXSTATE_STOPPING, RTTIMERLNXSTATE_ACTIVE)) 1232 1245 { 1233 1246 rtTimerLnxStopSubTimer(&pTimer->aSubTimers[0], pTimer->fHighRes); … … 1241 1254 Assert(enmState != RTTIMERLNXSTATE_CB_STOPPING || fForDestroy); 1242 1255 if (rtTimerLnxCmpXchgState(&pTimer->aSubTimers[0].enmState, 1243 !fForDestroy ? RTTIMERLNXSTATE_ STOPPED: RTTIMERLNXSTATE_CB_DESTROYING,1256 !fForDestroy ? RTTIMERLNXSTATE_CB_STOPPING : RTTIMERLNXSTATE_CB_DESTROYING, 1244 1257 enmState)) 1245 1258 return true; … … 1288 1301 RTDECL(int) RTTimerChangeInterval(PRTTIMER pTimer, uint64_t u64NanoInterval) 1289 1302 { 1303 unsigned long cJiffies; 1304 unsigned long flFlags; 1305 1290 1306 /* 1291 1307 * Validate. … … 1314 1330 if (pTimer->cCpus > 1) 1315 1331 return VERR_NOT_SUPPORTED; 1316 RTTimerStop(pTimer); 1317 return RTTimerStart(pTimer, u64NanoInterval); 1332 1333 cJiffies = u64NanoInterval / RTTimerGetSystemGranularity(); 1334 if (cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval) 1335 cJiffies = 0; 1336 1337 spin_lock_irqsave(&pTimer->ChgIntLock, flFlags); 1338 pTimer->aSubTimers[0].u.Std.fFirstAfterChg = true; 1339 pTimer->cJiffies = cJiffies; 1340 ASMAtomicWriteU64(&pTimer->u64NanoInterval, u64NanoInterval); 1341 spin_unlock_irqrestore(&pTimer->ChgIntLock, flFlags); 1342 return VINF_SUCCESS; 1318 1343 } 1319 1344 RT_EXPORT_SYMBOL(RTTimerChangeInterval); … … 1445 1470 if (pTimer->cJiffies * RTTimerGetSystemGranularity() != u64NanoInterval) 1446 1471 pTimer->cJiffies = 0; 1472 spin_lock_init(&pTimer->ChgIntLock); 1447 1473 1448 1474 for (iCpu = 0; iCpu < cCpus; iCpu++) … … 1461 1487 pTimer->aSubTimers[iCpu].u.Std.LnxTimer.function = rtTimerLinuxStdCallback; 1462 1488 pTimer->aSubTimers[iCpu].u.Std.LnxTimer.expires = jiffies; 1463 pTimer->aSubTimers[iCpu].u.Std.u64StartTS = 0;1464 1489 pTimer->aSubTimers[iCpu].u.Std.u64NextTS = 0; 1465 1490 }
Note:
See TracChangeset
for help on using the changeset viewer.