From 66a99f619fe1a24f9ff6797d56d417fbf23cb0ef Mon Sep 17 00:00:00 2001 From: Yonggang Luo Date: Sun, 12 Feb 2023 00:15:19 +0800 Subject: [PATCH] c11: Improve timespec_get to support TIME_MONOTONIC TIME_ACTIVE TIME_THREAD_ACTIVE TIME_MONOTONIC_RAW As c11 already provided timespec_get, to avoid symbol conflict, use c23_timespec_get as the function name and define timespec_get c23_timespec_get to achieve that Signed-off-by: Yonggang Luo Reviewed-by: Jesse Natalie Acked-by: David Heidelberg Part-of: --- meson.build | 1 - src/c11/impl/time.c | 71 ++++++++++++++++++++++++++++++++++++++++----- src/c11/time.h | 35 ++++++++++++++++++---- 3 files changed, 93 insertions(+), 14 deletions(-) diff --git a/meson.build b/meson.build index ad5070eac7e..5238d6f0640 100644 --- a/meson.build +++ b/meson.build @@ -1282,7 +1282,6 @@ endforeach functions_to_detect = { 'strtof': '', 'mkostemp': '', - 'timespec_get': '#include ', 'memfd_create': '', 'random_r': '', 'flock': '', diff --git a/src/c11/impl/time.c b/src/c11/impl/time.c index f99788c0fea..55575cb01e8 100644 --- a/src/c11/impl/time.c +++ b/src/c11/impl/time.c @@ -30,14 +30,24 @@ #include "c11/time.h" -#ifndef HAVE_TIMESPEC_GET +#ifdef _TIMESPEC_GET_NEED_IMPL #if defined(_WIN32) && !defined(HAVE_PTHREAD) +#include "c11/threads.h" #include +static LARGE_INTEGER frequency; + +static +void +c23_timespec_get_init(void) +{ + QueryPerformanceFrequency(&frequency); +} + int -timespec_get(struct timespec *ts, int base) +c23_timespec_get(struct timespec *ts, int base) { /* difference between 1970 and 1601 */ #define _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS 116444736000000000ull @@ -57,6 +67,25 @@ timespec_get(struct timespec *ts, int base) ts->tv_sec = ticks / _TIMESPEC_IMPL_TICKS_PER_SECONDS; ts->tv_nsec = (ticks % _TIMESPEC_IMPL_TICKS_PER_SECONDS) * 100; return base; + } else if (base == TIME_MONOTONIC || base == TIME_MONOTONIC_RAW) { + if (frequency.QuadPart == 0) { + static once_flag once = ONCE_FLAG_INIT; + call_once(&once, c23_timespec_get_init); + } + if (frequency.QuadPart != 0) { + LARGE_INTEGER now; + LONGLONG sec; + LONGLONG nsec; + QueryPerformanceCounter(&now); + sec = now.QuadPart / frequency.QuadPart; + nsec = (now.QuadPart - sec * frequency.QuadPart) + * 1000000000UL / frequency.QuadPart; + ts->tv_sec = (time_t)sec; + ts->tv_nsec = (long)nsec; + return base; + } + /* Otherwise timespec_get with TIME_MONOTONIC or TIME_MONOTONIC_RAW failed */ + return 0; } return 0; #undef _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS @@ -65,14 +94,42 @@ timespec_get(struct timespec *ts, int base) #else -int -timespec_get(struct timespec *ts, int base) +int c23_timespec_get(struct timespec *ts, int base) { if (!ts) return 0; - if (base == TIME_UTC) { - clock_gettime(CLOCK_REALTIME, ts); - return base; + switch (base) + { + case TIME_UTC: + if (clock_gettime(CLOCK_REALTIME, ts) == 0) + return base; + break; +#ifdef CLOCK_MONOTONIC + case TIME_MONOTONIC: + if (clock_gettime(CLOCK_MONOTONIC, ts) == 0) + return base; + break; +#endif +#ifdef CLOCK_PROCESS_CPUTIME_ID + case TIME_ACTIVE: + if (clock_gettime(CLOCK_PROCESS_CPUTIME_ID, ts) == 0) + return base; + break; +#endif +#ifdef CLOCK_THREAD_CPUTIME_ID + case TIME_THREAD_ACTIVE: + if (clock_gettime(CLOCK_THREAD_CPUTIME_ID, ts) == 0) + return base; + break; +#endif +#ifdef CLOCK_MONOTONIC_RAW + case TIME_MONOTONIC_RAW: + if (clock_gettime(CLOCK_MONOTONIC_RAW, ts) == 0) + return base; + break; +#endif + default: + break; } return 0; } diff --git a/src/c11/time.h b/src/c11/time.h index b9f779c83d3..33762f893b9 100644 --- a/src/c11/time.h +++ b/src/c11/time.h @@ -12,8 +12,31 @@ /*---------------------------- macros ---------------------------*/ -#ifndef TIME_UTC +/* Refer to https://htmlpreview.github.io/?https://icube-forge.unistra.fr/icps/c23-library/-/raw/main/README.html#time_monotonic-time_active-time_thread_active */ +#if defined(TIME_UTC) && \ + defined(TIME_MONOTONIC) && \ + defined(TIME_ACTIVE) && \ + defined(TIME_THREAD_ACTIVE) && \ + defined(TIME_MONOTONIC_RAW) +/* all needed time base is implemented */ +#else +#define _TIMESPEC_GET_NEED_IMPL +#endif + +#ifdef _TIMESPEC_GET_NEED_IMPL +#undef TIME_UTC +#undef TIME_MONOTONIC +#undef TIME_ACTIVE +#undef TIME_THREAD_ACTIVE +#undef TIME_MONOTONIC_RAW +/* c11 */ #define TIME_UTC 1 +/* c23 */ +#define TIME_MONOTONIC 2 +#define TIME_ACTIVE 3 +#define TIME_THREAD_ACTIVE 4 +#define TIME_MONOTONIC_RAW 5 +#define timespec_get c23_timespec_get #endif #ifdef __cplusplus @@ -37,22 +60,22 @@ struct timespec /*-------------------------- functions --------------------------*/ -#if !defined(HAVE_TIMESPEC_GET) -#define _HAVE_TIMESPEC_GET_NEED_DECL +#if defined(_TIMESPEC_GET_NEED_IMPL) +#define _TIMESPEC_GET_NEED_DECL #elif defined(__APPLE__) && defined(__cplusplus) && (__cplusplus < 201703L) /* On macOS, the guard for declaration of timespec_get is by * (defined(__cplusplus) && __cplusplus >= 201703L), * fix the declaration for C++14 and lower here */ -#define _HAVE_TIMESPEC_GET_NEED_DECL +#define _TIMESPEC_GET_NEED_DECL #endif -#ifdef _HAVE_TIMESPEC_GET_NEED_DECL +#ifdef _TIMESPEC_GET_NEED_DECL /*-------------------- 7.25.7 Time functions --------------------*/ // 7.25.6.1 int timespec_get(struct timespec *ts, int base); -#undef _HAVE_TIMESPEC_GET_NEED_DECL +#undef _TIMESPEC_GET_NEED_DECL #endif #ifdef __cplusplus