unix,win: add uv_clock_gettime() (#3971)
Fixes: https://github.com/libuv/libuv/issues/1674
This commit is contained in:
parent
e02642cf3b
commit
c8a1e6132b
@ -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.
|
||||
|
||||
::
|
||||
|
||||
|
||||
@ -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`.
|
||||
|
||||
32
include/uv.h
32
include/uv.h
@ -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);
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user