rsys

Basic data structures and low-level features
git clone git://git.meso-star.fr/rsys.git
Log | Files | Refs | README | LICENSE

commit ba86a79ba534c1b802121737718d5640486da028
parent 5deb09eaf8f1d91b87d7458a9f810a9cbace8c82
Author: vaplv <vaplv@free.fr>
Date:   Fri, 29 Nov 2013 11:38:32 +0100

Use more accurate timing functions on Unix platforms

Diffstat:
Msrc/CMakeLists.txt | 3+--
Msrc/clock_time.c | 42+++++++++++++++++++++++++++++++++++++++++-
Msrc/clock_time.h | 41+++++++++++++++++++++++++++++++----------
Msrc/test_time.c | 21++++++++++++++++-----
4 files changed, 89 insertions(+), 18 deletions(-)

diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt @@ -44,7 +44,7 @@ set(RSYS_FILES_INC rsys.h) add_library(rsys SHARED ${RSYS_FILES_SRC} ${RSYS_FILES_INC}) -target_link_libraries(rsys dl) +target_link_libraries(rsys dl rt) set_target_properties(rsys PROPERTIES DEFINE_SYMBOL RSYS_SHARED_BUILD) ################################################################################ @@ -76,7 +76,6 @@ add_test(test_atomic test_atomic) add_executable(test_ref test_ref.c) add_test(test_ref test_ref) - if(NOT OPENMP_FOUND) message(STATUS "No OpenMP support: multi-threaded tests cannot be generated") else() diff --git a/src/clock_time.c b/src/clock_time.c @@ -3,7 +3,7 @@ #include <string.h> #define TIME_TO_NSEC(Time) \ - (((Time)->tv_usec + (Time)->tv_sec * 1000000L) * 1000L) + ((Time)->tv_nsec + (Time)->tv_sec * 1000000000L) #define NSEC_PER_USEC 1000L #define NSEC_PER_MSEC (1000L * NSEC_PER_USEC) @@ -12,6 +12,46 @@ #define NSEC_PER_HOUR (60L * NSEC_PER_MIN) #define NSEC_PER_DAY (24L * NSEC_PER_HOUR) +void +time_val_set(time_T* time, const int64_t val, const enum time_unit unit) +{ + int64_t ns = 0; + int64_t s = 0; + + if(unit & (TIME_NSEC | TIME_USEC | TIME_MSEC)) { + switch(unit) { + case TIME_NSEC: + s = val / 1000000000L; + ns = val - s * 1000000000L; + break; + case TIME_USEC: + s = val / 1000000L; + ns = (val - s * 1000000L) * 1000L; + break; + case TIME_MSEC: + s = val / 1000L; + ns = (val - s * 1000L) * 1000000L; + break; + default: + ASSERT(0 && "Unreachable code"); + break; + } + } else { + int64_t factor = 0; + switch(unit) { + case TIME_SEC: factor = 0L; break; + case TIME_MIN: factor = 60L; break; + case TIME_HOUR: factor = 3600L; break; + case TIME_DAY: factor = 86400L; break; + default: ASSERT(0 && "Unreachable code"); break; + } + s = val * factor; + ns = 0; + } + time->tv_sec = s; + time->tv_nsec = ns; +} + int64_t time_val(const time_T* time, enum time_unit unit) { diff --git a/src/clock_time.h b/src/clock_time.h @@ -2,13 +2,22 @@ #define TIME_H #include "rsys.h" -#ifndef PLATFORM_UNIX +#if !defined(PLATFORM_UNIX) \ + || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE < 200112L) #error "Unsupported platform" #endif -#include <sys/time.h> + +#ifdef _POSIX_C_SOURCE + #include <time.h> +#else + #define _POSIX_C_SOURCE 200112L + #include <time.h> + #undef _POSIX_C_SOURCE +#endif + #include <stddef.h> -typedef struct timeval time_T; +typedef struct timespec time_T; enum time_unit { TIME_NSEC = BIT(0), @@ -25,20 +34,26 @@ time_current(time_T* time) { int err = 0; (void) err; ASSERT(time); - err = gettimeofday(time, NULL); + err = clock_gettime(CLOCK_REALTIME, time); ASSERT(err == 0); } static FINLINE void +time_sleep(const time_T* time) +{ + clock_nanosleep(CLOCK_REALTIME, 0, time, NULL); +} + +static FINLINE void time_sub(time_T* res, const time_T* a, const time_T* b) { ASSERT(res && a && b); res->tv_sec = a->tv_sec - b->tv_sec; - res->tv_usec = a->tv_usec - b->tv_usec; - if(res->tv_usec < 0) { + res->tv_nsec = a->tv_nsec - b->tv_nsec; + if(res->tv_nsec < 0) { --res->tv_sec; - res->tv_usec += 1000000L; + res->tv_nsec += 1000000000L; } } @@ -48,10 +63,10 @@ time_add(time_T* res, const time_T* a, const time_T* b) ASSERT(res && a && b); res->tv_sec = a->tv_sec + b->tv_sec; - res->tv_usec = a->tv_usec + b->tv_usec; - if(res->tv_usec >= 1000000L) { + res->tv_nsec = a->tv_nsec + b->tv_nsec; + if(res->tv_nsec >= 1000000000L) { ++res->tv_sec; - res->tv_usec -= 1000000L; + res->tv_nsec -= 1000000000L; } } @@ -59,6 +74,12 @@ time_add(time_T* res, const time_T* a, const time_T* b) extern "C" { #endif +RSYS_API void +time_val_set + (time_T* time, + const int64_t val, + const enum time_unit unit); + RSYS_API int64_t time_val (const time_T* time, diff --git a/src/test_time.c b/src/test_time.c @@ -10,19 +10,30 @@ main(int argc, char** argv) int64_t time = 0; (void)argc, (void)argv; + time_val_set(&res, 1250, TIME_MSEC); time_current(&start); - sleep(2); + time_sleep(&res); time_current(&end); time_sub(&res, &end, &start); time = time_val(&res, TIME_NSEC); - CHECK(llabs((long long)(time - 2000000000)) <= 1000000 , 1); + CHECK(llabs((long long)(time - 1250000000)) <= 1000000 , 1); time = time_val(&res, TIME_USEC); - CHECK(llabs((long long)(time - 2000000)) <= 1000 , 1); + CHECK(llabs((long long)(time - 1250000)) <= 1000 , 1); time = time_val(&res, TIME_MSEC); - CHECK(llabs((long long)(time - 2000)) <= 1 , 1); + CHECK(llabs((long long)(time - 1250)) <= 1 , 1); time = time_val(&res, TIME_SEC); - CHECK(llabs((long long)(time - 2)) <= 0 , 1); + CHECK(time, 1); + CHECK(time_val(&res, TIME_NSEC) >= time_val(&res, TIME_USEC) * 1000, 1); + CHECK(time_val(&res, TIME_USEC) >= time_val(&res, TIME_MSEC) * 1000, 1); + CHECK(time_val(&res, TIME_MSEC) >= time_val(&res, TIME_SEC) * 1000, 1); + time_val_set(&res, 1234, TIME_USEC); + time_current(&start); + time_sleep(&res); + time_current(&end); + time_sub(&res, &end, &start); + time = time_val(&res, TIME_NSEC); + CHECK(llabs((long long)(time - 1234000)) <= 1000000 , 1); return 0; }