VirtualBox

Ignore:
Timestamp:
Jun 6, 2008 12:19:12 PM (17 years ago)
Author:
vboxsync
Message:

Generic timer code for async GIP mode.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/HostDrivers/Support/SUPDRVShared.c

    r9444 r9470  
    253253static int      supdrvGipCreate(PSUPDRVDEVEXT pDevExt);
    254254static void     supdrvGipDestroy(PSUPDRVDEVEXT pDevExt);
    255 static DECLCALLBACK(void) supdrvGipTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     255static DECLCALLBACK(void) supdrvGipSyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     256static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick);
     257static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser);
    256258#endif
    257259
     
    37483750
    37493751    /*
    3750      * Find a reasonable update interval, something close to 10ms would be nice,
    3751      * and create a recurring timer.
     3752     * Find a reasonable update interval and initialize the structure.
    37523753     */
    37533754    u32Interval = u32SystemResolution = RTTimerGetSystemGranularity();
     
    37553756        u32Interval += u32SystemResolution;
    37563757
    3757     rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0, supdrvGipTimer, pDevExt);
    3758     if (RT_FAILURE(rc))
    3759     {
    3760         OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %RU32 ns interval. rc=%d\n", u32Interval, rc));
     3758    supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/);
     3759
     3760    /*
     3761     * Create the timer.
     3762     * If CPU_ALL isn't supported we'll have to fall back to synchronous mode.
     3763     */
     3764    if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
     3765    {
     3766        rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, RTTIMER_FLAGS_CPU_ALL, supdrvGipAsyncTimer, pDevExt);
     3767        if (rc == VERR_NOT_SUPPORTED)
     3768        {
     3769            OSDBGPRINT(("supdrvGipCreate: omni timer not supported, falling back to synchronous mode\n"));
     3770            pGip->u32Mode = SUPGIPMODE_SYNC_TSC;
     3771        }
     3772    }
     3773    if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC)
     3774        rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0, supdrvGipSyncTimer, pDevExt);
     3775    if (RT_SUCCESS(rc))
     3776    {
     3777        if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC)
     3778            rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt);
     3779        if (RT_SUCCESS(rc))
     3780        {
     3781            /*
     3782             * We're good.
     3783             */
     3784            dprintf(("supdrvGipCreate: %ld ns interval.\n", (long)u32Interval));
     3785            return VINF_SUCCESS;
     3786        }
     3787
     3788        OSDBGPRINT(("supdrvGipCreate: failed register MP event notfication. rc=%d\n", rc));
     3789    }
     3790    else
     3791    {
     3792        OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %ld ns interval. rc=%d\n", (long)u32Interval, rc));
    37613793        Assert(!pDevExt->pGipTimer);
    3762         supdrvGipDestroy(pDevExt);
    3763         return rc;
    3764     }
    3765 
    3766     /*
    3767      * We're good.
    3768      */
    3769     supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), 1000000000 / u32Interval /*=Hz*/);
    3770     return VINF_SUCCESS;
     3794    }
     3795    supdrvGipDestroy(pDevExt);
     3796    return rc;
    37713797}
    37723798
     
    38223848
    38233849/**
    3824  * Timer callback function.
     3850 * Timer callback function sync GIP mode.
    38253851 * @param   pTimer      The timer.
    38263852 * @param   pvUser      The device extension.
    3827  * @param   iTick       The current tick.
    3828  */
    3829 static DECLCALLBACK(void) supdrvGipTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     3853 */
     3854static DECLCALLBACK(void) supdrvGipSyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
    38303855{
    38313856    PSUPDRVDEVEXT pDevExt  = (PSUPDRVDEVEXT)pvUser;
    38323857    supdrvGipUpdate(pDevExt->pGip, RTTimeSystemNanoTS());
    3833     NOREF(iTick);
    3834 }
     3858}
     3859
     3860
     3861/**
     3862 * Timer callback function for async GIP mode.
     3863 * @param   pTimer      The timer.
     3864 * @param   pvUser      The device extension.
     3865 */
     3866static DECLCALLBACK(void) supdrvGipAsyncTimer(PRTTIMER pTimer, void *pvUser, uint64_t iTick)
     3867{
     3868    PSUPDRVDEVEXT   pDevExt = (PSUPDRVDEVEXT)pvUser;
     3869    RTCPUID         idCpu   = RTMpCpuId();
     3870    uint64_t        NanoTS  = RTTimeSystemNanoTS();
     3871
     3872    if (pDevExt->idGipMaster == idCpu)
     3873        supdrvGipUpdate(pDevExt->pGip, NanoTS);
     3874    else
     3875        supdrvGipUpdatePerCpu(pDevExt->pGip, NanoTS, ASMGetApicId());
     3876}
     3877
     3878
     3879/**
     3880 * Multiprocessor event notification callback.
     3881 *
     3882 * This is used to make sue that the GIP master gets passed on to
     3883 * another CPU.
     3884 *
     3885 * @param   enmEvent    The event.
     3886 * @param   idCpu       The cpu it applies to.
     3887 * @param   pvUser      Pointer to the device extension.
     3888 */
     3889static DECLCALLBACK(void) supdrvGipMpEvent(RTMPEVENT enmEvent, RTCPUID idCpu, void *pvUser)
     3890{
     3891    PSUPDRVDEVEXT   pDevExt = (PSUPDRVDEVEXT)pvUser;
     3892    if (enmEvent == RTMPEVENT_OFFLINE)
     3893    {
     3894        RTCPUID idGipMaster;
     3895        ASMAtomicReadSize(&pDevExt->idGipMaster, &idGipMaster);
     3896        if (idGipMaster == idCpu)
     3897        {
     3898            /*
     3899             * Find a new GIP master.
     3900             */
     3901            bool        fIgnored;
     3902            unsigned    i;
     3903            RTCPUID     idNewGipMaster = NIL_RTCPUID;
     3904            RTCPUSET    OnlineCpus;
     3905            RTMpGetOnlineSet(&OnlineCpus);
     3906
     3907            for (i = 0; i < RTCPUSET_MAX_CPUS; i++)
     3908            {
     3909                RTCPUID idCurCpu = RTMpCpuIdFromSetIndex(i);
     3910                if (    RTCpuSetIsMember(&OnlineCpus, idCurCpu)
     3911                    &&  idCurCpu != idGipMaster)
     3912                {
     3913                    idNewGipMaster = idCurCpu;
     3914                    break;
     3915                }
     3916            }
     3917
     3918            dprintf(("supdrvGipMpEvent: Gip master %#lx -> %#lx\n", (long)idGipMaster, (long)idNewGipMaster));
     3919            ASMAtomicCmpXchgSize(&pDevExt->idGipMaster, idNewGipMaster, idGipMaster, fIgnored);
     3920            NOREF(fIgnored);
     3921        }
     3922    }
     3923}
     3924
    38353925#endif /* USE_NEW_OS_INTERFACE_FOR_GIP */
    38363926
     
    39073997static SUPGIPMODE supdrvGipDeterminTscMode(PSUPDRVDEVEXT pDevExt)
    39083998{
    3909 #ifndef USE_NEW_OS_INTERFACE_FOR_GIP
    39103999    /*
    39114000     * The problem here is that AMD processors with power management features
     
    39194008     * can be relied upon to have somewhat uniform TSC between the cpus.
    39204009     */
     4010# ifdef RT_OS_WINDOWS /** @todo fix RTMpGetCount() wrt to IRQL. */
    39214011    if (supdrvOSGetCPUCount(pDevExt) > 1)
     4012# else
     4013    if (RTMpGetCount() > 1)
     4014# endif
    39224015    {
    39234016        uint32_t uEAX, uEBX, uECX, uEDX;
    39244017
    3925         /* Permit user users override. */
     4018        /* Permit the user and/or the OS specfic bits to force async mode. */
    39264019        if (supdrvOSGetForcedAsyncTscMode(pDevExt))
    39274020            return SUPGIPMODE_ASYNC_TSC;
     4021
     4022        /** @todo perform supdrvDetermineAsyncTsc here! */
    39284023
    39294024        /* Check for "AuthenticAMD" */
     
    39344029            &&  uEDX == X86_CPUID_VENDOR_AMD_EDX)
    39354030        {
     4031            /** @todo This is probably wrong. TscInvariant doesn't seem to mean that RdTSC returns the
     4032             * value everywhere, but rather that the rate is supposed to be the same. */
    39364033            /* Check for APM support and that TscInvariant is cleared. */
    39374034            ASMCpuId(0x80000000, &uEAX, &uEBX, &uECX, &uEDX);
     
    39454042        }
    39464043    }
    3947 #endif
    39484044    return SUPGIPMODE_SYNC_TSC;
    39494045}
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