Changeset 53457 in vbox for trunk/src/VBox/Runtime/r0drv
- Timestamp:
- Dec 5, 2014 12:54:16 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp
r47637 r53457 40 40 #include "internal-r0drv-nt.h" 41 41 #include "internal/magics.h" 42 43 /** This seems to provide better accuracy. */ 44 #define RTR0TIMER_NT_MANUAL_RE_ARM 1 42 45 43 46 … … 71 74 * is destroyed to indicate clearly that thread should exit. */ 72 75 uint32_t volatile u32Magic; 76 /** Suspend count down for single shot omnit timers. */ 77 int32_t volatile cOmniSuspendCountDown; 73 78 /** Flag indicating the timer is suspended. */ 74 79 bool volatile fSuspended; … … 86 91 /** The timer interval. 0 if one-shot. */ 87 92 uint64_t u64NanoInterval; 93 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 94 /** The NT start time . */ 95 uint64_t uNtStartTime; 96 #endif 88 97 /** The Nt timer object. */ 89 98 KTIMER NtTimer; … … 98 107 99 108 109 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 110 /** 111 * Get current NT interrupt time. 112 * @return NT interrupt time 113 */ 114 static uint64_t rtTimerNtQueryInterruptTime(void) 115 { 116 # ifdef RT_ARCH_AMD64 117 return KeQueryInterruptTime(); /* macro */ 118 # else 119 if (g_pfnrtKeQueryInterruptTime) 120 return g_pfnrtKeQueryInterruptTime(); 121 122 /* NT4 */ 123 ULARGE_INTEGER InterruptTime; 124 do 125 { 126 InterruptTime.HighPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High1Time; 127 InterruptTime.LowPart = ((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.LowPart; 128 } while (((KUSER_SHARED_DATA volatile *)SharedUserData)->InterruptTime.High2Time != InterruptTime.HighPart); 129 return InterruptTime.QuadPart; 130 # endif 131 } 132 #endif /* RTR0TIMER_NT_MANUAL_RE_ARM */ 133 134 135 /** 136 * Manually re-arms an internval timer. 137 * 138 * Turns out NT doesn't necessarily do a very good job at re-arming timers 139 * accurately. 140 * 141 * @param pTimer The timer. 142 * @param iTick The current timer tick. 143 * @param pMasterDpc The master DPC. 144 */ 145 DECLINLINE(void) rtTimerNtRearmInternval(PRTTIMER pTimer, uint64_t iTick, PKDPC pMasterDpc) 146 { 147 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 148 Assert(pTimer->u64NanoInterval); 149 150 uint64_t uNtNext = (iTick * pTimer->u64NanoInterval) / 100 - 10; /* 1us fudge */ 151 LARGE_INTEGER DueTime; 152 DueTime.QuadPart = rtTimerNtQueryInterruptTime() - pTimer->uNtStartTime; 153 if (DueTime.QuadPart < 0) 154 DueTime.QuadPart = 0; 155 if ((uint64_t)DueTime.QuadPart < uNtNext) 156 DueTime.QuadPart -= uNtNext; 157 else 158 DueTime.QuadPart = -2500; /* 0.25ms */ 159 160 KeSetTimerEx(&pTimer->NtTimer, DueTime, 0, &pTimer->aSubTimers[0].NtDpc); 161 #endif 162 } 163 100 164 101 165 /** … … 125 189 if (!pTimer->u64NanoInterval) 126 190 ASMAtomicWriteBool(&pTimer->fSuspended, true); 127 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pTimer->aSubTimers[0].iTick); 191 uint64_t iTick = ++pTimer->aSubTimers[0].iTick; 192 if (pTimer->u64NanoInterval) 193 rtTimerNtRearmInternval(pTimer, iTick, &pTimer->aSubTimers[0].NtDpc); 194 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 128 195 } 129 196 … … 161 228 { 162 229 if (!pTimer->u64NanoInterval) 163 ASMAtomicWriteBool(&pTimer->fSuspended, true); 230 if (ASMAtomicDecS32(&pTimer->cOmniSuspendCountDown) <= 0) 231 ASMAtomicWriteBool(&pTimer->fSuspended, true); 232 164 233 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick); 165 234 } … … 203 272 RTCPUSET OnlineSet; 204 273 RTMpGetOnlineSet(&OnlineSet); 205 for (int iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++) 206 if ( RTCpuSetIsMemberByIndex(&OnlineSet, iCpu) 207 && iCpuSelf != iCpu) 208 KeInsertQueueDpc(&pTimer->aSubTimers[iCpu].NtDpc, 0, 0); 209 210 if (!pTimer->u64NanoInterval) 211 ASMAtomicWriteBool(&pTimer->fSuspended, true); 212 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick); 274 275 if (pTimer->u64NanoInterval) 276 { 277 /* 278 * Recurring timer. 279 */ 280 for (int iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++) 281 if ( RTCpuSetIsMemberByIndex(&OnlineSet, iCpu) 282 && iCpuSelf != iCpu) 283 KeInsertQueueDpc(&pTimer->aSubTimers[iCpu].NtDpc, 0, 0); 284 285 uint64_t iTick = ++pSubTimer->iTick; 286 rtTimerNtRearmInternval(pTimer, iTick, &pTimer->aSubTimers[RTMpCpuIdToSetIndex(pTimer->idCpu)].NtDpc); 287 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 288 } 289 else 290 { 291 /* 292 * Single shot timers gets complicated wrt to fSuspended maintance. 293 */ 294 uint32_t cCpus = 0; 295 for (int iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++) 296 if (RTCpuSetIsMemberByIndex(&OnlineSet, iCpu)) 297 cCpus++; 298 ASMAtomicAddS32(&pTimer->cOmniSuspendCountDown, cCpus); 299 300 for (int iCpu = 0; iCpu < RTCPUSET_MAX_CPUS; iCpu++) 301 if ( RTCpuSetIsMemberByIndex(&OnlineSet, iCpu) 302 && iCpuSelf != iCpu) 303 if (!KeInsertQueueDpc(&pTimer->aSubTimers[iCpu].NtDpc, 0, 0)) 304 ASMAtomicDecS32(&pTimer->cOmniSuspendCountDown); /* already queued and counted. */ 305 306 if (ASMAtomicDecS32(&pTimer->cOmniSuspendCountDown) <= 0) 307 ASMAtomicWriteBool(&pTimer->fSuspended, true); 308 309 pTimer->pfnTimer(pTimer, pTimer->pvUser, ++pSubTimer->iTick); 310 } 213 311 } 214 312 … … 239 337 : &pTimer->aSubTimers[0].NtDpc; 240 338 339 #ifndef RTR0TIMER_NT_MANUAL_RE_ARM 241 340 uint64_t u64Interval = pTimer->u64NanoInterval / 1000000; /* This is ms, believe it or not. */ 242 341 ULONG ulInterval = (ULONG)u64Interval; … … 245 344 else if (!ulInterval && pTimer->u64NanoInterval) 246 345 ulInterval = 1; 346 #endif 247 347 248 348 LARGE_INTEGER DueTime; … … 254 354 for (unsigned iCpu = 0; iCpu < cSubTimers; iCpu++) 255 355 pTimer->aSubTimers[iCpu].iTick = 0; 356 ASMAtomicWriteS32(&pTimer->cOmniSuspendCountDown, 0); 256 357 ASMAtomicWriteBool(&pTimer->fSuspended, false); 358 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 359 pTimer->uNtStartTime = rtTimerNtQueryInterruptTime(); 360 KeSetTimerEx(&pTimer->NtTimer, DueTime, 0, pMasterDpc); 361 #else 257 362 KeSetTimerEx(&pTimer->NtTimer, DueTime, ulInterval, pMasterDpc); 363 #endif 258 364 return VINF_SUCCESS; 259 365 } … … 369 475 */ 370 476 pTimer->u32Magic = RTTIMER_MAGIC; 477 pTimer->cOmniSuspendCountDown = 0; 371 478 pTimer->fSuspended = true; 372 479 pTimer->fSpecificCpu = (fFlags & RTTIMER_FLAGS_CPU_SPECIFIC) && (fFlags & RTTIMER_FLAGS_CPU_ALL) != RTTIMER_FLAGS_CPU_ALL;
Note:
See TracChangeset
for help on using the changeset viewer.