unix,win: add uv_clock_gettime() (#3971)

Fixes: https://github.com/libuv/libuv/issues/1674
This commit is contained in:
Ben Noordhuis 2023-04-27 22:13:46 +02:00 committed by GitHub
parent e02642cf3b
commit c8a1e6132b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 14 deletions

View File

@ -30,7 +30,8 @@ Data types
.. c:type:: uv_timespec_t
Portable equivalent of ``struct timespec``.
Y2K38-unsafe data type for storing times with nanosecond resolution.
Will be replaced with :c:type:`uv_timespec64_t` in libuv v2.0.
::

View File

@ -73,7 +73,8 @@ Data types
.. c:type:: uv_timeval_t
Data type for storing times.
Y2K38-unsafe data type for storing times with microsecond resolution.
Will be replaced with :c:type:`uv_timeval64_t` in libuv v2.0.
::
@ -84,7 +85,7 @@ Data types
.. c:type:: uv_timeval64_t
Alternative data type for storing times.
Y2K38-safe data type for storing times with microsecond resolution.
::
@ -93,6 +94,28 @@ Data types
int32_t tv_usec;
} uv_timeval64_t;
.. c:type:: uv_timespec64_t
Y2K38-safe data type for storing times with nanosecond resolution.
::
typedef struct {
int64_t tv_sec;
int32_t tv_nsec;
} uv_timespec64_t;
.. c:enum:: uv_clock_id
Clock source for :c:func:`uv_clock_gettime`.
::
typedef enum {
UV_CLOCK_MONOTONIC,
UV_CLOCK_REALTIME
} uv_clock_id;
.. c:type:: uv_rusage_t
Data type for resource usage results.
@ -588,7 +611,7 @@ API
.. c:function:: uint64_t uv_hrtime(void)
Returns the current high-resolution real time. This is expressed in
Returns the current high-resolution timestamp. This is expressed in
nanoseconds. It is relative to an arbitrary time in the past. It is not
related to the time of day and therefore not subject to clock drift. The
primary use is for measuring performance between intervals.
@ -597,6 +620,19 @@ API
Not every platform can support nanosecond resolution; however, this value will always
be in nanoseconds.
.. c:function:: int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts)
Obtain the current system time from a high-resolution real-time or monotonic
clock source.
The real-time clock counts from the UNIX epoch (1970-01-01) and is subject
to time adjustments; it can jump back in time.
The monotonic clock counts from an arbitrary point in the past and never
jumps back in time.
.. versionadded:: 1.45.0
.. c:function:: void uv_print_all_handles(uv_loop_t* loop, FILE* stream)
Prints all handles associated with the given `loop` to the given `stream`.

View File

@ -345,11 +345,32 @@ typedef void (*uv_random_cb)(uv_random_t* req,
void* buf,
size_t buflen);
typedef enum {
UV_CLOCK_MONOTONIC,
UV_CLOCK_REALTIME
} uv_clock_id;
/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
typedef struct {
long tv_sec;
long tv_nsec;
} uv_timespec_t;
typedef struct {
int64_t tv_sec;
int32_t tv_nsec;
} uv_timespec64_t;
/* XXX(bnoordhuis) not 2038-proof, https://github.com/libuv/libuv/issues/3864 */
typedef struct {
long tv_sec;
long tv_usec;
} uv_timeval_t;
typedef struct {
int64_t tv_sec;
int32_t tv_usec;
} uv_timeval64_t;
typedef struct {
uint64_t st_dev;
@ -1191,16 +1212,6 @@ UV_EXTERN int uv_uptime(double* uptime);
UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd);
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd);
typedef struct {
long tv_sec;
long tv_usec;
} uv_timeval_t;
typedef struct {
int64_t tv_sec;
int32_t tv_usec;
} uv_timeval64_t;
typedef struct {
uv_timeval_t ru_utime; /* user CPU time used */
uv_timeval_t ru_stime; /* system CPU time used */
@ -1732,6 +1743,7 @@ UV_EXTERN uint64_t uv_get_total_memory(void);
UV_EXTERN uint64_t uv_get_constrained_memory(void);
UV_EXTERN uint64_t uv_get_available_memory(void);
UV_EXTERN int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts);
UV_EXTERN uint64_t uv_hrtime(void);
UV_EXTERN void uv_sleep(unsigned int msec);

View File

@ -44,6 +44,7 @@
#include <grp.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <time.h> /* clock_gettime */
#ifdef __sun
# include <sys/filio.h>
@ -108,6 +109,35 @@ STATIC_ASSERT(offsetof(uv_buf_t, base) == offsetof(struct iovec, iov_base));
STATIC_ASSERT(offsetof(uv_buf_t, len) == offsetof(struct iovec, iov_len));
/* https://github.com/libuv/libuv/issues/1674 */
int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) {
struct timespec t;
int r;
if (ts == NULL)
return UV_EFAULT;
switch (clock_id) {
default:
return UV_EINVAL;
case UV_CLOCK_MONOTONIC:
r = clock_gettime(CLOCK_MONOTONIC, &t);
break;
case UV_CLOCK_REALTIME:
r = clock_gettime(CLOCK_REALTIME, &t);
break;
}
if (r)
return UV__ERR(errno);
ts->tv_sec = t.tv_sec;
ts->tv_nsec = t.tv_nsec;
return 0;
}
uint64_t uv_hrtime(void) {
return uv__hrtime(UV_CLOCK_PRECISE);
}

View File

@ -31,6 +31,7 @@
#include "internal.h"
/* clang-format off */
#include <sysinfoapi.h>
#include <winsock2.h>
#include <winperf.h>
#include <iphlpapi.h>
@ -504,11 +505,43 @@ int uv_get_process_title(char* buffer, size_t size) {
}
/* https://github.com/libuv/libuv/issues/1674 */
int uv_clock_gettime(uv_clock_id clock_id, uv_timespec64_t* ts) {
FILETIME ft;
int64_t t;
if (ts == NULL)
return UV_EFAULT;
switch (clock_id) {
case UV_CLOCK_MONOTONIC:
uv__once_init();
t = uv__hrtime(UV__NANOSEC);
ts->tv_sec = t / 1000000000;
ts->tv_nsec = t % 1000000000;
return 0;
case UV_CLOCK_REALTIME:
GetSystemTimePreciseAsFileTime(&ft);
/* In 100-nanosecond increments from 1601-01-01 UTC because why not? */
t = (int64_t) ft.dwHighDateTime << 32 | ft.dwLowDateTime;
/* Convert to UNIX epoch, 1970-01-01. Still in 100 ns increments. */
t -= 116444736000000000ll;
/* Now convert to seconds and nanoseconds. */
ts->tv_sec = t / 10000000;
ts->tv_nsec = t % 10000000 * 100;
return 0;
}
return UV_EINVAL;
}
uint64_t uv_hrtime(void) {
uv__once_init();
return uv__hrtime(UV__NANOSEC);
}
uint64_t uv__hrtime(unsigned int scale) {
LARGE_INTEGER counter;
double scaled_freq;

View File

@ -50,3 +50,16 @@ TEST_IMPL(hrtime) {
}
return 0;
}
TEST_IMPL(clock_gettime) {
uv_timespec64_t t;
ASSERT_EQ(UV_EINVAL, uv_clock_gettime(1337, &t));
ASSERT_EQ(UV_EFAULT, uv_clock_gettime(1337, NULL));
ASSERT_EQ(0, uv_clock_gettime(UV_CLOCK_MONOTONIC, &t));
ASSERT_EQ(0, uv_clock_gettime(UV_CLOCK_REALTIME, &t));
ASSERT_GT(1682500000000ll, t.tv_sec); /* 2023-04-26T09:06:40.000Z */
return 0;
}

View File

@ -289,6 +289,7 @@ TEST_DECLARE (handle_fileno)
TEST_DECLARE (homedir)
TEST_DECLARE (tmpdir)
TEST_DECLARE (hrtime)
TEST_DECLARE (clock_gettime)
TEST_DECLARE (getaddrinfo_fail)
TEST_DECLARE (getaddrinfo_fail_sync)
TEST_DECLARE (getaddrinfo_basic)
@ -919,6 +920,8 @@ TASK_LIST_START
TEST_ENTRY_CUSTOM (hrtime, 0, 0, 20000)
TEST_ENTRY (clock_gettime)
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
TEST_ENTRY_CUSTOM (getaddrinfo_fail_sync, 0, 0, 10000)