diff options
Diffstat (limited to 'pjlib/src/pj')
-rw-r--r-- | pjlib/src/pj/os_core_win32.c | 4 | ||||
-rw-r--r-- | pjlib/src/pj/os_timestamp_common.c | 58 | ||||
-rw-r--r-- | pjlib/src/pj/os_timestamp_win32.c | 71 |
3 files changed, 128 insertions, 5 deletions
diff --git a/pjlib/src/pj/os_core_win32.c b/pjlib/src/pj/os_core_win32.c index 91add770..756b88a8 100644 --- a/pjlib/src/pj/os_core_win32.c +++ b/pjlib/src/pj/os_core_win32.c @@ -161,8 +161,10 @@ PJ_DEF(pj_status_t) pj_init(void) #if defined(PJ_HAS_HIGH_RES_TIMER) && PJ_HAS_HIGH_RES_TIMER != 0 { pj_timestamp dummy_ts; + if ((rc=pj_get_timestamp_freq(&dummy_ts)) != PJ_SUCCESS) { + return rc; + } if ((rc=pj_get_timestamp(&dummy_ts)) != PJ_SUCCESS) { - PJ_LOG(1, ("pj_init", "Unable to initialize timestamp")); return rc; } } diff --git a/pjlib/src/pj/os_timestamp_common.c b/pjlib/src/pj/os_timestamp_common.c index 4dc410f3..a86c1746 100644 --- a/pjlib/src/pj/os_timestamp_common.c +++ b/pjlib/src/pj/os_timestamp_common.c @@ -26,9 +26,14 @@ #define USEC (1000000UL) #define MSEC (1000) +#define u64tohighprec(u64) ((pj_highprec_t)((pj_int64_t)(u64))) + static pj_highprec_t get_elapsed( const pj_timestamp *start, const pj_timestamp *stop ) { +#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0 + return u64tohighprec(stop->u64 - start->u64); +#else pj_highprec_t elapsed_hi, elapsed_lo; elapsed_hi = stop->u32.hi - start->u32.hi; @@ -38,6 +43,38 @@ static pj_highprec_t get_elapsed( const pj_timestamp *start, pj_highprec_mul(elapsed_hi, U32MAX); return elapsed_hi + elapsed_lo; +#endif +} + +static pj_highprec_t elapsed_msec( const pj_timestamp *start, + const pj_timestamp *stop ) +{ + pj_timestamp ts_freq; + pj_highprec_t freq, elapsed; + + if (pj_get_timestamp_freq(&ts_freq) != PJ_SUCCESS) + return 0; + + /* Convert frequency timestamp */ +#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0 + freq = u64tohighprec(ts_freq.u64); +#else + freq = ts_freq.u32.hi; + pj_highprec_mul(freq, U32MAX); + freq += ts_freq.u32.lo; +#endif + + /* Avoid division by zero. */ + if (freq == 0) freq = 1; + + /* Get elapsed time in cycles. */ + elapsed = get_elapsed(start, stop); + + /* usec = elapsed * MSEC / freq */ + pj_highprec_mul(elapsed, MSEC); + pj_highprec_div(elapsed, freq); + + return elapsed; } static pj_highprec_t elapsed_usec( const pj_timestamp *start, @@ -50,9 +87,13 @@ static pj_highprec_t elapsed_usec( const pj_timestamp *start, return 0; /* Convert frequency timestamp */ +#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0 + freq = u64tohighprec(ts_freq.u64); +#else freq = ts_freq.u32.hi; pj_highprec_mul(freq, U32MAX); freq += ts_freq.u32.lo; +#endif /* Avoid division by zero. */ if (freq == 0) freq = 1; @@ -77,9 +118,13 @@ PJ_DEF(pj_uint32_t) pj_elapsed_nanosec( const pj_timestamp *start, return 0; /* Convert frequency timestamp */ +#if defined(PJ_HAS_INT64) && PJ_HAS_INT64!=0 + freq = u64tohighprec(ts_freq.u64); +#else freq = ts_freq.u32.hi; pj_highprec_mul(freq, U32MAX); freq += ts_freq.u32.lo; +#endif /* Avoid division by zero. */ if (freq == 0) freq = 1; @@ -100,10 +145,16 @@ PJ_DEF(pj_uint32_t) pj_elapsed_usec( const pj_timestamp *start, return (pj_uint32_t)elapsed_usec(start, stop); } +PJ_DEF(pj_uint32_t) pj_elapsed_msec( const pj_timestamp *start, + const pj_timestamp *stop ) +{ + return (pj_uint32_t)elapsed_msec(start, stop); +} + PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start, const pj_timestamp *stop ) { - pj_highprec_t elapsed = elapsed_usec(start, stop); + pj_highprec_t elapsed = elapsed_msec(start, stop); pj_time_val tv_elapsed; if (PJ_HIGHPREC_VALUE_IS_ZERO(elapsed)) { @@ -113,12 +164,11 @@ PJ_DEF(pj_time_val) pj_elapsed_time( const pj_timestamp *start, pj_highprec_t sec, msec; sec = elapsed; - pj_highprec_div(sec, USEC); + pj_highprec_div(sec, MSEC); tv_elapsed.sec = (long)sec; msec = elapsed; - pj_highprec_mod(msec, USEC); - pj_highprec_div(msec, 1000); + pj_highprec_mod(msec, MSEC); tv_elapsed.msec = (long)msec; return tv_elapsed; diff --git a/pjlib/src/pj/os_timestamp_win32.c b/pjlib/src/pj/os_timestamp_win32.c index eeff6c00..757a3000 100644 --- a/pjlib/src/pj/os_timestamp_win32.c +++ b/pjlib/src/pj/os_timestamp_win32.c @@ -20,6 +20,75 @@ #include <pj/errno.h> #include <windows.h> +#if defined(PJ_TIMESTAMP_USE_RDTSC) && PJ_TIMESTAMP_USE_RDTSC!=0 && \ + defined(PJ_M_I386) && PJ_M_I386 != 0 && \ + defined(_MSC_VER) +/* + * Use rdtsc to get the OS timestamp. + */ +static LONG CpuMhz; +static pj_int64_t CpuHz; + +static pj_status_t GetCpuHz(void) +{ + HKEY key; + LONG rc; + DWORD size; + + rc = RegOpenKey( HKEY_LOCAL_MACHINE, + "HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0", + &key); + if (rc != ERROR_SUCCESS) + return PJ_RETURN_OS_ERROR(rc); + + size = sizeof(CpuMhz); + rc = RegQueryValueEx(key, "~MHz", NULL, NULL, (BYTE*)&CpuMhz, &size); + RegCloseKey(key); + + if (rc != ERROR_SUCCESS) { + return PJ_RETURN_OS_ERROR(rc); + } + + CpuHz = CpuMhz; + CpuHz = CpuHz * 1000000; + + return PJ_SUCCESS; +} + +/* __int64 is nicely returned in EDX:EAX */ +__declspec(naked) __int64 rdtsc() +{ + __asm + { + RDTSC + RET + } +} + +PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts) +{ + ts->u64 = rdtsc(); + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq) +{ + pj_status_t status; + + if (CpuHz == 0) { + status = GetCpuHz(); + if (status != PJ_SUCCESS) + return status; + } + + freq->u64 = CpuHz; + return PJ_SUCCESS; +} + +#else +/* + * Use QueryPerformanceCounter and QueryPerformanceFrequency. + */ PJ_DEF(pj_status_t) pj_get_timestamp(pj_timestamp *ts) { LARGE_INTEGER val; @@ -42,3 +111,5 @@ PJ_DEF(pj_status_t) pj_get_timestamp_freq(pj_timestamp *freq) return PJ_SUCCESS; } +#endif /* PJ_TIMESTAMP_USE_RDTSC */ + |