From 7ffc73fe67ebd88410ce1094d83d6e4809ffb578 Mon Sep 17 00:00:00 2001 From: Josh Blum Date: Sun, 30 Jan 2011 19:08:30 -0800 Subject: uhd: implemented high-res get time in time_spec_t clock_gettime for linux, mach_absolute_time for macos, QueryPerformanceFrequency for windows, and fallback to boost microsec_clock --- host/lib/types/CMakeLists.txt | 55 ++++++++++++++++++++++++++++++++ host/lib/types/time_spec.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) (limited to 'host/lib/types') diff --git a/host/lib/types/CMakeLists.txt b/host/lib/types/CMakeLists.txt index dfb7cf903..bcc04e08d 100644 --- a/host/lib/types/CMakeLists.txt +++ b/host/lib/types/CMakeLists.txt @@ -15,6 +15,61 @@ # along with this program. If not, see . # +######################################################################## +# Setup defines for high resolution timing +######################################################################## +MESSAGE(STATUS "") +MESSAGE(STATUS "Configuring high resolution timing...") +INCLUDE(CheckCXXSourceCompiles) + +SET(CMAKE_REQUIRED_LIBRARIES -lrt) +CHECK_CXX_SOURCE_COMPILES(" + #include + int main(){ + timespec ts; + return clock_gettime(CLOCK_MONOTONIC, &ts); + } + " HAVE_CLOCK_GETTIME +) +UNSET(CMAKE_REQUIRED_LIBRARIES) + +INCLUDE(CheckCXXSourceCompiles) +CHECK_CXX_SOURCE_COMPILES(" + #include + int main(){ + mach_timebase_info_data_t info; + mach_timebase_info(&info); + mach_absolute_time(); + return 0; + } + " HAVE_MACH_ABSOLUTE_TIME +) + +CHECK_CXX_SOURCE_COMPILES(" + #include + int main(){ + LARGE_INTEGER value; + QueryPerformanceCounter(&value); + QueryPerformanceFrequency(&value); + return 0; + } + " HAVE_QUERY_PERFORMANCE_COUNTER +) + +IF(HAVE_CLOCK_GETTIME) + MESSAGE(STATUS " High resolution timing supported through clock_gettime.") + ADD_DEFINITIONS(-DTIME_SPEC_USE_GETTIME) +ELSEIF(HAVE_MACH_ABSOLUTE_TIME) + MESSAGE(STATUS " High resolution timing supported through mach_absolute_time.") + ADD_DEFINITIONS(-DTIME_SPEC_USE_MACH_ABSOLUTE_TIME) +ELSEIF(HAVE_QUERY_PERFORMANCE_COUNTER) + MESSAGE(STATUS " High resolution timing supported through QueryPerformanceCounter.") + ADD_DEFINITIONS(-DTIME_SPEC_USE_QUERY_PERFORMANCE_COUNTER) +ELSE() + MESSAGE(STATUS " High resolution timing supported though microsec_clock.") + ADD_DEFINITIONS(-DTIME_SPEC_USE_MICROSEC_CLOCK) +ENDIF() + ######################################################################## # This file included, use CMake directory variables ######################################################################## diff --git a/host/lib/types/time_spec.cpp b/host/lib/types/time_spec.cpp index f39625a11..312c161cb 100644 --- a/host/lib/types/time_spec.cpp +++ b/host/lib/types/time_spec.cpp @@ -19,6 +19,73 @@ #include using namespace uhd; + +/*********************************************************************** + * Time spec system time + **********************************************************************/ + +/*! + * Creates a time spec from system counts: + * TODO make part of API as a static factory function + * The counts type is 64 bits and will overflow the ticks type of long. + * Therefore, divmod the counts into seconds + sub-second counts first. + */ +#include //imaxdiv, intmax_t +static UHD_INLINE time_spec_t time_spec_t_from_counts(intmax_t counts, intmax_t freq){ + imaxdiv_t divres = imaxdiv(counts, freq); + return time_spec_t(time_t(divres.quot), double(divres.rem)/freq); +} + +#ifdef TIME_SPEC_USE_CLOCK_GETTIME +#include +time_spec_t time_spec_t::get_system_time(void){ + timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); + return time_spec_t(ts.tv_sec, ts.tv_nsec, 1e9); +} +#endif /* TIME_SPEC_USE_CLOCK_GETTIME */ + + +#ifdef TIME_SPEC_USE_MACH_ABSOLUTE_TIME +#include +static intmax_t get_freq(void){ + mach_timebase_info_data_t info; mach_timebase_info(&info); + return intmax_t(1e9*(double(info.denom)/double(info.numer))); +} +time_spec_t time_spec_t::get_system_time(void){ + static const intmax_t freq = get_freq(); + return time_spec_t_from_counts(mach_absolute_time(), freq); +} +#endif /* TIME_SPEC_USE_MACH_ABSOLUTE_TIME */ + + +#ifdef TIME_SPEC_USE_QUERY_PERFORMANCE_COUNTER +#include +time_spec_t time_spec_t::get_system_time(void){ + LARGE_INTEGER counts, freq; + QueryPerformanceCounter(&counts); + QueryPerformanceFrequency(&freq); + return time_spec_t_from_counts(counts.QuadPart, freq.QuadPart); +} +#endif /* TIME_SPEC_USE_QUERY_PERFORMANCE_COUNTER */ + + +#ifdef TIME_SPEC_USE_MICROSEC_CLOCK +#include +namespace pt = boost::posix_time; +time_spec_t time_spec_t::get_system_time(void){ + pt::ptime time_now = pt::microsec_clock::universal_time(); + pt::time_duration time_dur = time_now - pt::from_time_t(0); + return time_spec_t( + time_t(time_dur.total_seconds()), + long(time_dur.fractional_seconds()), + double(pt::time_duration::ticks_per_second()) + ); +} +#endif /* TIME_SPEC_USE_MICROSEC_CLOCK */ + +/*********************************************************************** + * Time spec constructors + **********************************************************************/ time_spec_t::time_spec_t(double secs): _full_secs(0), _frac_secs(secs) @@ -40,6 +107,9 @@ time_spec_t::time_spec_t(time_t full_secs, long tick_count, double tick_rate): /* NOP */ } +/*********************************************************************** + * Time spec accessors + **********************************************************************/ long time_spec_t::get_tick_count(double tick_rate) const{ return boost::math::iround(this->get_frac_secs()*tick_rate); } @@ -58,6 +128,9 @@ double time_spec_t::get_frac_secs(void) const{ return std::fmod(this->_frac_secs, 1.0); } +/*********************************************************************** + * Time spec math overloads + **********************************************************************/ time_spec_t &time_spec_t::operator+=(const time_spec_t &rhs){ this->_full_secs += rhs.get_full_secs(); this->_frac_secs += rhs.get_frac_secs(); -- cgit v1.2.3