#include "c11/time.h"
-#ifndef HAVE_TIMESPEC_GET
+#ifdef _TIMESPEC_GET_NEED_IMPL
#if defined(_WIN32) && !defined(HAVE_PTHREAD)
+#include "c11/threads.h"
#include <windows.h>
+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
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
#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;
}
/*---------------------------- 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
/*-------------------------- 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