| /* |
| * C11 <time.h> implementation |
| * |
| * (C) Copyright yohhoy 2012. |
| * Copyright 2022 Yonggang Luo |
| * Distributed under the Boost Software License, Version 1.0. |
| * |
| * Permission is hereby granted, free of charge, to any person or organization |
| * obtaining a copy of the software and accompanying documentation covered by |
| * this license (the "Software") to use, reproduce, display, distribute, |
| * execute, and transmit the Software, and to prepare [[derivative work]]s of the |
| * Software, and to permit third-parties to whom the Software is furnished to |
| * do so, all subject to the following: |
| * |
| * The copyright notices in the Software and this entire statement, including |
| * the above license grant, this restriction and the following disclaimer, |
| * must be included in all copies of the Software, in whole or in part, and |
| * all derivative works of the Software, unless such copies or derivative |
| * works are solely in the form of machine-executable object code generated by |
| * a source language processor. |
| * |
| * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
| * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT |
| * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE |
| * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, |
| * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
| * DEALINGS IN THE SOFTWARE. |
| */ |
| |
| #include "c11/time.h" |
| |
| #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 |
| c23_timespec_get(struct timespec *ts, int base) |
| { |
| /* difference between 1970 and 1601 */ |
| #define _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS 116444736000000000ull |
| /* 1 tick is 100 nanoseconds */ |
| #define _TIMESPEC_IMPL_TICKS_PER_SECONDS 10000000ull |
| if (!ts) |
| return 0; |
| if (base == TIME_UTC) { |
| FILETIME ft; |
| ULARGE_INTEGER date; |
| LONGLONG ticks; |
| |
| GetSystemTimeAsFileTime(&ft); |
| date.HighPart = ft.dwHighDateTime; |
| date.LowPart = ft.dwLowDateTime; |
| ticks = (LONGLONG)(date.QuadPart - _TIMESPEC_IMPL_UNIX_EPOCH_IN_TICKS); |
| 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 |
| #undef _TIMESPEC_IMPL_TICKS_PER_SECONDS |
| } |
| |
| #else |
| |
| int c23_timespec_get(struct timespec *ts, int base) |
| { |
| if (!ts) |
| return 0; |
| 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; |
| } |
| #endif |
| |
| #endif /* !HAVE_TIMESPEC_GET */ |