Changeset 54375 in vbox for trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
- Timestamp:
- Feb 23, 2015 10:41:10 AM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
r54371 r54375 1385 1385 ASMAtomicIncU32(&pDevExt->cMpOnOffEvents); 1386 1386 1387 /* If we are the initiator going offline while measuring the TSC delta, unspin other waiting CPUs! */1388 if (ASMAtomicReadU32(&pDevExt->idTscDeltaInitiator) == idCpu)1389 {1390 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_START);1391 ASMAtomicWriteU64(&pGip->aCPUs[i].u64TSCSample, ~GIP_TSC_DELTA_RSVD);1392 }1393 1394 1387 if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED) 1395 1388 { … … 1805 1798 LogFlow(("supdrvGipCreate:\n")); 1806 1799 1807 /* Assert order. */ 1800 /* 1801 * Assert order. 1802 */ 1808 1803 Assert(pDevExt->u32SystemTimerGranularityGrant == 0); 1809 1804 Assert(pDevExt->GipMemObj == NIL_RTR0MEMOBJ); 1810 1805 Assert(!pDevExt->pGipTimer); 1806 #ifdef SUPDRV_USE_MUTEX_FOR_GIP 1807 Assert(pDevExt->mtxGip != NIL_RTSEMMUTEX); 1808 Assert(pDevExt->mtxTscDelta != NIL_RTSEMMUTEX); 1809 #else 1810 Assert(pDevExt->mtxGip != NIL_RTSEMFASTMUTEX); 1811 Assert(pDevExt->mtxTscDelta != NIL_RTSEMFASTMUTEX); 1812 #endif 1811 1813 1812 1814 /* … … 1832 1834 pGip = (PSUPGLOBALINFOPAGE)RTR0MemObjAddress(pDevExt->GipMemObj); AssertPtr(pGip); 1833 1835 HCPhysGip = RTR0MemObjGetPagePhysAddr(pDevExt->GipMemObj, 0); Assert(HCPhysGip != NIL_RTHCPHYS); 1834 1835 /*1836 * Allocate the TSC-delta sync struct on a separate cache line.1837 */1838 pDevExt->pvTscDeltaSync = RTMemAllocZ(sizeof(SUPTSCDELTASYNC) + 63);1839 pDevExt->pTscDeltaSync = RT_ALIGN_PT(pDevExt->pvTscDeltaSync, 64, PSUPTSCDELTASYNC);1840 Assert(RT_ALIGN_PT(pDevExt->pTscDeltaSync, 64, PSUPTSCDELTASYNC) == pDevExt->pTscDeltaSync);1841 1836 1842 1837 /* … … 2046 2041 } 2047 2042 2048 if (pDevExt->pvTscDeltaSync)2049 {2050 RTMemFree(pDevExt->pvTscDeltaSync);2051 pDevExt->pTscDeltaSync = NULL;2052 pDevExt->pvTscDeltaSync = NULL;2053 }2054 2055 2043 /* 2056 2044 * Invalid the GIP data. … … 2635 2623 * @{ 2636 2624 */ 2637 #if 02638 #define TSCDELTA_MASTER_SYNC_BEFORE(a_pSync1, a_pMySync, a_pOtherSync) \2639 do {\2640 ASMAtomicWriteU32(&(a_pSync1)->u, GIP_TSC_DELTA_SYNC_START); \2641 \2642 /* Disable interrupts only in the master for as short a period \2643 as possible, thanks again to Windows. See @bugref{6710} comment #73. */ \2644 uFlags = ASMIntDisableFlags(); \2645 \2646 while (ASMAtomicReadU32(&(a_pSync1)->u) == GIP_TSC_DELTA_SYNC_START) \2647 { /* nothing */ } \2648 } while (0)2649 #define TSCDELTA_MASTER_SYNC_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \2650 do {\2651 /* Sync up with worker. */ \2652 ASMSetFlags(uFlags); \2653 \2654 while (ASMAtomicReadU32(&(a_pSync1)->u) != GIP_TSC_DELTA_SYNC_WORKER_DONE) \2655 { /* nothing */ } \2656 } while (0)2657 #define TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \2658 do {\2659 ASMAtomicWriteU32(&(a_pSync1)->u, GIP_TSC_DELTA_SYNC_STOP); \2660 } while (0)2661 2662 #define TSCDELTA_OTHER_SYNC_BEFORE(a_pSync1, a_pMySync, a_pOtherSync, a_MidSyncExpr) \2663 do { \2664 while (ASMAtomicReadU32(&(a_pSync1)->u) != GIP_TSC_DELTA_SYNC_START) \2665 { /* nothing */ } \2666 a_MidSyncExpr; \2667 ASMAtomicWriteU32(&(a_pSync1)->u, GIP_TSC_DELTA_SYNC_WORKER_READY); \2668 } while (0)2669 #define TSCDELTA_OTHER_SYNC_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \2670 do { \2671 /* Tell master we're done collecting our data. */ \2672 ASMAtomicWriteU32(&(a_pSync1)->u, GIP_TSC_DELTA_SYNC_WORKER_DONE); \2673 \2674 /* Wait for the master to process the data. */ \2675 while (ASMAtomicReadU32(&(a_pSync1)->u) == GIP_TSC_DELTA_SYNC_WORKER_DONE) \2676 ASMNopPause(); \2677 } while (0)2678 #else2679 2680 2625 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS) 2681 2626 # define TSCDELTA_DBG_VARS() uint32_t iDbgCounter 2682 # define TSCDELTA_DBG_START_LOOP() do { iDbgCounter = 0;} while (0)2683 # define TSCDELTA_DBG_CHECK_LOOP() do { if (++iDbgCounter == 0) __debugbreak(); } while (0)2627 # define TSCDELTA_DBG_START_LOOP() do { iDbgCounter = 0; } while (0) 2628 # define TSCDELTA_DBG_CHECK_LOOP() do { if (++iDbgCounter == 0) RT_BREAKPOINT(); } while (0) 2684 2629 #else 2685 2630 # define TSCDELTA_DBG_VARS() ((void)0) … … 2847 2792 } 2848 2793 2849 #define TSCDELTA_MASTER_SYNC_BEFORE(a_p Sync1, a_pMySync, a_pOtherSync) \2794 #define TSCDELTA_MASTER_SYNC_BEFORE(a_pMySync, a_pOtherSync) \ 2850 2795 do { \ 2851 2796 if (RT_LIKELY(supdrvTscDeltaSync2_Before(a_pMySync, a_pOtherSync, true /*fMaster*/, &uFlags))) \ … … 2853 2798 else break; \ 2854 2799 } while (0) 2855 #define TSCDELTA_OTHER_SYNC_BEFORE(a_p Sync1, a_pMySync, a_pOtherSync, a_MidSyncExpr) \2800 #define TSCDELTA_OTHER_SYNC_BEFORE(a_pMySync, a_pOtherSync) \ 2856 2801 do { \ 2857 2802 if (RT_LIKELY(supdrvTscDeltaSync2_Before(a_pMySync, a_pOtherSync, false /*fMaster*/, &uFlags))) \ … … 2860 2805 } while (0) 2861 2806 2862 #define TSCDELTA_MASTER_SYNC_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \ 2863 do {\ 2864 /* \ 2865 * Wait for the worker to give us the 'ready' signal. \ 2866 */ \ 2867 uint32_t u32Tmp; \ 2868 TSCDELTA_DBG_VARS(); \ 2869 ASMSetFlags(uFlags); \ 2870 TSCDELTA_DBG_START_LOOP(); \ 2871 l_master_wait_done: \ 2872 u32Tmp = ASMAtomicReadU32(&(a_pMySync)->uSyncVar); \ 2873 if (u32Tmp != GIP_TSC_DELTA_SYNC2_READY) \ 2874 { \ 2875 ASMNopPause(); \ 2876 if (u32Tmp != GIP_TSC_DELTA_SYNC2_GO) \ 2877 break; /* shouldn't ever happen! */ \ 2878 TSCDELTA_DBG_CHECK_LOOP(); \ 2879 ASMNopPause(); \ 2880 goto l_master_wait_done; \ 2881 } \ 2807 2808 static bool supdrvTscDeltaSync2_After(PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync, RTCCUINTREG fEFlags) 2809 { 2810 TSCDELTA_DBG_VARS(); 2811 2812 /* 2813 * Wait for the 'ready' signal. In the master's case, this means the 2814 * worker has completed its data collection, while in the worker's case it 2815 * means the master is done processing the data and it's time for the next 2816 * loop iteration (or whatever). 2817 */ 2818 ASMSetFlags(fEFlags); 2819 TSCDELTA_DBG_START_LOOP(); 2820 for (;;) 2821 { 2822 uint32_t u32Tmp = ASMAtomicReadU32(&pMySync->uSyncVar); 2823 if (u32Tmp == GIP_TSC_DELTA_SYNC2_READY) 2824 return true; 2825 ASMNopPause(); 2826 if (u32Tmp != GIP_TSC_DELTA_SYNC2_GO) 2827 return false; /* shouldn't ever happen! */ 2828 TSCDELTA_DBG_CHECK_LOOP(); 2829 ASMNopPause(); 2830 } 2831 } 2832 2833 #define TSCDELTA_MASTER_SYNC_AFTER(a_pMySync, a_pOtherSync) \ 2834 do { \ 2835 if (supdrvTscDeltaSync2_After(a_pMySync, a_pOtherSync, uFlags)) \ 2836 { /* likely */ } \ 2837 else break; \ 2882 2838 } while (0) 2883 2839 2884 #define TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(a_p Sync1, a_pMySync, a_pOtherSync) \2840 #define TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(a_pMySync, a_pOtherSync) \ 2885 2841 do {\ 2886 2842 /* \ … … 2894 2850 } while (0) 2895 2851 2896 2897 #define TSCDELTA_OTHER_SYNC_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \ 2852 #define TSCDELTA_OTHER_SYNC_AFTER(a_pMySync, a_pOtherSync) \ 2898 2853 do { \ 2899 2854 /* \ 2900 * Tell the master that we're done and wait for the data to be processed andthe next round to start. \2855 * Tell the master that we're done collecting data and wait for the next round to start. \ 2901 2856 */ \ 2902 uint32_t u32Tmp; \2903 TSCDELTA_DBG_VARS(); \2904 2857 if (!ASMAtomicCmpXchgU32(&(a_pOtherSync)->uSyncVar, GIP_TSC_DELTA_SYNC2_READY, GIP_TSC_DELTA_SYNC2_GO)) \ 2905 2858 { \ … … 2907 2860 break; \ 2908 2861 } \ 2909 ASMSetFlags(uFlags); \ 2910 TSCDELTA_DBG_START_LOOP(); \ 2911 l_other_wait_done: \ 2912 u32Tmp = ASMAtomicReadU32(&(a_pMySync)->uSyncVar); \ 2913 if (u32Tmp != GIP_TSC_DELTA_SYNC2_READY) \ 2914 { \ 2915 ASMNopPause(); \ 2916 if (u32Tmp != GIP_TSC_DELTA_SYNC2_GO) \ 2917 break; /* shouldn't ever happen! */ \ 2918 TSCDELTA_DBG_CHECK_LOOP(); \ 2919 ASMNopPause(); \ 2920 goto l_other_wait_done; \ 2921 } \ 2862 if (supdrvTscDeltaSync2_After(a_pMySync, a_pOtherSync, uFlags)) \ 2863 { /* likely */ } \ 2864 else break; \ 2922 2865 } while (0) 2923 #endif2924 2866 /** @} */ 2925 2867 … … 2953 2895 * 2954 2896 * @param pArgs The argument/state data. 2955 * @param p Sync1 The synchronization structure2956 * (pDevExt->pTscDeltaSync).2897 * @param pMySync My synchronization structure. 2898 * @param pOtherSync My partner's synchronization structure. 2957 2899 * @param fIsMaster Set if master, clear if worker. 2958 2900 * @param iTry The attempt number. 2959 2901 */ 2960 static void supdrvTscDeltaMethod1Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC pSync1,2961 PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync,bool fIsMaster, uint32_t iTry)2902 static void supdrvTscDeltaMethod1Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync, 2903 bool fIsMaster, uint32_t iTry) 2962 2904 { 2963 2905 PSUPGIPCPU pGipCpuWorker = pArgs->pWorker; … … 2978 2920 ("%#llx idMaster=%#x idWorker=%#x (idGipMaster=%#x)\n", 2979 2921 pGipCpuMaster->u64TSCSample, pGipCpuMaster->idCpu, pGipCpuWorker->idCpu, pArgs->pDevExt->idGipMaster)); 2980 TSCDELTA_MASTER_SYNC_BEFORE(p Sync1, pMySync, pOtherSync);2922 TSCDELTA_MASTER_SYNC_BEFORE(pMySync, pOtherSync); 2981 2923 2982 2924 do … … 2986 2928 } while (pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD); 2987 2929 2988 TSCDELTA_MASTER_SYNC_AFTER(p Sync1, pMySync, pOtherSync);2930 TSCDELTA_MASTER_SYNC_AFTER(pMySync, pOtherSync); 2989 2931 2990 2932 /* Process the data. */ … … 3004 2946 /* Reset our TSC sample and tell the worker to move on. */ 3005 2947 ASMAtomicWriteU64(&pGipCpuMaster->u64TSCSample, GIP_TSC_DELTA_RSVD); 3006 TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(p Sync1, pMySync, pOtherSync);2948 TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(pMySync, pOtherSync); 3007 2949 } 3008 2950 else … … 3016 2958 3017 2959 ASMAtomicReadU64(&pGipCpuMaster->u64TSCSample); /* Warm the cache line. */ 3018 TSCDELTA_OTHER_SYNC_BEFORE(p Sync1, pMySync, pOtherSync, Assert(pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD));2960 TSCDELTA_OTHER_SYNC_BEFORE(pMySync, pOtherSync); 3019 2961 3020 2962 /* … … 3051 2993 } 3052 2994 3053 TSCDELTA_OTHER_SYNC_AFTER(p Sync1, pMySync, pOtherSync);2995 TSCDELTA_OTHER_SYNC_AFTER(pMySync, pOtherSync); 3054 2996 } 3055 2997 } … … 3220 3162 * 3221 3163 * @param pArgs The argument/state data. 3222 * @param p Sync1 The synchronization structure3223 * (pDevExt->pTscDeltaSync).3164 * @param pMySync My synchronization structure. 3165 * @param pOtherSync My partner's synchronization structure. 3224 3166 * @param fIsMaster Set if master, clear if worker. 3225 3167 * @param iTry The attempt number. 3226 3168 */ 3227 static void supdrvTscDeltaMethod2Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC pSync1,3228 PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync,bool fIsMaster, uint32_t iTry)3169 static void supdrvTscDeltaMethod2Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync, 3170 bool fIsMaster, uint32_t iTry) 3229 3171 { 3230 3172 unsigned iLoop; … … 3272 3214 * Sync up with the worker and collect data. 3273 3215 */ 3274 TSCDELTA_MASTER_SYNC_BEFORE(p Sync1, pMySync, pOtherSync);3216 TSCDELTA_MASTER_SYNC_BEFORE(pMySync, pOtherSync); 3275 3217 supdrvTscDeltaMethod2CollectData(pArgs->M2.pMasterData, &pArgs->M2.pWorkerData->iCurSeqNo, pArgs->M2.fLagMaster); 3276 TSCDELTA_MASTER_SYNC_AFTER(p Sync1, pMySync, pOtherSync);3218 TSCDELTA_MASTER_SYNC_AFTER(pMySync, pOtherSync); 3277 3219 3278 3220 /* … … 3284 3226 supdrvTscDeltaMethod2ProcessDataOnMaster(pArgs, iLoop); 3285 3227 3286 TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(p Sync1, pMySync, pOtherSync);3228 TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(pMySync, pOtherSync); 3287 3229 } 3288 3230 else … … 3291 3233 * The worker. 3292 3234 */ 3293 TSCDELTA_OTHER_SYNC_BEFORE(p Sync1, pMySync, pOtherSync, (void)0);3235 TSCDELTA_OTHER_SYNC_BEFORE(pMySync, pOtherSync); 3294 3236 supdrvTscDeltaMethod2CollectData(pArgs->M2.pWorkerData, &pArgs->M2.pMasterData->iCurSeqNo, pArgs->M2.fLagWorker); 3295 TSCDELTA_OTHER_SYNC_AFTER(p Sync1, pMySync, pOtherSync);3237 TSCDELTA_OTHER_SYNC_AFTER(pMySync, pOtherSync); 3296 3238 } 3297 3239 … … 3346 3288 PSUPTSCDELTASYNC2 volatile *ppMySync = fIsMaster ? &pArgs->pSyncMaster : &pArgs->pSyncWorker; 3347 3289 PSUPTSCDELTASYNC2 volatile *ppOtherSync = fIsMaster ? &pArgs->pSyncWorker : &pArgs->pSyncMaster; 3348 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS) 3349 uint32_t iTry = 0; 3350 #endif 3290 TSCDELTA_DBG_VARS(); 3351 3291 3352 3292 /* … … 3360 3300 * sync state again (would cause stack corruption). 3361 3301 */ 3302 TSCDELTA_DBG_START_LOOP(); 3362 3303 while (ASMAtomicReadPtrT(ppOtherSync, PSUPTSCDELTASYNC2) != NULL) 3363 3304 { … … 3365 3306 ASMNopPause(); 3366 3307 ASMNopPause(); 3367 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS) 3368 if (++iTry == 0) __debugbreak(); 3369 #endif 3308 TSCDELTA_DBG_CHECK_LOOP(); 3370 3309 } 3371 3310 … … 3395 3334 { 3396 3335 PSUPDRVDEVEXT pDevExt = pArgs->pDevExt; 3397 PSUPTSCDELTASYNC pSync1 = pDevExt->pTscDeltaSync;3398 3336 PSUPGIPCPU pGipCpuWorker = pArgs->pWorker; 3399 3337 PSUPGIPCPU pGipCpuMaster = pArgs->pMaster; … … 3404 3342 SUPTSCDELTASYNC2 MySync; 3405 3343 PSUPTSCDELTASYNC2 pOtherSync; 3344 TSCDELTA_DBG_VARS(); 3406 3345 3407 3346 /* A bit of paranoia first. */ … … 3431 3370 /* Look for the partner, might not be here yet... Special abort considerations. */ 3432 3371 iTry = 0; 3372 TSCDELTA_DBG_START_LOOP(); 3433 3373 while ((pOtherSync = ASMAtomicReadPtrT(ppOtherSync, PSUPTSCDELTASYNC2)) == NULL) 3434 3374 { … … 3440 3380 && ASMReadTSC() - MySync.uTscStart > pArgs->cMaxTscTicks) 3441 3381 return supdrvMeasureTscDeltaCallbackAbortSyncSetup(pArgs, &MySync, fIsMaster, true /*fTimeout*/); 3442 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS) 3443 if (iTry == 0) __debugbreak(); 3444 #endif 3382 TSCDELTA_DBG_CHECK_LOOP(); 3445 3383 ASMNopPause(); 3446 3384 } … … 3452 3390 3453 3391 iTry = 0; 3392 TSCDELTA_DBG_START_LOOP(); 3454 3393 while (ASMAtomicReadU32(&MySync.uSyncVar) == GIP_TSC_DELTA_SYNC2_PRESTART_WAIT) 3455 3394 { … … 3465 3404 return supdrvMeasureTscDeltaCallbackAbortSyncSetup(pArgs, &MySync, fIsMaster, true /*fTimeout*/); 3466 3405 } 3467 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS) 3468 if (iTry == 0) __debugbreak(); 3469 #endif 3406 TSCDELTA_DBG_CHECK_LOOP(); 3470 3407 } 3471 3408 … … 3487 3424 */ 3488 3425 #ifdef GIP_TSC_DELTA_METHOD_1 3489 supdrvTscDeltaMethod1Loop(pArgs, pSync1,&MySync, pOtherSync, fIsMaster, iTry);3426 supdrvTscDeltaMethod1Loop(pArgs, &MySync, pOtherSync, fIsMaster, iTry); 3490 3427 #elif defined(GIP_TSC_DELTA_METHOD_2) 3491 supdrvTscDeltaMethod2Loop(pArgs, pSync1,&MySync, pOtherSync, fIsMaster, iTry);3428 supdrvTscDeltaMethod2Loop(pArgs, &MySync, pOtherSync, fIsMaster, iTry); 3492 3429 #else 3493 3430 # error "huh??" … … 3522 3459 ASMAtomicWriteNullPtr(ppMySync); 3523 3460 iTry = 0; 3461 TSCDELTA_DBG_START_LOOP(); 3524 3462 while (ASMAtomicReadU32(&MySync.uSyncVar) != GIP_TSC_DELTA_SYNC2_FINAL) 3525 3463 { … … 3528 3466 && !RTMpIsCpuOnline(fIsMaster ? pGipCpuWorker->idCpu : pGipCpuWorker->idCpu)) 3529 3467 break; /* this really shouldn't happen. */ 3530 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS) 3531 if (iTry == 0) __debugbreak(); 3532 #endif 3468 TSCDELTA_DBG_CHECK_LOOP(); 3533 3469 ASMNopPause(); 3534 3470 } … … 3567 3503 { 3568 3504 int rc; 3505 int rc2; 3569 3506 PSUPGLOBALINFOPAGE pGip = pDevExt->pGip; 3570 3507 RTCPUID idMaster = pDevExt->idGipMaster; … … 3587 3524 return VINF_SUCCESS; 3588 3525 } 3526 3527 /* 3528 * One measurement at at time, at least for now. We might be using 3529 * broadcast IPIs so, so be nice to the rest of the system. 3530 */ 3531 #ifdef SUPDRV_USE_MUTEX_FOR_GIP 3532 rc = RTSemMutexRequest(pDevExt->mtxTscDelta, RT_INDEFINITE_WAIT); 3533 #else 3534 rc = RTSemFastMutexRequest(pDevExt->mtxTscDelta, RT_INDEFINITE_WAIT); 3535 #endif 3536 if (RT_FAILURE(rc)) 3537 return rc; 3589 3538 3590 3539 /* … … 3629 3578 } 3630 3579 3631 /*3632 * Set the master TSC as the initiator. This serializes delta measurments.3633 */3634 /** @todo We can use a mutex or five for this now, and move it up before we3635 * do the HTT/offline-master stuff. */3636 while (!ASMAtomicCmpXchgU32(&pDevExt->idTscDeltaInitiator, idMaster, NIL_RTCPUID))3637 {3638 /*3639 * Sleep here rather than spin as there is a parallel measurement3640 * being executed and that can take a good while to be done.3641 */3642 RTThreadSleep(1);3643 }3644 3645 3580 if (RTCpuSetIsMemberByIndex(&pGip->OnlineCpuSet, pGipCpuWorker->iCpuSet)) 3646 3581 { … … 3651 3586 */ 3652 3587 /** @todo this must be allocated, not residing on the stack. */ 3653 SUPDRVGIPTSCDELTARGS Args; 3654 RT_ZERO(Args); 3655 Args.pWorker = pGipCpuWorker; 3656 Args.pMaster = pGipCpuMaster; 3657 Args.pDevExt = pDevExt; 3658 Args.pSyncMaster = NULL; 3659 Args.pSyncWorker = NULL; 3588 PSUPDRVGIPTSCDELTARGS pArgs = (PSUPDRVGIPTSCDELTARGS)RTMemAllocZ(sizeof(*pArgs)); 3589 if (pArgs) 3590 { 3591 pArgs->pWorker = pGipCpuWorker; 3592 pArgs->pMaster = pGipCpuMaster; 3593 pArgs->pDevExt = pDevExt; 3594 pArgs->pSyncMaster = NULL; 3595 pArgs->pSyncWorker = NULL; 3660 3596 #if 0 /* later */ 3661 Args.cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 2048; /* 488 us */3597 pArgs->cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 2048; /* 488 us */ 3662 3598 #else 3663 Args.cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 1024; /* 976 us */3599 pArgs->cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 1024; /* 976 us */ 3664 3600 #endif 3665 3601 3666 3602 #ifdef GIP_TSC_DELTA_METHOD_1 3667 rc = supdrvTscDeltaMethod1Init(&Args);3603 rc = supdrvTscDeltaMethod1Init(pArgs); 3668 3604 #elif defined(GIP_TSC_DELTA_METHOD_2) 3669 rc = supdrvTscDeltaMethod2Init(&Args);3605 rc = supdrvTscDeltaMethod2Init(pArgs); 3670 3606 #else 3671 3607 # error "huh?" 3672 3608 #endif 3673 if (RT_SUCCESS(rc))3674 {3675 /*3676 * Fire TSC-read workers on all CPUs but only synchronize between master3677 * and one worker to ease memory contention.3678 */3679 ASMAtomicWriteS64(&pGipCpuWorker->i64TSCDelta, INT64_MAX);3680 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP);3681 3682 /** @todo Add RTMpOnPair and replace this ineffecient broadcast IPI. */3683 rc = RTMpOnAll(supdrvMeasureTscDeltaCallback, &Args, NULL);3684 3609 if (RT_SUCCESS(rc)) 3685 3610 { 3686 if (RT_LIKELY(pGipCpuWorker->i64TSCDelta != INT64_MAX)) 3611 /* 3612 * Fire TSC-read workers on all CPUs but only synchronize between master 3613 * and one worker to ease memory contention. 3614 */ 3615 ASMAtomicWriteS64(&pGipCpuWorker->i64TSCDelta, INT64_MAX); 3616 3617 /** @todo Add RTMpOnPair and replace this ineffecient broadcast IPI. */ 3618 rc = RTMpOnAll(supdrvMeasureTscDeltaCallback, pArgs, NULL); 3619 if (RT_SUCCESS(rc)) 3687 3620 { 3688 /* 3689 * Work the TSC delta applicability rating. It starts 3690 * optimistic in supdrvGipInit, we downgrade it here. 3691 */ 3692 SUPGIPUSETSCDELTA enmRating; 3693 if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO 3694 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO) 3695 enmRating = SUPGIPUSETSCDELTA_NOT_ZERO; 3696 else if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO 3697 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO) 3698 enmRating = SUPGIPUSETSCDELTA_ROUGHLY_ZERO; 3621 if (RT_LIKELY(pGipCpuWorker->i64TSCDelta != INT64_MAX)) 3622 { 3623 /* 3624 * Work the TSC delta applicability rating. It starts 3625 * optimistic in supdrvGipInit, we downgrade it here. 3626 */ 3627 SUPGIPUSETSCDELTA enmRating; 3628 if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO 3629 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_ROUGHLY_ZERO) 3630 enmRating = SUPGIPUSETSCDELTA_NOT_ZERO; 3631 else if ( pGipCpuWorker->i64TSCDelta > GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO 3632 || pGipCpuWorker->i64TSCDelta < -GIP_TSC_DELTA_THRESHOLD_PRACTICALLY_ZERO) 3633 enmRating = SUPGIPUSETSCDELTA_ROUGHLY_ZERO; 3634 else 3635 enmRating = SUPGIPUSETSCDELTA_PRACTICALLY_ZERO; 3636 if (pGip->enmUseTscDelta < enmRating) 3637 { 3638 AssertCompile(sizeof(pGip->enmUseTscDelta) == sizeof(uint32_t)); 3639 ASMAtomicWriteU32((uint32_t volatile *)&pGip->enmUseTscDelta, enmRating); 3640 } 3641 } 3699 3642 else 3700 enmRating = SUPGIPUSETSCDELTA_PRACTICALLY_ZERO; 3701 if (pGip->enmUseTscDelta < enmRating) 3702 { 3703 AssertCompile(sizeof(pGip->enmUseTscDelta) == sizeof(uint32_t)); 3704 ASMAtomicWriteU32((uint32_t volatile *)&pGip->enmUseTscDelta, enmRating); 3705 } 3643 rc = VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED; 3706 3644 } 3707 else 3708 rc = VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED; 3645 /** @todo return try-again if we get an offline CPU error. */ 3709 3646 } 3710 /** @todo return try-again if we get an offline CPU error. */3711 }3712 3647 3713 3648 #ifdef GIP_TSC_DELTA_METHOD_1 3714 supdrvTscDeltaMethod1Delete(&Args);3649 supdrvTscDeltaMethod1Delete(pArgs); 3715 3650 #elif defined(GIP_TSC_DELTA_METHOD_2) 3716 supdrvTscDeltaMethod2Delete(&Args);3651 supdrvTscDeltaMethod2Delete(pArgs); 3717 3652 #else 3718 3653 # error "huh?" 3719 3654 #endif 3655 RTMemFree(pArgs); 3656 } 3657 else 3658 rc = VERR_NO_MEMORY; 3720 3659 } 3721 3660 else 3722 3661 rc = VERR_CPU_OFFLINE; 3723 3662 3724 ASMAtomicWriteU32(&pDevExt->idTscDeltaInitiator, NIL_RTCPUID); 3663 /* 3664 * We're done now. 3665 */ 3666 #ifdef SUPDRV_USE_MUTEX_FOR_GIP 3667 rc2 = RTSemMutexRelease(pDevExt->mtxTscDelta); AssertRC(rc2); 3668 #else 3669 rc2 = RTSemFastMutexRelease(pDevExt->mtxTscDelta); AssertRC(rc2); 3670 #endif 3725 3671 return rc; 3726 3672 } … … 3747 3693 ASMAtomicWriteS64(&pGipCpu->i64TSCDelta, INT64_MAX); 3748 3694 } 3749 ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP);3750 3695 } 3751 3696
Note:
See TracChangeset
for help on using the changeset viewer.