VirtualBox

Changeset 54278 in vbox


Ignore:
Timestamp:
Feb 18, 2015 7:42:01 PM (10 years ago)
Author:
vboxsync
Message:

timesupref.h: Moved things around a little, avoiding the 'break' statement. Mostly pointless from a performance point of view (windows at least).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/time/timesupref.h

    r54270 r54278  
    4444RTDECL(uint64_t) rtTimeNanoTSInternalRef(PRTTIMENANOTSDATA pData)
    4545{
    46     uint64_t    u64Delta;
    47 #if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
    48     int64_t     i64TscDelta;
    49 # ifdef IN_RING3
    50     PSUPGIPCPU  pGipCpuAttemptedTscRecalibration = NULL;
    51 # endif
    52 #endif
    53     uint32_t    u32NanoTSFactor0;
    54     uint64_t    u64TSC;
    55     uint64_t    u64NanoTS;
    56     uint32_t    u32UpdateIntervalTSC;
    57     uint64_t    u64PrevNanoTS;
     46#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA && defined(IN_RING3)
     47    PSUPGIPCPU pGipCpuAttemptedTscRecalibration = NULL;
     48#endif
    5849    AssertCompile(RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS));
    5950
    60     /*
    61      * Read the GIP data and the previous value.
    62      */
    6351    for (;;)
    6452    {
     
    147135                 * without triggering serializing twice.
    148136                 */
    149                 u32NanoTSFactor0        = pGip->u32UpdateIntervalNS;
     137                uint32_t u32NanoTSFactor0       = pGip->u32UpdateIntervalNS;
    150138#if TMPL_MODE == TMPL_MODE_ASYNC
    151                 u32UpdateIntervalTSC    = pGipCpu->u32UpdateIntervalTSC;
    152                 u64NanoTS               = pGipCpu->u64NanoTS;
    153                 u64TSC                  = pGipCpu->u64TSC;
    154 #else
    155                 u32UpdateIntervalTSC    = pGip->aCPUs[0].u32UpdateIntervalTSC;
    156                 u64NanoTS               = pGip->aCPUs[0].u64NanoTS;
    157                 u64TSC                  = pGip->aCPUs[0].u64TSC;
     139                uint32_t u32UpdateIntervalTSC   = pGipCpu->u32UpdateIntervalTSC;
     140                uint64_t u64NanoTS              = pGipCpu->u64NanoTS;
     141                uint64_t u64TSC                 = pGipCpu->u64TSC;
     142#else
     143                uint32_t u32UpdateIntervalTSC   = pGip->aCPUs[0].u32UpdateIntervalTSC;
     144                uint64_t u64NanoTS              = pGip->aCPUs[0].u64NanoTS;
     145                uint64_t u64TSC                 = pGip->aCPUs[0].u64TSC;
    158146# if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA
    159                 i64TscDelta             = pGipCpu->i64TSCDelta;
    160 # endif
    161 #endif
     147                int64_t i64TscDelta             = pGipCpu->i64TSCDelta;
     148# endif
     149#endif
     150                uint64_t u64PrevNanoTS          = ASMAtomicUoReadU64(pData->pu64Prev);
    162151#if TMPL_GET_CPU_METHOD == SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS
    163                 u64PrevNanoTS           = ASMAtomicUoReadU64(pData->pu64Prev);
    164152                ASMCompilerBarrier();
    165153                uint32_t uAux2;
    166                 u64Delta                = ASMReadTscWithAux(&uAux2); /* serializing */
    167 #else
    168                 u64Delta                = ASMReadTSC();
    169                 u64PrevNanoTS           = ASMAtomicUoReadU64(pData->pu64Prev);
     154                uint64_t u64Delta               = ASMReadTscWithAux(&uAux2); /* serializing */
     155#else
     156                uint64_t u64Delta               = ASMReadTSC();
    170157                ASMCompilerBarrier();
    171158# if TMPL_GET_CPU_METHOD != SUPGIPGETCPU_APIC_ID /* getting APIC will serialize  */ \
     
    222209                            ASMSetFlags(uFlags);
    223210#endif
    224                             break;
     211
     212                            /*
     213                             * Calc NanoTS delta.
     214                             */
     215                            u64Delta -= u64TSC;
     216                            if (RT_LIKELY(u64Delta <= u32UpdateIntervalTSC))
     217                            { /* MSVC branch hint, probably pointless. */ }
     218                            else
     219                            {
     220                                /*
     221                                 * We've expired the interval, cap it. If we're here for the 2nd
     222                                 * time without any GIP update in-between, the checks against
     223                                 * *pu64Prev below will force 1ns stepping.
     224                                 */
     225                                ASMAtomicIncU32(&pData->cExpired++);
     226                                u64Delta = u32UpdateIntervalTSC;
     227                            }
     228#if !defined(_MSC_VER) || !defined(RT_ARCH_X86) /* GCC makes very pretty code from these two inline calls, while MSC cannot. */
     229                            u64Delta = ASMMult2xU32RetU64((uint32_t)u64Delta, u32NanoTSFactor0);
     230                            u64Delta = ASMDivU64ByU32RetU32(u64Delta, u32UpdateIntervalTSC);
     231#else
     232                            __asm
     233                            {
     234                                mov     eax, dword ptr [u64Delta]
     235                                mul     dword ptr [u32NanoTSFactor0]
     236                                div     dword ptr [u32UpdateIntervalTSC]
     237                                mov     dword ptr [u64Delta], eax
     238                                xor     edx, edx
     239                                mov     dword ptr [u64Delta + 4], edx
     240                            }
     241#endif
     242
     243                            /*
     244                             * Calculate the time and compare it with the previously returned value.
     245                             */
     246                            u64NanoTS += u64Delta;
     247                            uint64_t u64DeltaPrev = u64NanoTS - u64PrevNanoTS;
     248                            if (RT_LIKELY(   u64DeltaPrev > 0
     249                                          && u64DeltaPrev < UINT64_C(86000000000000) /* 24h */))
     250                            { /* Frequent - less than 24h since last call. */ }
     251                            else if (RT_LIKELY(   (int64_t)u64DeltaPrev <= 0
     252                                               && (int64_t)u64DeltaPrev + u32NanoTSFactor0 * 2 >= 0))
     253                            {
     254                                /* Occasional - u64NanoTS is in the recent 'past' relative the previous call. */
     255                                ASMAtomicIncU32(&pData->c1nsSteps);
     256                                u64NanoTS = u64PrevNanoTS + 1;
     257                            }
     258                            else if (!u64PrevNanoTS)
     259                                /* We're resuming (see TMVirtualResume). */;
     260                            else
     261                            {
     262                                /* Something has gone bust, if negative offset it's real bad. */
     263                                ASMAtomicIncU32(&pData->cBadPrev);
     264                                pData->pfnBad(pData, u64NanoTS, u64DeltaPrev, u64PrevNanoTS);
     265                            }
     266
     267                            /*
     268                             * Attempt updating the previous value, provided we're still ahead of it.
     269                             *
     270                             * There is no point in recalculating u64NanoTS because we got preempted or if
     271                             * we raced somebody while the GIP was updated, since these are events
     272                             * that might occur at any point in the return path as well.
     273                             */
     274                            if (RT_LIKELY(ASMAtomicCmpXchgU64(pData->pu64Prev, u64NanoTS, u64PrevNanoTS)))
     275                                return u64NanoTS;
     276
     277                            ASMAtomicIncU32(&pData->cUpdateRaces);
     278                            for (int cTries = 25; cTries > 0; cTries--)
     279                            {
     280                                u64PrevNanoTS = ASMAtomicReadU64(pData->pu64Prev);
     281                                if (u64PrevNanoTS >= u64NanoTS)
     282                                    break;
     283                                if (ASMAtomicCmpXchgU64(pData->pu64Prev, u64NanoTS, u64PrevNanoTS))
     284                                    break;
     285                                ASMNopPause();
     286                            }
     287                            return u64NanoTS;
    225288                        }
     289
    226290#if TMPL_MODE == TMPL_MODE_SYNC_INVAR_WITH_DELTA && defined(IN_RING3)
    227291                        /*
     
    284348        return pData->pfnRediscover(pData);
    285349    }
    286 
    287     /*
    288      * Calc NanoTS delta.
    289      */
    290     u64Delta -= u64TSC;
    291     if (RT_UNLIKELY(u64Delta > u32UpdateIntervalTSC))
    292     {
    293         /*
    294          * We've expired the interval, cap it. If we're here for the 2nd
    295          * time without any GIP update in-between, the checks against
    296          * *pu64Prev below will force 1ns stepping.
    297          */
    298         pData->cExpired++;
    299         u64Delta = u32UpdateIntervalTSC;
    300     }
    301 #if !defined(_MSC_VER) || defined(RT_ARCH_AMD64) /* GCC makes very pretty code from these two inline calls, while MSC cannot. */
    302     u64Delta = ASMMult2xU32RetU64((uint32_t)u64Delta, u32NanoTSFactor0);
    303     u64Delta = ASMDivU64ByU32RetU32(u64Delta, u32UpdateIntervalTSC);
    304 #else
    305     __asm
    306     {
    307         mov     eax, dword ptr [u64Delta]
    308         mul     dword ptr [u32NanoTSFactor0]
    309         div     dword ptr [u32UpdateIntervalTSC]
    310         mov     dword ptr [u64Delta], eax
    311         xor     edx, edx
    312         mov     dword ptr [u64Delta + 4], edx
    313     }
    314 #endif
    315 
    316     /*
    317      * Calculate the time and compare it with the previously returned value.
    318      */
    319     u64NanoTS += u64Delta;
    320     uint64_t u64DeltaPrev = u64NanoTS - u64PrevNanoTS;
    321     if (RT_LIKELY(   u64DeltaPrev > 0
    322                   && u64DeltaPrev < UINT64_C(86000000000000) /* 24h */))
    323         /* Frequent - less than 24h since last call. */;
    324     else if (RT_LIKELY(   (int64_t)u64DeltaPrev <= 0
    325                        && (int64_t)u64DeltaPrev + u32NanoTSFactor0 * 2 >= 0))
    326     {
    327         /* Occasional - u64NanoTS is in the recent 'past' relative the previous call. */
    328         ASMAtomicIncU32(&pData->c1nsSteps);
    329         u64NanoTS = u64PrevNanoTS + 1;
    330     }
    331     else if (!u64PrevNanoTS)
    332         /* We're resuming (see TMVirtualResume). */;
    333     else
    334     {
    335         /* Something has gone bust, if negative offset it's real bad. */
    336         ASMAtomicIncU32(&pData->cBadPrev);
    337         pData->pfnBad(pData, u64NanoTS, u64DeltaPrev, u64PrevNanoTS);
    338     }
    339 
    340     if (RT_UNLIKELY(!ASMAtomicCmpXchgU64(pData->pu64Prev, u64NanoTS, u64PrevNanoTS)))
    341     {
    342         /*
    343          * Attempt updating the previous value, provided we're still ahead of it.
    344          *
    345          * There is no point in recalculating u64NanoTS because we got preempted or if
    346          * we raced somebody while the GIP was updated, since these are events
    347          * that might occur at any point in the return path as well.
    348          */
    349         pData->cUpdateRaces++;
    350         for (int cTries = 25; cTries > 0; cTries--)
    351         {
    352             u64PrevNanoTS = ASMAtomicReadU64(pData->pu64Prev);
    353             if (u64PrevNanoTS >= u64NanoTS)
    354                 break;
    355             if (ASMAtomicCmpXchgU64(pData->pu64Prev, u64NanoTS, u64PrevNanoTS))
    356                 break;
    357         }
    358     }
    359     return u64NanoTS;
    360350}
    361351
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