mirror of
https://github.com/zeromq/libzmq.git
synced 2025-01-02 19:35:29 +08:00
Merge pull request #742 from psl-felipefarinon/master
Fixing issue #583. Using low resolution timer for clock::now_ms
This commit is contained in:
commit
de5a787868
@ -22,6 +22,7 @@
|
|||||||
#include "likely.hpp"
|
#include "likely.hpp"
|
||||||
#include "config.hpp"
|
#include "config.hpp"
|
||||||
#include "err.hpp"
|
#include "err.hpp"
|
||||||
|
#include "mutex.hpp"
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@ -41,9 +42,47 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef ULONGLONG (*f_compatible_get_tick_count64)();
|
||||||
|
|
||||||
|
static zmq::mutex_t compatible_get_tick_count64_mutex;
|
||||||
|
|
||||||
|
ULONGLONG compatible_get_tick_count64()
|
||||||
|
{
|
||||||
|
compatible_get_tick_count64_mutex.lock();
|
||||||
|
static DWORD s_wrap = 0;
|
||||||
|
static DWORD s_last_tick = 0;
|
||||||
|
const DWORD current_tick = ::GetTickCount();
|
||||||
|
if (current_tick < s_last_tick)
|
||||||
|
++s_wrap;
|
||||||
|
|
||||||
|
s_last_tick = current_tick;
|
||||||
|
const ULONGLONG result = (static_cast<ULONGLONG>(s_wrap) << 32) + static_cast<ULONGLONG>(current_tick);
|
||||||
|
compatible_get_tick_count64_mutex.unlock();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
f_compatible_get_tick_count64 init_compatible_get_tick_count64()
|
||||||
|
{
|
||||||
|
f_compatible_get_tick_count64 func = NULL;
|
||||||
|
HMODULE module = ::LoadLibraryA("Kernel32.dll");
|
||||||
|
if (module != NULL)
|
||||||
|
func = reinterpret_cast<f_compatible_get_tick_count64>(::GetProcAddress(module, "GetTickCount64"));
|
||||||
|
|
||||||
|
if (func == NULL)
|
||||||
|
func = compatible_get_tick_count64;
|
||||||
|
|
||||||
|
return func;
|
||||||
|
}
|
||||||
|
|
||||||
|
static f_compatible_get_tick_count64 my_get_tick_count64 = init_compatible_get_tick_count64();
|
||||||
|
|
||||||
zmq::clock_t::clock_t () :
|
zmq::clock_t::clock_t () :
|
||||||
last_tsc (rdtsc ()),
|
last_tsc (rdtsc ()),
|
||||||
|
#ifdef ZMQ_HAVE_WINDOWS
|
||||||
|
last_time (static_cast<uint64_t>((*my_get_tick_count64)()))
|
||||||
|
#else
|
||||||
last_time (now_us () / 1000)
|
last_time (now_us () / 1000)
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,7 +104,7 @@ uint64_t zmq::clock_t::now_us ()
|
|||||||
|
|
||||||
// Convert the tick number into the number of seconds
|
// Convert the tick number into the number of seconds
|
||||||
// since the system was started.
|
// since the system was started.
|
||||||
double ticks_div = ticksPerSecond.QuadPart / 1000000.0;
|
double ticks_div = ticksPerSecond.QuadPart / 1000000.0;
|
||||||
return (uint64_t) (tick.QuadPart / ticks_div);
|
return (uint64_t) (tick.QuadPart / ticks_div);
|
||||||
|
|
||||||
#elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC
|
#elif defined HAVE_CLOCK_GETTIME && defined CLOCK_MONOTONIC
|
||||||
@ -74,7 +113,7 @@ uint64_t zmq::clock_t::now_us ()
|
|||||||
struct timespec tv;
|
struct timespec tv;
|
||||||
int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
|
int rc = clock_gettime (CLOCK_MONOTONIC, &tv);
|
||||||
// Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
|
// Fix case where system has clock_gettime but CLOCK_MONOTONIC is not supported.
|
||||||
// This should be a configuration check, but I looked into it and writing an
|
// This should be a configuration check, but I looked into it and writing an
|
||||||
// AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
|
// AC_FUNC_CLOCK_MONOTONIC seems beyond my powers.
|
||||||
if( rc != 0) {
|
if( rc != 0) {
|
||||||
// Use POSIX gettimeofday function to get precise time.
|
// Use POSIX gettimeofday function to get precise time.
|
||||||
@ -106,7 +145,18 @@ uint64_t zmq::clock_t::now_ms ()
|
|||||||
|
|
||||||
// If TSC is not supported, get precise time and chop off the microseconds.
|
// If TSC is not supported, get precise time and chop off the microseconds.
|
||||||
if (!tsc)
|
if (!tsc)
|
||||||
|
{
|
||||||
|
#ifdef ZMQ_HAVE_WINDOWS
|
||||||
|
// Under Windows, now_us is not so reliable since QueryPerformanceCounter
|
||||||
|
// does not guarantee that it will use a hardware that offers a monotonic timer.
|
||||||
|
// So, lets use GetTickCount when GetTickCount64 is not available with an workaround
|
||||||
|
// to its 32 bit limitation.
|
||||||
|
static_assert(sizeof(uint64_t) >= sizeof(ULONGLONG), "Loosing timer information");
|
||||||
|
return static_cast<uint64_t>((*my_get_tick_count64)());
|
||||||
|
#else
|
||||||
return now_us () / 1000;
|
return now_us () / 1000;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// If TSC haven't jumped back (in case of migration to a different
|
// If TSC haven't jumped back (in case of migration to a different
|
||||||
// CPU core) and if not too much time elapsed since last measurement,
|
// CPU core) and if not too much time elapsed since last measurement,
|
||||||
@ -115,7 +165,11 @@ uint64_t zmq::clock_t::now_ms ()
|
|||||||
return last_time;
|
return last_time;
|
||||||
|
|
||||||
last_tsc = tsc;
|
last_tsc = tsc;
|
||||||
|
#ifdef ZMQ_HAVE_WINDOWS
|
||||||
|
last_time = static_cast<uint64_t>((*my_get_tick_count64)());
|
||||||
|
#else
|
||||||
last_time = now_us () / 1000;
|
last_time = now_us () / 1000;
|
||||||
|
#endif
|
||||||
return last_time;
|
return last_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user