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
|
.. 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
|
.. 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
|
.. 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;
|
int32_t tv_usec;
|
||||||
} uv_timeval64_t;
|
} 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
|
.. c:type:: uv_rusage_t
|
||||||
|
|
||||||
Data type for resource usage results.
|
Data type for resource usage results.
|
||||||
@ -588,7 +611,7 @@ API
|
|||||||
|
|
||||||
.. c:function:: uint64_t uv_hrtime(void)
|
.. 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
|
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
|
related to the time of day and therefore not subject to clock drift. The
|
||||||
primary use is for measuring performance between intervals.
|
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
|
Not every platform can support nanosecond resolution; however, this value will always
|
||||||
be in nanoseconds.
|
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)
|
.. 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`.
|
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,
|
void* buf,
|
||||||
size_t buflen);
|
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 {
|
typedef struct {
|
||||||
long tv_sec;
|
long tv_sec;
|
||||||
long tv_nsec;
|
long tv_nsec;
|
||||||
} uv_timespec_t;
|
} 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 {
|
typedef struct {
|
||||||
uint64_t st_dev;
|
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 uv_os_fd_t uv_get_osfhandle(int fd);
|
||||||
UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_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 {
|
typedef struct {
|
||||||
uv_timeval_t ru_utime; /* user CPU time used */
|
uv_timeval_t ru_utime; /* user CPU time used */
|
||||||
uv_timeval_t ru_stime; /* system 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_constrained_memory(void);
|
||||||
UV_EXTERN uint64_t uv_get_available_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 uint64_t uv_hrtime(void);
|
||||||
UV_EXTERN void uv_sleep(unsigned int msec);
|
UV_EXTERN void uv_sleep(unsigned int msec);
|
||||||
|
|
||||||
|
|||||||
@ -44,6 +44,7 @@
|
|||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <time.h> /* clock_gettime */
|
||||||
|
|
||||||
#ifdef __sun
|
#ifdef __sun
|
||||||
# include <sys/filio.h>
|
# 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));
|
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) {
|
uint64_t uv_hrtime(void) {
|
||||||
return uv__hrtime(UV_CLOCK_PRECISE);
|
return uv__hrtime(UV_CLOCK_PRECISE);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,6 +31,7 @@
|
|||||||
#include "internal.h"
|
#include "internal.h"
|
||||||
|
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
#include <sysinfoapi.h>
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <winperf.h>
|
#include <winperf.h>
|
||||||
#include <iphlpapi.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) {
|
uint64_t uv_hrtime(void) {
|
||||||
uv__once_init();
|
uv__once_init();
|
||||||
return uv__hrtime(UV__NANOSEC);
|
return uv__hrtime(UV__NANOSEC);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint64_t uv__hrtime(unsigned int scale) {
|
uint64_t uv__hrtime(unsigned int scale) {
|
||||||
LARGE_INTEGER counter;
|
LARGE_INTEGER counter;
|
||||||
double scaled_freq;
|
double scaled_freq;
|
||||||
|
|||||||
@ -50,3 +50,16 @@ TEST_IMPL(hrtime) {
|
|||||||
}
|
}
|
||||||
return 0;
|
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 (homedir)
|
||||||
TEST_DECLARE (tmpdir)
|
TEST_DECLARE (tmpdir)
|
||||||
TEST_DECLARE (hrtime)
|
TEST_DECLARE (hrtime)
|
||||||
|
TEST_DECLARE (clock_gettime)
|
||||||
TEST_DECLARE (getaddrinfo_fail)
|
TEST_DECLARE (getaddrinfo_fail)
|
||||||
TEST_DECLARE (getaddrinfo_fail_sync)
|
TEST_DECLARE (getaddrinfo_fail_sync)
|
||||||
TEST_DECLARE (getaddrinfo_basic)
|
TEST_DECLARE (getaddrinfo_basic)
|
||||||
@ -919,6 +920,8 @@ TASK_LIST_START
|
|||||||
|
|
||||||
TEST_ENTRY_CUSTOM (hrtime, 0, 0, 20000)
|
TEST_ENTRY_CUSTOM (hrtime, 0, 0, 20000)
|
||||||
|
|
||||||
|
TEST_ENTRY (clock_gettime)
|
||||||
|
|
||||||
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
|
TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
|
||||||
TEST_ENTRY_CUSTOM (getaddrinfo_fail_sync, 0, 0, 10000)
|
TEST_ENTRY_CUSTOM (getaddrinfo_fail_sync, 0, 0, 10000)
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user