VirtualBox

Ignore:
Timestamp:
Feb 23, 2015 10:41:10 AM (10 years ago)
Author:
vboxsync
Message:

SUPDrvGip.cpp: Replaced idTscDeltaInitiator+RTThreadSleep(1) with a mutex semaphore. Allocate the SUPDRVGIPTSCDELTARGS structure (stack might be swappable, also don't waste it). Remove old sync code.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp

    r54371 r54375  
    13851385    ASMAtomicIncU32(&pDevExt->cMpOnOffEvents);
    13861386
    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 
    13941387    if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED)
    13951388    {
     
    18051798    LogFlow(("supdrvGipCreate:\n"));
    18061799
    1807     /* Assert order. */
     1800    /*
     1801     * Assert order.
     1802     */
    18081803    Assert(pDevExt->u32SystemTimerGranularityGrant == 0);
    18091804    Assert(pDevExt->GipMemObj == NIL_RTR0MEMOBJ);
    18101805    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
    18111813
    18121814    /*
     
    18321834    pGip = (PSUPGLOBALINFOPAGE)RTR0MemObjAddress(pDevExt->GipMemObj); AssertPtr(pGip);
    18331835    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);
    18411836
    18421837    /*
     
    20462041    }
    20472042
    2048     if (pDevExt->pvTscDeltaSync)
    2049     {
    2050         RTMemFree(pDevExt->pvTscDeltaSync);
    2051         pDevExt->pTscDeltaSync  = NULL;
    2052         pDevExt->pvTscDeltaSync = NULL;
    2053     }
    2054 
    20552043    /*
    20562044     * Invalid the GIP data.
     
    26352623 * @{
    26362624 */
    2637 #if 0
    2638 #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 #else
    2679 
    26802625#if defined(DEBUG_bird) && defined(RT_OS_WINDOWS)
    26812626# 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)
    26842629#else
    26852630# define TSCDELTA_DBG_VARS()            ((void)0)
     
    28472792}
    28482793
    2849 #define TSCDELTA_MASTER_SYNC_BEFORE(a_pSync1, a_pMySync, a_pOtherSync) \
     2794#define TSCDELTA_MASTER_SYNC_BEFORE(a_pMySync, a_pOtherSync) \
    28502795    do { \
    28512796        if (RT_LIKELY(supdrvTscDeltaSync2_Before(a_pMySync, a_pOtherSync, true /*fMaster*/, &uFlags))) \
     
    28532798        else break; \
    28542799    } while (0)
    2855 #define TSCDELTA_OTHER_SYNC_BEFORE(a_pSync1, a_pMySync, a_pOtherSync, a_MidSyncExpr) \
     2800#define TSCDELTA_OTHER_SYNC_BEFORE(a_pMySync, a_pOtherSync) \
    28562801    do { \
    28572802        if (RT_LIKELY(supdrvTscDeltaSync2_Before(a_pMySync, a_pOtherSync, false /*fMaster*/, &uFlags))) \
     
    28602805    } while (0)
    28612806
    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
     2808static 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; \
    28822838    } while (0)
    28832839
    2884 #define TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \
     2840#define TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(a_pMySync, a_pOtherSync) \
    28852841    do {\
    28862842        /* \
     
    28942850    } while (0)
    28952851
    2896 
    2897 #define TSCDELTA_OTHER_SYNC_AFTER(a_pSync1, a_pMySync, a_pOtherSync) \
     2852#define TSCDELTA_OTHER_SYNC_AFTER(a_pMySync, a_pOtherSync) \
    28982853    do { \
    28992854        /* \
    2900          * Tell the master that we're done and wait for the data to be processed and the next round to start. \
     2855         * Tell the master that we're done collecting data and wait for the next round to start. \
    29012856         */ \
    2902         uint32_t u32Tmp; \
    2903         TSCDELTA_DBG_VARS(); \
    29042857        if (!ASMAtomicCmpXchgU32(&(a_pOtherSync)->uSyncVar, GIP_TSC_DELTA_SYNC2_READY, GIP_TSC_DELTA_SYNC2_GO)) \
    29052858        { \
     
    29072860            break; \
    29082861        } \
    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; \
    29222865    } while (0)
    2923 #endif
    29242866/** @} */
    29252867
     
    29532895 *
    29542896 * @param   pArgs               The argument/state data.
    2955  * @param   pSync1              The synchronization structure
    2956  *                              (pDevExt->pTscDeltaSync).
     2897 * @param   pMySync             My synchronization structure.
     2898 * @param   pOtherSync          My partner's synchronization structure.
    29572899 * @param   fIsMaster           Set if master, clear if worker.
    29582900 * @param   iTry                The attempt number.
    29592901 */
    2960 static void supdrvTscDeltaMethod1Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC pSync1,
    2961                                       PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync, bool fIsMaster, uint32_t iTry)
     2902static void supdrvTscDeltaMethod1Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync,
     2903                                      bool fIsMaster, uint32_t iTry)
    29622904{
    29632905    PSUPGIPCPU  pGipCpuWorker   = pArgs->pWorker;
     
    29782920                      ("%#llx idMaster=%#x idWorker=%#x (idGipMaster=%#x)\n",
    29792921                       pGipCpuMaster->u64TSCSample, pGipCpuMaster->idCpu, pGipCpuWorker->idCpu, pArgs->pDevExt->idGipMaster));
    2980             TSCDELTA_MASTER_SYNC_BEFORE(pSync1, pMySync, pOtherSync);
     2922            TSCDELTA_MASTER_SYNC_BEFORE(pMySync, pOtherSync);
    29812923
    29822924            do
     
    29862928            } while (pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD);
    29872929
    2988             TSCDELTA_MASTER_SYNC_AFTER(pSync1, pMySync, pOtherSync);
     2930            TSCDELTA_MASTER_SYNC_AFTER(pMySync, pOtherSync);
    29892931
    29902932            /* Process the data. */
     
    30042946            /* Reset our TSC sample and tell the worker to move on. */
    30052947            ASMAtomicWriteU64(&pGipCpuMaster->u64TSCSample, GIP_TSC_DELTA_RSVD);
    3006             TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(pSync1, pMySync, pOtherSync);
     2948            TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(pMySync, pOtherSync);
    30072949        }
    30082950        else
     
    30162958
    30172959            ASMAtomicReadU64(&pGipCpuMaster->u64TSCSample);     /* Warm the cache line. */
    3018             TSCDELTA_OTHER_SYNC_BEFORE(pSync1, pMySync, pOtherSync, Assert(pGipCpuMaster->u64TSCSample == GIP_TSC_DELTA_RSVD));
     2960            TSCDELTA_OTHER_SYNC_BEFORE(pMySync, pOtherSync);
    30192961
    30202962            /*
     
    30512993            }
    30522994
    3053             TSCDELTA_OTHER_SYNC_AFTER(pSync1, pMySync, pOtherSync);
     2995            TSCDELTA_OTHER_SYNC_AFTER(pMySync, pOtherSync);
    30542996        }
    30552997    }
     
    32203162 *
    32213163 * @param   pArgs               The argument/state data.
    3222  * @param   pSync1               The synchronization structure
    3223  *                              (pDevExt->pTscDeltaSync).
     3164 * @param   pMySync             My synchronization structure.
     3165 * @param   pOtherSync          My partner's synchronization structure.
    32243166 * @param   fIsMaster           Set if master, clear if worker.
    32253167 * @param   iTry                The attempt number.
    32263168 */
    3227 static void supdrvTscDeltaMethod2Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC pSync1,
    3228                                       PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync, bool fIsMaster, uint32_t iTry)
     3169static void supdrvTscDeltaMethod2Loop(PSUPDRVGIPTSCDELTARGS pArgs, PSUPTSCDELTASYNC2 pMySync, PSUPTSCDELTASYNC2 pOtherSync,
     3170                                      bool fIsMaster, uint32_t iTry)
    32293171{
    32303172    unsigned iLoop;
     
    32723214             * Sync up with the worker and collect data.
    32733215             */
    3274             TSCDELTA_MASTER_SYNC_BEFORE(pSync1, pMySync, pOtherSync);
     3216            TSCDELTA_MASTER_SYNC_BEFORE(pMySync, pOtherSync);
    32753217            supdrvTscDeltaMethod2CollectData(pArgs->M2.pMasterData, &pArgs->M2.pWorkerData->iCurSeqNo, pArgs->M2.fLagMaster);
    3276             TSCDELTA_MASTER_SYNC_AFTER(pSync1, pMySync, pOtherSync);
     3218            TSCDELTA_MASTER_SYNC_AFTER(pMySync, pOtherSync);
    32773219
    32783220            /*
     
    32843226                supdrvTscDeltaMethod2ProcessDataOnMaster(pArgs, iLoop);
    32853227
    3286             TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(pSync1, pMySync, pOtherSync);
     3228            TSCDELTA_MASTER_KICK_OTHER_OUT_OF_AFTER(pMySync, pOtherSync);
    32873229        }
    32883230        else
     
    32913233             * The worker.
    32923234             */
    3293             TSCDELTA_OTHER_SYNC_BEFORE(pSync1, pMySync, pOtherSync, (void)0);
     3235            TSCDELTA_OTHER_SYNC_BEFORE(pMySync, pOtherSync);
    32943236            supdrvTscDeltaMethod2CollectData(pArgs->M2.pWorkerData, &pArgs->M2.pMasterData->iCurSeqNo, pArgs->M2.fLagWorker);
    3295             TSCDELTA_OTHER_SYNC_AFTER(pSync1, pMySync, pOtherSync);
     3237            TSCDELTA_OTHER_SYNC_AFTER(pMySync, pOtherSync);
    32963238        }
    32973239
     
    33463288    PSUPTSCDELTASYNC2 volatile *ppMySync    = fIsMaster ? &pArgs->pSyncMaster : &pArgs->pSyncWorker;
    33473289    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();
    33513291
    33523292    /*
     
    33603300     * sync state again (would cause stack corruption).
    33613301     */
     3302    TSCDELTA_DBG_START_LOOP();
    33623303    while (ASMAtomicReadPtrT(ppOtherSync, PSUPTSCDELTASYNC2) != NULL)
    33633304    {
     
    33653306        ASMNopPause();
    33663307        ASMNopPause();
    3367 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS)
    3368 if (++iTry == 0) __debugbreak();
    3369 #endif
     3308        TSCDELTA_DBG_CHECK_LOOP();
    33703309    }
    33713310
     
    33953334{
    33963335    PSUPDRVDEVEXT               pDevExt          = pArgs->pDevExt;
    3397     PSUPTSCDELTASYNC            pSync1           = pDevExt->pTscDeltaSync;
    33983336    PSUPGIPCPU                  pGipCpuWorker    = pArgs->pWorker;
    33993337    PSUPGIPCPU                  pGipCpuMaster    = pArgs->pMaster;
     
    34043342    SUPTSCDELTASYNC2            MySync;
    34053343    PSUPTSCDELTASYNC2           pOtherSync;
     3344    TSCDELTA_DBG_VARS();
    34063345
    34073346    /* A bit of paranoia first. */
     
    34313370    /* Look for the partner, might not be here yet... Special abort considerations. */
    34323371    iTry = 0;
     3372    TSCDELTA_DBG_START_LOOP();
    34333373    while ((pOtherSync = ASMAtomicReadPtrT(ppOtherSync, PSUPTSCDELTASYNC2)) == NULL)
    34343374    {
     
    34403380            && ASMReadTSC() - MySync.uTscStart > pArgs->cMaxTscTicks)
    34413381            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();
    34453383        ASMNopPause();
    34463384    }
     
    34523390
    34533391    iTry = 0;
     3392    TSCDELTA_DBG_START_LOOP();
    34543393    while (ASMAtomicReadU32(&MySync.uSyncVar) == GIP_TSC_DELTA_SYNC2_PRESTART_WAIT)
    34553394    {
     
    34653404            return supdrvMeasureTscDeltaCallbackAbortSyncSetup(pArgs, &MySync, fIsMaster, true /*fTimeout*/);
    34663405        }
    3467 #if defined(DEBUG_bird) && defined(RT_OS_WINDOWS)
    3468 if (iTry == 0) __debugbreak();
    3469 #endif
     3406        TSCDELTA_DBG_CHECK_LOOP();
    34703407    }
    34713408
     
    34873424         */
    34883425#ifdef GIP_TSC_DELTA_METHOD_1
    3489         supdrvTscDeltaMethod1Loop(pArgs, pSync1, &MySync, pOtherSync, fIsMaster, iTry);
     3426        supdrvTscDeltaMethod1Loop(pArgs, &MySync, pOtherSync, fIsMaster, iTry);
    34903427#elif defined(GIP_TSC_DELTA_METHOD_2)
    3491         supdrvTscDeltaMethod2Loop(pArgs, pSync1, &MySync, pOtherSync, fIsMaster, iTry);
     3428        supdrvTscDeltaMethod2Loop(pArgs, &MySync, pOtherSync, fIsMaster, iTry);
    34923429#else
    34933430# error "huh??"
     
    35223459    ASMAtomicWriteNullPtr(ppMySync);
    35233460    iTry = 0;
     3461    TSCDELTA_DBG_START_LOOP();
    35243462    while (ASMAtomicReadU32(&MySync.uSyncVar) != GIP_TSC_DELTA_SYNC2_FINAL)
    35253463    {
     
    35283466            && !RTMpIsCpuOnline(fIsMaster ? pGipCpuWorker->idCpu : pGipCpuWorker->idCpu))
    35293467            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();
    35333469        ASMNopPause();
    35343470    }
     
    35673503{
    35683504    int                 rc;
     3505    int                 rc2;
    35693506    PSUPGLOBALINFOPAGE  pGip          = pDevExt->pGip;
    35703507    RTCPUID             idMaster      = pDevExt->idGipMaster;
     
    35873524        return VINF_SUCCESS;
    35883525    }
     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;
    35893538
    35903539    /*
     
    36293578    }
    36303579
    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 we
    3635      *        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 measurement
    3640          * being executed and that can take a good while to be done.
    3641          */
    3642         RTThreadSleep(1);
    3643     }
    3644 
    36453580    if (RTCpuSetIsMemberByIndex(&pGip->OnlineCpuSet, pGipCpuWorker->iCpuSet))
    36463581    {
     
    36513586         */
    36523587        /** @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;
    36603596#if 0 /* later */
    3661         Args.cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 2048; /* 488 us */
     3597            pArgs->cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 2048; /* 488 us */
    36623598#else
    3663         Args.cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 1024; /* 976 us */
     3599            pArgs->cMaxTscTicks = ASMAtomicReadU64(&pGip->u64CpuHz) / 1024; /* 976 us */
    36643600#endif
    36653601
    36663602#ifdef GIP_TSC_DELTA_METHOD_1
    3667         rc = supdrvTscDeltaMethod1Init(&Args);
     3603            rc = supdrvTscDeltaMethod1Init(pArgs);
    36683604#elif defined(GIP_TSC_DELTA_METHOD_2)
    3669         rc = supdrvTscDeltaMethod2Init(&Args);
     3605            rc = supdrvTscDeltaMethod2Init(pArgs);
    36703606#else
    36713607# error "huh?"
    36723608#endif
    3673         if (RT_SUCCESS(rc))
    3674         {
    3675             /*
    3676              * Fire TSC-read workers on all CPUs but only synchronize between master
    3677              * 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);
    36843609            if (RT_SUCCESS(rc))
    36853610            {
    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))
    36873620                {
    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                    }
    36993642                    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;
    37063644                }
    3707                 else
    3708                     rc = VERR_SUPDRV_TSC_DELTA_MEASUREMENT_FAILED;
     3645                /** @todo return try-again if we get an offline CPU error.   */
    37093646            }
    3710             /** @todo return try-again if we get an offline CPU error.   */
    3711         }
    37123647
    37133648#ifdef GIP_TSC_DELTA_METHOD_1
    3714         supdrvTscDeltaMethod1Delete(&Args);
     3649            supdrvTscDeltaMethod1Delete(pArgs);
    37153650#elif defined(GIP_TSC_DELTA_METHOD_2)
    3716         supdrvTscDeltaMethod2Delete(&Args);
     3651            supdrvTscDeltaMethod2Delete(pArgs);
    37173652#else
    37183653# error "huh?"
    37193654#endif
     3655            RTMemFree(pArgs);
     3656        }
     3657        else
     3658            rc = VERR_NO_MEMORY;
    37203659    }
    37213660    else
    37223661        rc = VERR_CPU_OFFLINE;
    37233662
    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
    37253671    return rc;
    37263672}
     
    37473693            ASMAtomicWriteS64(&pGipCpu->i64TSCDelta, INT64_MAX);
    37483694    }
    3749     ASMAtomicWriteU32(&pDevExt->pTscDeltaSync->u, GIP_TSC_DELTA_SYNC_STOP);
    37503695}
    37513696
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette