Changeset 92825 in vbox for trunk/src/VBox/Runtime/r0drv
- Timestamp:
- Dec 8, 2021 3:32:59 PM (3 years ago)
- Location:
- trunk/src/VBox/Runtime/r0drv/nt
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/r0drv/nt/initterm-r0drv-nt.cpp
r92183 r92825 49 49 /** ExSetTimerResolution, introduced in W2K. */ 50 50 PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution; 51 /** ExAllocateTimer, introduced in Windows 8.1 */ 52 PFNEXALLOCATETIMER g_pfnrtExAllocateTimer; 53 /** ExDeleteTimer, introduced in Windows 8.1 */ 54 PFNEXDELETETIMER g_pfnrtExDeleteTimer; 55 /** ExSetTimer, introduced in Windows 8.1 */ 56 PFNEXSETTIMER g_pfnrtExSetTimer; 57 /** ExCancelTimer, introduced in Windows 8.1 */ 58 PFNEXCANCELTIMER g_pfnrtExCancelTimer; 51 59 /** KeFlushQueuedDpcs, introduced in XP. */ 52 60 PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs; … … 303 311 GET_SYSTEM_ROUTINE(ExFreePoolWithTag); 304 312 GET_SYSTEM_ROUTINE_PRF(Nt,ExSetTimerResolution); 313 GET_SYSTEM_ROUTINE_TYPE(ExAllocateTimer, PFNEXALLOCATETIMER); 314 GET_SYSTEM_ROUTINE_TYPE(ExDeleteTimer, PFNEXDELETETIMER); 315 GET_SYSTEM_ROUTINE_TYPE(ExSetTimer, PFNEXSETTIMER); 316 GET_SYSTEM_ROUTINE_TYPE(ExCancelTimer, PFNEXCANCELTIMER); 305 317 GET_SYSTEM_ROUTINE_PRF(Nt,KeFlushQueuedDpcs); 306 318 GET_SYSTEM_ROUTINE(KeIpiGenericCall); -
trunk/src/VBox/Runtime/r0drv/nt/internal-r0drv-nt.h
r91449 r92825 36 36 RT_C_DECLS_BEGIN 37 37 38 /******************************************************************************* 39 * Structures and Typedefs *40 ******************************************************************************* /38 /********************************************************************************************************************************* 39 * Structures and Typedefs * 40 *********************************************************************************************************************************/ 41 41 typedef ULONG (__stdcall *PFNMYEXSETTIMERRESOLUTION)(ULONG, BOOLEAN); 42 42 typedef VOID (__stdcall *PFNMYKEFLUSHQUEUEDDPCS)(VOID); … … 54 54 SIZE_T, MEMORY_CACHING_TYPE, ULONG); 55 55 56 #ifndef EX_TIMER_HIGH_RESOLUTION /* Too old DDK, so add missing bits. */ 57 # define EX_TIMER_NO_WAKE RT_BIT_32(3) 58 # define EX_TIMER_HIGH_RESOLUTION RT_BIT_32(2) 59 # define EX_TIMER_NOTIFICATION RT_BIT_32(31) 60 typedef struct _EX_TIMER *PEX_TIMER; 61 typedef VOID (__stdcall *PEXT_CALLBACK)(PEX_TIMER, void *); 62 typedef PEX_TIMER (__stdcall *PFNEXALLOCATETIMER)(PEXT_CALLBACK pfnCallback, void *pvUser, ULONG fFlags); 56 63 57 /******************************************************************************* 58 * Global Variables * 59 *******************************************************************************/ 64 typedef VOID (__stdcall *PEXT_DELETE_CALLBACK)(void *); 65 typedef struct _EXT_DELETE_PARAMETERS 66 { 67 ULONG Version; 68 ULONG Reserved; 69 PEXT_DELETE_CALLBACK DeleteCallback; 70 void *DeleteContext; 71 } EXT_DELETE_PARAMETERS; 72 typedef EXT_DELETE_PARAMETERS *PEXT_DELETE_PARAMETERS; 73 DECLINLINE(void) ExInitializeDeleteTimerParameters(PEXT_DELETE_PARAMETERS pParams) 74 { 75 pParams->Version = 0; 76 pParams->Reserved = 0; 77 pParams->DeleteCallback = NULL; 78 pParams->DeleteContext = NULL; 79 } 80 typedef BOOLEAN (__stdcall *PFNEXDELETETIMER)(PEX_TIMER pTimer, BOOLEAN fCancel, BOOLEAN fWait, PEXT_DELETE_PARAMETERS pParams); 81 82 typedef struct _EXT_SET_PARAMETERS_V0 83 { 84 ULONG Version; 85 ULONG Reserved; 86 LONGLONG NoWakeTolerance; 87 } EXT_SET_PARAMETERS; 88 typedef EXT_SET_PARAMETERS *PEXT_SET_PARAMETERS; 89 DECLINLINE(void) ExInitializeSetTimerParameters(PEXT_SET_PARAMETERS pParams) 90 { 91 pParams->Version = 0; 92 pParams->Reserved = 0; 93 pParams->NoWakeTolerance = 0; 94 } 95 typedef BOOLEAN (__stdcall *PFNEXSETTIMER)(PEX_TIMER pTimer, LONGLONG DueTime, LONGLONG Period, PEXT_SET_PARAMETERS pParams); 96 97 typedef BOOLEAN (__stdcall *PFNEXCANCELTIMER)(PEX_TIMER pTimer, void *pvReserved); 98 99 #else 100 typedef decltype(ExAllocateTimer) *PFNEXALLOCATETIMER; 101 typedef decltype(ExDeleteTimer) *PFNEXDELETETIMER; 102 typedef decltype(ExSetTimer) *PFNEXSETTIMER; 103 typedef decltype(ExCancelTimer) *PFNEXCANCELTIMER; 104 #endif 105 106 107 /********************************************************************************************************************************* 108 * Global Variables * 109 *********************************************************************************************************************************/ 60 110 extern RTCPUSET g_rtMpNtCpuSet; 61 111 extern uint32_t g_cRtMpNtMaxGroups; … … 66 116 extern decltype(ExFreePoolWithTag) *g_pfnrtExFreePoolWithTag; 67 117 extern PFNMYEXSETTIMERRESOLUTION g_pfnrtNtExSetTimerResolution; 118 extern PFNEXALLOCATETIMER g_pfnrtExAllocateTimer; 119 extern PFNEXDELETETIMER g_pfnrtExDeleteTimer; 120 extern PFNEXSETTIMER g_pfnrtExSetTimer; 121 extern PFNEXCANCELTIMER g_pfnrtExCancelTimer; 68 122 extern PFNMYKEFLUSHQUEUEDDPCS g_pfnrtNtKeFlushQueuedDpcs; 69 123 extern PFNHALREQUESTIPI_W7PLUS g_pfnrtHalRequestIpiW7Plus; -
trunk/src/VBox/Runtime/r0drv/nt/timer-r0drv-nt.cpp
r82968 r92825 43 43 #include "internal/magics.h" 44 44 45 46 /********************************************************************************************************************************* 47 * Defined Constants And Macros * 48 *********************************************************************************************************************************/ 45 49 /** This seems to provide better accuracy. */ 46 50 #define RTR0TIMER_NT_MANUAL_RE_ARM 1 51 52 #if !defined(IN_GUEST) || defined(DOXYGEN_RUNNING) 53 /** This using high resolution timers introduced with windows 8.1. */ 54 # define RTR0TIMER_NT_HIGH_RES 1 55 #endif 47 56 48 57 … … 99 108 uint64_t uNtStartTime; 100 109 #endif 101 /** The N ttimer object. */110 /** The NT timer object. */ 102 111 KTIMER NtTimer; 112 #ifdef RTR0TIMER_NT_HIGH_RES 113 /** High resolution timer. If not NULL, this must be used instead of NtTimer. */ 114 PEX_TIMER pHighResTimer; 115 #endif 103 116 /** The number of sub-timers. */ 104 117 RTCPUID cSubTimers; … … 145 158 * @param pTimer The timer. 146 159 * @param iTick The current timer tick. 147 * @param pMasterDpc The master DPC. 148 */ 149 DECLINLINE(void) rtTimerNtRearmInternval(PRTTIMER pTimer, uint64_t iTick, PKDPC pMasterDpc) 160 */ 161 DECLINLINE(void) rtTimerNtRearmInternval(PRTTIMER pTimer, uint64_t iTick) 150 162 { 151 163 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 152 164 Assert(pTimer->u64NanoInterval); 153 RT_NOREF1(pMasterDpc);154 165 155 166 uint64_t uNtNext = (iTick * pTimer->u64NanoInterval) / 100 - 10; /* 1us fudge */ … … 163 174 DueTime.QuadPart = -2500; /* 0.25ms */ 164 175 165 KeSetTimerEx(&pTimer->NtTimer, DueTime, 0, &pTimer->aSubTimers[0].NtDpc); 176 # ifdef RTR0TIMER_NT_HIGH_RES 177 if (pTimer->pHighResTimer) 178 g_pfnrtExSetTimer(pTimer->pHighResTimer, DueTime.QuadPart, 0, NULL); 179 else 180 # endif 181 KeSetTimerEx(&pTimer->NtTimer, DueTime, 0, &pTimer->aSubTimers[0].NtDpc); 166 182 #else 167 RT_NOREF 3(pTimer, iTick, pMasterDpc);168 #endif 169 } 170 171 172 /** 173 * Timer callback functionfor the non-omni timers.183 RT_NOREF(pTimer, iTick); 184 #endif 185 } 186 187 188 /** 189 * Common timer callback worker for the non-omni timers. 174 190 * 175 191 * @returns HRTIMER_NORESTART or HRTIMER_RESTART depending on whether it's a one-shot or interval timer. 192 * @param pTimer The timer. 193 */ 194 static void rtTimerNtSimpleCallbackWorker(PRTTIMER pTimer) 195 { 196 /* 197 * Check that we haven't been suspended before doing the callout. 198 */ 199 if ( !ASMAtomicUoReadBool(&pTimer->fSuspended) 200 && pTimer->u32Magic == RTTIMER_MAGIC) 201 { 202 ASMAtomicWriteHandle(&pTimer->aSubTimers[0].hActiveThread, RTThreadNativeSelf()); 203 204 if (!pTimer->u64NanoInterval) 205 ASMAtomicWriteBool(&pTimer->fSuspended, true); 206 uint64_t iTick = ++pTimer->aSubTimers[0].iTick; 207 if (pTimer->u64NanoInterval) 208 rtTimerNtRearmInternval(pTimer, iTick); 209 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 210 211 ASMAtomicWriteHandle(&pTimer->aSubTimers[0].hActiveThread, NIL_RTNATIVETHREAD); 212 } 213 } 214 215 216 /** 217 * Timer callback function for the low-resolution non-omni timers. 218 * 176 219 * @param pDpc Pointer to the DPC. 177 220 * @param pvUser Pointer to our internal timer structure. … … 188 231 #endif 189 232 190 /* 191 * Check that we haven't been suspended before doing the callout. 192 */ 193 if ( !ASMAtomicUoReadBool(&pTimer->fSuspended) 194 && pTimer->u32Magic == RTTIMER_MAGIC) 195 { 196 ASMAtomicWriteHandle(&pTimer->aSubTimers[0].hActiveThread, RTThreadNativeSelf()); 197 198 if (!pTimer->u64NanoInterval) 199 ASMAtomicWriteBool(&pTimer->fSuspended, true); 200 uint64_t iTick = ++pTimer->aSubTimers[0].iTick; 201 if (pTimer->u64NanoInterval) 202 rtTimerNtRearmInternval(pTimer, iTick, &pTimer->aSubTimers[0].NtDpc); 203 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 204 205 ASMAtomicWriteHandle(&pTimer->aSubTimers[0].hActiveThread, NIL_RTNATIVETHREAD); 206 } 207 208 NOREF(pDpc); NOREF(SystemArgument1); NOREF(SystemArgument2); 209 } 233 rtTimerNtSimpleCallbackWorker(pTimer); 234 235 RT_NOREF(pDpc, SystemArgument1, SystemArgument2); 236 } 237 238 239 #ifdef RTR0TIMER_NT_HIGH_RES 240 /** 241 * Timer callback function for the high-resolution non-omni timers. 242 * 243 * @param pExTimer The windows timer. 244 * @param pvUser Pointer to our internal timer structure. 245 */ 246 static void _stdcall rtTimerNtHighResSimpleCallback(PEX_TIMER pExTimer, void *pvUser) 247 { 248 PRTTIMER pTimer = (PRTTIMER)pvUser; 249 AssertPtr(pTimer); 250 Assert(pTimer->pHighResTimer == pExTimer); 251 # ifdef RT_STRICT 252 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 253 RTAssertMsg2Weak("rtTimerNtHighResSimpleCallback: Irql=%d expected >=%d\n", KeGetCurrentIrql(), DISPATCH_LEVEL); 254 # endif 255 256 /* If we're not on the desired CPU, trigger the DPC. That will rearm the 257 timer and such. */ 258 if ( !pTimer->fSpecificCpu 259 || pTimer->idCpu == RTMpCpuId()) 260 rtTimerNtSimpleCallbackWorker(pTimer); 261 else 262 KeInsertQueueDpc(&pTimer->aSubTimers[0].NtDpc, 0, 0); 263 264 RT_NOREF(pExTimer); 265 } 266 #endif /* RTR0TIMER_NT_HIGH_RES */ 210 267 211 268 … … 254 311 255 312 /** 256 * The timer callback for an omni-timer.313 * Common timer callback worker for omni-timers. 257 314 * 258 315 * This is responsible for queueing the DPCs for the other CPUs and 259 316 * perform the callback on the CPU on which it is called. 260 317 * 261 * @param pDpc The DPC object. 262 * @param pvUser Pointer to the sub-timer. 263 * @param SystemArgument1 Some system stuff. 264 * @param SystemArgument2 Some system stuff. 265 */ 266 static void _stdcall rtTimerNtOmniMasterCallback(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 267 { 268 PRTTIMERNTSUBTIMER pSubTimer = (PRTTIMERNTSUBTIMER)pvUser; 269 PRTTIMER pTimer = pSubTimer->pParent; 270 int iCpuSelf = RTMpCpuIdToSetIndex(RTMpCpuId()); 271 272 AssertPtr(pTimer); 318 * @param pTimer The timer. 319 * @param pSubTimer The sub-timer of the calling CPU. 320 * @param iCpuSelf The set index of the CPU we're running on. 321 */ 322 static void rtTimerNtOmniMasterCallbackWorker(PRTTIMER pTimer, PRTTIMERNTSUBTIMER pSubTimer, int iCpuSelf) 323 { 273 324 #ifdef RT_STRICT 274 325 if (KeGetCurrentIrql() < DISPATCH_LEVEL) … … 301 352 302 353 uint64_t iTick = ++pSubTimer->iTick; 303 rtTimerNtRearmInternval(pTimer, iTick , &pTimer->aSubTimers[RTMpCpuIdToSetIndex(pTimer->idCpu)].NtDpc);354 rtTimerNtRearmInternval(pTimer, iTick); 304 355 pTimer->pfnTimer(pTimer, pTimer->pvUser, iTick); 305 356 } … … 329 380 ASMAtomicWriteHandle(&pSubTimer->hActiveThread, NIL_RTNATIVETHREAD); 330 381 } 331 332 NOREF(pDpc); NOREF(SystemArgument1); NOREF(SystemArgument2); 333 } 334 382 } 383 384 385 /** 386 * The timer callback for an omni-timer, low-resolution. 387 * 388 * @param pDpc The DPC object. 389 * @param pvUser Pointer to the sub-timer. 390 * @param SystemArgument1 Some system stuff. 391 * @param SystemArgument2 Some system stuff. 392 */ 393 static void _stdcall rtTimerNtOmniMasterCallback(IN PKDPC pDpc, IN PVOID pvUser, IN PVOID SystemArgument1, IN PVOID SystemArgument2) 394 { 395 PRTTIMERNTSUBTIMER const pSubTimer = (PRTTIMERNTSUBTIMER)pvUser; 396 PRTTIMER const pTimer = pSubTimer->pParent; 397 int const iCpuSelf = RTMpCpuIdToSetIndex(RTMpCpuId()); 398 399 AssertPtr(pTimer); 400 #ifdef RT_STRICT 401 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 402 RTAssertMsg2Weak("rtTimerNtOmniMasterCallback: Irql=%d expected >=%d\n", KeGetCurrentIrql(), DISPATCH_LEVEL); 403 if (pSubTimer - &pTimer->aSubTimers[0] != iCpuSelf) 404 RTAssertMsg2Weak("rtTimerNtOmniMasterCallback: iCpuSelf=%d pSubTimer=%p / %d\n", iCpuSelf, pSubTimer, pSubTimer - &pTimer->aSubTimers[0]); 405 #endif 406 407 rtTimerNtOmniMasterCallbackWorker(pTimer, pSubTimer, iCpuSelf); 408 409 RT_NOREF(pDpc, SystemArgument1, SystemArgument2); 410 } 411 412 413 #ifdef RTR0TIMER_NT_HIGH_RES 414 /** 415 * The timer callback for an high-resolution omni-timer. 416 * 417 * @param pExTimer The windows timer. 418 * @param pvUser Pointer to our internal timer structure. 419 */ 420 static void __stdcall rtTimerNtHighResOmniCallback(PEX_TIMER pExTimer, void *pvUser) 421 { 422 PRTTIMER const pTimer = (PRTTIMER)pvUser; 423 int const iCpuSelf = RTMpCpuIdToSetIndex(RTMpCpuId()); 424 PRTTIMERNTSUBTIMER const pSubTimer = &pTimer->aSubTimers[iCpuSelf]; 425 426 AssertPtr(pTimer); 427 Assert(pTimer->pHighResTimer == pExTimer); 428 # ifdef RT_STRICT 429 if (KeGetCurrentIrql() < DISPATCH_LEVEL) 430 RTAssertMsg2Weak("rtTimerNtHighResOmniCallback: Irql=%d expected >=%d\n", KeGetCurrentIrql(), DISPATCH_LEVEL); 431 # endif 432 433 rtTimerNtOmniMasterCallbackWorker(pTimer, pSubTimer, iCpuSelf); 434 435 RT_NOREF(pExTimer); 436 } 437 #endif /* RTR0TIMER_NT_HIGH_RES */ 335 438 336 439 … … 373 476 for (unsigned iCpu = 0; iCpu < cSubTimers; iCpu++) 374 477 pTimer->aSubTimers[iCpu].iTick = 0; 478 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 479 pTimer->uNtStartTime = rtTimerNtQueryInterruptTime() + u64First / 100; 480 #endif 375 481 ASMAtomicWriteS32(&pTimer->cOmniSuspendCountDown, 0); 376 482 ASMAtomicWriteBool(&pTimer->fSuspended, false); 483 484 #ifdef RTR0TIMER_NT_HIGH_RES 485 if (pTimer->pHighResTimer) 486 { 487 # ifdef RTR0TIMER_NT_MANUAL_RE_ARM 488 g_pfnrtExSetTimer(pTimer->pHighResTimer, DueTime.QuadPart, 0, NULL); 489 # else 490 g_pfnrtExSetTimer(pTimer->pHighResTimer, DueTime.QuadPart, RT_MIN(pTimer->u64NanoInterval / 100, MAXLONG), NULL); 491 # endif 492 } 493 else 494 #endif 495 { 377 496 #ifdef RTR0TIMER_NT_MANUAL_RE_ARM 378 pTimer->uNtStartTime = rtTimerNtQueryInterruptTime() + u64First / 100; 379 KeSetTimerEx(&pTimer->NtTimer, DueTime, 0, pMasterDpc); 497 KeSetTimerEx(&pTimer->NtTimer, DueTime, 0, pMasterDpc); 380 498 #else 381 KeSetTimerEx(&pTimer->NtTimer, DueTime, ulInterval, pMasterDpc); 382 #endif 499 KeSetTimerEx(&pTimer->NtTimer, DueTime, ulInterval, pMasterDpc); 500 #endif 501 } 383 502 return VINF_SUCCESS; 384 503 } … … 399 518 ASMAtomicWriteBool(&pTimer->fSuspended, true); 400 519 401 KeCancelTimer(&pTimer->NtTimer); 520 #ifdef RTR0TIMER_NT_HIGH_RES 521 if (pTimer->pHighResTimer) 522 g_pfnrtExCancelTimer(pTimer->pHighResTimer, NULL); 523 else 524 #endif 525 KeCancelTimer(&pTimer->NtTimer); 402 526 403 527 for (RTCPUID iCpu = 0; iCpu < pTimer->cSubTimers; iCpu++) … … 456 580 if (!ASMAtomicUoReadBool(&pTimer->fSuspended)) 457 581 rtTimerNtStopWorker(pTimer); 582 583 #ifdef RTR0TIMER_NT_HIGH_RES 584 /* 585 * Destroy the high-resolution timer before flushing DPCs. 586 */ 587 if (pTimer->pHighResTimer) 588 { 589 g_pfnrtExDeleteTimer(pTimer->pHighResTimer, TRUE /*fCancel*/, TRUE /*fWait*/, NULL); 590 pTimer->pHighResTimer = NULL; 591 } 592 #endif 458 593 459 594 /* … … 499 634 /* 500 635 * Initialize it. 636 * 637 * Note! The difference between a SynchronizationTimer and a NotificationTimer 638 * (KeInitializeTimer) is, as far as I can gather, only that the former 639 * will wake up exactly one waiting thread and the latter will wake up 640 * everyone. Since we don't do any waiting on the NtTimer, that is not 641 * relevant to us. 501 642 */ 502 643 pTimer->u32Magic = RTTIMER_MAGIC; … … 510 651 pTimer->pvUser = pvUser; 511 652 pTimer->u64NanoInterval = u64NanoInterval; 512 if (g_pfnrtKeInitializeTimerEx) 513 g_pfnrtKeInitializeTimerEx(&pTimer->NtTimer, SynchronizationTimer); 653 654 int rc = VINF_SUCCESS; 655 #ifdef RTR0TIMER_NT_HIGH_RES 656 if ( (fFlags & RTTIMER_FLAGS_HIGH_RES) 657 && RTTimerCanDoHighResolution()) 658 { 659 pTimer->pHighResTimer = g_pfnrtExAllocateTimer(pTimer->fOmniTimer ? rtTimerNtHighResOmniCallback 660 : rtTimerNtHighResSimpleCallback, pTimer, 661 EX_TIMER_HIGH_RESOLUTION | EX_TIMER_NOTIFICATION); 662 if (!pTimer->pHighResTimer) 663 rc = VERR_OUT_OF_RESOURCES; 664 } 514 665 else 515 KeInitializeTimer(&pTimer->NtTimer); 516 int rc = VINF_SUCCESS; 517 if (pTimer->fOmniTimer) 518 { 519 /* 520 * Initialize the per-cpu "sub-timers", select the first online cpu 521 * to be the master. 522 * ASSUMES that no cpus will ever go offline. 523 */ 524 pTimer->idCpu = NIL_RTCPUID; 525 for (unsigned iCpu = 0; iCpu < cSubTimers && RT_SUCCESS(rc); iCpu++) 666 #endif 667 { 668 if (g_pfnrtKeInitializeTimerEx) /** @todo just call KeInitializeTimer. */ 669 g_pfnrtKeInitializeTimerEx(&pTimer->NtTimer, SynchronizationTimer); 670 else 671 KeInitializeTimer(&pTimer->NtTimer); 672 } 673 if (RT_SUCCESS(rc)) 674 { 675 if (pTimer->fOmniTimer) 526 676 { 527 pTimer->aSubTimers[iCpu].iTick = 0; 528 pTimer->aSubTimers[iCpu].pParent = pTimer; 529 530 if ( pTimer->idCpu == NIL_RTCPUID 531 && RTMpIsCpuOnline(RTMpCpuIdFromSetIndex(iCpu))) 677 /* 678 * Initialize the per-cpu "sub-timers", select the first online cpu to be 679 * the master. This ASSUMES that no cpus will ever go offline. 680 * 681 * Note! For the high-resolution scenario, all DPC callbacks are slaves as 682 * we have a dedicated timer callback, set above during allocation, 683 * and don't control which CPU it (rtTimerNtHighResOmniCallback) is 684 * called on. 685 */ 686 pTimer->idCpu = NIL_RTCPUID; 687 for (unsigned iCpu = 0; iCpu < cSubTimers && RT_SUCCESS(rc); iCpu++) 532 688 { 533 pTimer->idCpu = RTMpCpuIdFromSetIndex(iCpu); 534 KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniMasterCallback, &pTimer->aSubTimers[iCpu]); 689 pTimer->aSubTimers[iCpu].iTick = 0; 690 pTimer->aSubTimers[iCpu].pParent = pTimer; 691 692 if ( pTimer->idCpu == NIL_RTCPUID 693 && RTMpIsCpuOnline(RTMpCpuIdFromSetIndex(iCpu))) 694 { 695 pTimer->idCpu = RTMpCpuIdFromSetIndex(iCpu); 696 #ifdef RTR0TIMER_NT_HIGH_RES 697 if (pTimer->pHighResTimer) 698 KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniSlaveCallback, &pTimer->aSubTimers[iCpu]); 699 else 700 #endif 701 KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniMasterCallback, &pTimer->aSubTimers[iCpu]); 702 } 703 else 704 KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniSlaveCallback, &pTimer->aSubTimers[iCpu]); 705 if (g_pfnrtKeSetImportanceDpc) 706 g_pfnrtKeSetImportanceDpc(&pTimer->aSubTimers[iCpu].NtDpc, HighImportance); 707 rc = rtMpNtSetTargetProcessorDpc(&pTimer->aSubTimers[iCpu].NtDpc, iCpu); 535 708 } 536 else 537 KeInitializeDpc(&pTimer->aSubTimers[iCpu].NtDpc, rtTimerNtOmniSlaveCallback, &pTimer->aSubTimers[iCpu]); 709 Assert(pTimer->idCpu != NIL_RTCPUID); 710 } 711 else 712 { 713 /* 714 * Initialize the first "sub-timer", target the DPC on a specific processor 715 * if requested to do so. 716 */ 717 pTimer->aSubTimers[0].iTick = 0; 718 pTimer->aSubTimers[0].pParent = pTimer; 719 720 KeInitializeDpc(&pTimer->aSubTimers[0].NtDpc, rtTimerNtSimpleCallback, pTimer); 538 721 if (g_pfnrtKeSetImportanceDpc) 539 g_pfnrtKeSetImportanceDpc(&pTimer->aSubTimers[iCpu].NtDpc, HighImportance); 540 rc = rtMpNtSetTargetProcessorDpc(&pTimer->aSubTimers[iCpu].NtDpc, iCpu); 722 g_pfnrtKeSetImportanceDpc(&pTimer->aSubTimers[0].NtDpc, HighImportance); 723 if (pTimer->fSpecificCpu) 724 rc = rtMpNtSetTargetProcessorDpc(&pTimer->aSubTimers[0].NtDpc, (int)pTimer->idCpu); 541 725 } 542 Assert(pTimer->idCpu != NIL_RTCPUID); 543 } 544 else 545 { 546 /* 547 * Initialize the first "sub-timer", target the DPC on a specific processor 548 * if requested to do so. 549 */ 550 pTimer->aSubTimers[0].iTick = 0; 551 pTimer->aSubTimers[0].pParent = pTimer; 552 553 KeInitializeDpc(&pTimer->aSubTimers[0].NtDpc, rtTimerNtSimpleCallback, pTimer); 554 if (g_pfnrtKeSetImportanceDpc) 555 g_pfnrtKeSetImportanceDpc(&pTimer->aSubTimers[0].NtDpc, HighImportance); 556 if (pTimer->fSpecificCpu) 557 rc = rtMpNtSetTargetProcessorDpc(&pTimer->aSubTimers[0].NtDpc, (int)pTimer->idCpu); 558 } 559 if (RT_SUCCESS(rc)) 560 { 561 *ppTimer = pTimer; 562 return VINF_SUCCESS; 726 if (RT_SUCCESS(rc)) 727 { 728 *ppTimer = pTimer; 729 return VINF_SUCCESS; 730 } 731 732 #ifdef RTR0TIMER_NT_HIGH_RES 733 if (pTimer->pHighResTimer) 734 { 735 g_pfnrtExDeleteTimer(pTimer->pHighResTimer, FALSE, FALSE, NULL); 736 pTimer->pHighResTimer = NULL; 737 } 738 #endif 563 739 } 564 740 … … 593 769 RTDECL(bool) RTTimerCanDoHighResolution(void) 594 770 { 771 #ifdef RTR0TIMER_NT_HIGH_RES 772 return g_pfnrtExAllocateTimer != NULL 773 && g_pfnrtExDeleteTimer != NULL 774 && g_pfnrtExSetTimer != NULL 775 && g_pfnrtExCancelTimer != NULL; 776 #else 595 777 return false; 596 } 597 778 #endif 779 } 780
Note:
See TracChangeset
for help on using the changeset viewer.