mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2025-05-09 21:26:21 +00:00
Implement wasi clock_time/clock_res get (#2637)
Add os_clock_res_get and os_clock_time_get in platform_api_extension.h, and implement them in posix like platforms and windows platform.
This commit is contained in:
parent
fa5e9d72b0
commit
a874bf0ff8
|
@ -94,22 +94,9 @@ ns_lookup_list_search(char **list, const char *host)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a POSIX timespec to a CloudABI timestamp.
|
|
||||||
static __wasi_timestamp_t
|
|
||||||
convert_timespec(const struct timespec *ts)
|
|
||||||
{
|
|
||||||
if (ts->tv_sec < 0)
|
|
||||||
return 0;
|
|
||||||
if ((__wasi_timestamp_t)ts->tv_sec >= UINT64_MAX / 1000000000)
|
|
||||||
return UINT64_MAX;
|
|
||||||
return (__wasi_timestamp_t)ts->tv_sec * 1000000000
|
|
||||||
+ (__wasi_timestamp_t)ts->tv_nsec;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Converts a CloudABI clock identifier to a POSIX clock identifier.
|
|
||||||
#ifndef BH_PLATFORM_WINDOWS
|
#ifndef BH_PLATFORM_WINDOWS
|
||||||
static bool
|
static bool
|
||||||
convert_clockid(__wasi_clockid_t in, clockid_t *out)
|
wasi_clockid_to_clockid(__wasi_clockid_t in, clockid_t *out)
|
||||||
{
|
{
|
||||||
switch (in) {
|
switch (in) {
|
||||||
case __WASI_CLOCK_MONOTONIC:
|
case __WASI_CLOCK_MONOTONIC:
|
||||||
|
@ -210,22 +197,37 @@ wasi_addr_ip_to_bh_ip_addr_buffer(__wasi_addr_ip_t *addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
wasi_clockid_to_bh_clockid(__wasi_clockid_t in, bh_clock_id_t *out)
|
||||||
|
{
|
||||||
|
switch (in) {
|
||||||
|
case __WASI_CLOCK_MONOTONIC:
|
||||||
|
*out = BH_CLOCK_ID_MONOTONIC;
|
||||||
|
return true;
|
||||||
|
case __WASI_CLOCK_PROCESS_CPUTIME_ID:
|
||||||
|
*out = BH_CLOCK_ID_PROCESS_CPUTIME_ID;
|
||||||
|
return true;
|
||||||
|
case __WASI_CLOCK_REALTIME:
|
||||||
|
*out = BH_CLOCK_ID_REALTIME;
|
||||||
|
return true;
|
||||||
|
case __WASI_CLOCK_THREAD_CPUTIME_ID:
|
||||||
|
*out = BH_CLOCK_ID_THREAD_CPUTIME_ID;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
__wasi_errno_t
|
__wasi_errno_t
|
||||||
wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id,
|
wasmtime_ssp_clock_res_get(__wasi_clockid_t clock_id,
|
||||||
__wasi_timestamp_t *resolution)
|
__wasi_timestamp_t *resolution)
|
||||||
{
|
{
|
||||||
#ifdef BH_PLATFORM_WINDOWS
|
bh_clock_id_t bh_clockid;
|
||||||
return __WASI_ENOSYS;
|
if (!wasi_clockid_to_bh_clockid(clock_id, &bh_clockid))
|
||||||
#else
|
|
||||||
clockid_t nclock_id;
|
|
||||||
if (!convert_clockid(clock_id, &nclock_id))
|
|
||||||
return __WASI_EINVAL;
|
return __WASI_EINVAL;
|
||||||
struct timespec ts;
|
if (os_clock_res_get(clock_id, resolution) != BHT_OK)
|
||||||
if (clock_getres(nclock_id, &ts) < 0)
|
|
||||||
return convert_errno(errno);
|
return convert_errno(errno);
|
||||||
*resolution = convert_timespec(&ts);
|
return __WASI_ESUCCESS;
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
__wasi_errno_t
|
__wasi_errno_t
|
||||||
|
@ -233,18 +235,12 @@ wasmtime_ssp_clock_time_get(__wasi_clockid_t clock_id,
|
||||||
__wasi_timestamp_t precision,
|
__wasi_timestamp_t precision,
|
||||||
__wasi_timestamp_t *time)
|
__wasi_timestamp_t *time)
|
||||||
{
|
{
|
||||||
#ifdef BH_PLATFORM_WINDOWS
|
bh_clock_id_t bh_clockid;
|
||||||
return __WASI_ENOSYS;
|
if (!wasi_clockid_to_bh_clockid(clock_id, &bh_clockid))
|
||||||
#else
|
|
||||||
clockid_t nclock_id;
|
|
||||||
if (!convert_clockid(clock_id, &nclock_id))
|
|
||||||
return __WASI_EINVAL;
|
return __WASI_EINVAL;
|
||||||
struct timespec ts;
|
if (os_clock_time_get(clock_id, precision, time) != BHT_OK)
|
||||||
if (clock_gettime(nclock_id, &ts) < 0)
|
|
||||||
return convert_errno(errno);
|
return convert_errno(errno);
|
||||||
*time = convert_timespec(&ts);
|
return __WASI_ESUCCESS;
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct fd_prestat {
|
struct fd_prestat {
|
||||||
|
@ -2081,7 +2077,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
|
||||||
};
|
};
|
||||||
#if CONFIG_HAS_CLOCK_NANOSLEEP
|
#if CONFIG_HAS_CLOCK_NANOSLEEP
|
||||||
clockid_t clock_id;
|
clockid_t clock_id;
|
||||||
if (convert_clockid(in[0].u.u.clock.clock_id, &clock_id)) {
|
if (wasi_clockid_to_clockid(in[0].u.u.clock.clock_id, &clock_id)) {
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
||||||
int ret = clock_nanosleep(
|
int ret = clock_nanosleep(
|
||||||
|
|
72
core/shared/platform/common/posix/posix_clock.c
Normal file
72
core/shared/platform/common/posix/posix_clock.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform_api_vmcore.h"
|
||||||
|
|
||||||
|
#define NANOSECONDS_PER_SECOND 1000000000ULL
|
||||||
|
|
||||||
|
static bool
|
||||||
|
bh_clockid_to_clockid(bh_clock_id_t in, clockid_t *out)
|
||||||
|
{
|
||||||
|
switch (in) {
|
||||||
|
case BH_CLOCK_ID_MONOTONIC:
|
||||||
|
*out = CLOCK_MONOTONIC;
|
||||||
|
return true;
|
||||||
|
#if defined(CLOCK_PROCESS_CPUTIME_ID)
|
||||||
|
case BH_CLOCK_ID_PROCESS_CPUTIME_ID:
|
||||||
|
*out = CLOCK_PROCESS_CPUTIME_ID;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
case BH_CLOCK_ID_REALTIME:
|
||||||
|
*out = CLOCK_REALTIME;
|
||||||
|
return true;
|
||||||
|
#if defined(CLOCK_THREAD_CPUTIME_ID)
|
||||||
|
case BH_CLOCK_ID_THREAD_CPUTIME_ID:
|
||||||
|
*out = CLOCK_THREAD_CPUTIME_ID;
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64
|
||||||
|
timespec_to_nanoseconds(const struct timespec *ts)
|
||||||
|
{
|
||||||
|
if (ts->tv_sec < 0)
|
||||||
|
return 0;
|
||||||
|
if ((uint64)ts->tv_sec >= UINT64_MAX / NANOSECONDS_PER_SECOND)
|
||||||
|
return UINT64_MAX;
|
||||||
|
return (uint64)ts->tv_sec * NANOSECONDS_PER_SECOND + (uint64)ts->tv_nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution)
|
||||||
|
{
|
||||||
|
clockid_t nclock_id;
|
||||||
|
if (!bh_clockid_to_clockid(clock_id, &nclock_id))
|
||||||
|
return BHT_ERROR;
|
||||||
|
struct timespec ts;
|
||||||
|
if (clock_getres(nclock_id, &ts) < 0)
|
||||||
|
return BHT_ERROR;
|
||||||
|
*resolution = timespec_to_nanoseconds(&ts);
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time)
|
||||||
|
{
|
||||||
|
clockid_t nclock_id;
|
||||||
|
if (!bh_clockid_to_clockid(clock_id, &nclock_id))
|
||||||
|
return BHT_ERROR;
|
||||||
|
struct timespec ts;
|
||||||
|
if (clock_gettime(nclock_id, &ts) < 0)
|
||||||
|
return BHT_ERROR;
|
||||||
|
*time = timespec_to_nanoseconds(&ts);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -36,6 +36,26 @@ extern "C" {
|
||||||
* 2. To build the app-mgr and app-framework, you must implement it
|
* 2. To build the app-mgr and app-framework, you must implement it
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a resolution of the clock
|
||||||
|
*
|
||||||
|
* @param clock_id clock identifier
|
||||||
|
* @param resolution output variable to store the clock resolution
|
||||||
|
* @return BHT_OK if success; otherwise, BHT_ERROR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a current time of the clock
|
||||||
|
*
|
||||||
|
* @param clock_id clock identifier
|
||||||
|
* @param time output variable to store the clock time
|
||||||
|
* @return BHT_OK if success; otherwise, BHT_ERROR
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a thread
|
* Creates a thread
|
||||||
*
|
*
|
||||||
|
|
|
@ -37,6 +37,13 @@ extern "C" {
|
||||||
#define BH_TIME_T_MAX LONG_MAX
|
#define BH_TIME_T_MAX LONG_MAX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BH_CLOCK_ID_REALTIME,
|
||||||
|
BH_CLOCK_ID_MONOTONIC,
|
||||||
|
BH_CLOCK_ID_PROCESS_CPUTIME_ID,
|
||||||
|
BH_CLOCK_ID_THREAD_CPUTIME_ID
|
||||||
|
} bh_clock_id_t;
|
||||||
|
|
||||||
#if defined(_MSC_BUILD)
|
#if defined(_MSC_BUILD)
|
||||||
#if defined(COMPILING_WASM_RUNTIME_API)
|
#if defined(COMPILING_WASM_RUNTIME_API)
|
||||||
__declspec(dllexport) void *BH_MALLOC(unsigned int size);
|
__declspec(dllexport) void *BH_MALLOC(unsigned int size);
|
||||||
|
|
|
@ -36,6 +36,8 @@ endif()
|
||||||
|
|
||||||
file (GLOB source_all_untrusted ${PLATFORM_SHARED_DIR}/untrusted/*.c)
|
file (GLOB source_all_untrusted ${PLATFORM_SHARED_DIR}/untrusted/*.c)
|
||||||
|
|
||||||
|
list(APPEND source_all ${PLATFORM_SHARED_DIR}/../common/posix/posix_clock.c)
|
||||||
|
|
||||||
set (PLATFORM_SHARED_SOURCE ${source_all})
|
set (PLATFORM_SHARED_SOURCE ${source_all})
|
||||||
|
|
||||||
set (PLATFORM_SHARED_SOURCE_UNTRUSTED ${source_all_untrusted})
|
set (PLATFORM_SHARED_SOURCE_UNTRUSTED ${source_all_untrusted})
|
||||||
|
|
160
core/shared/platform/windows/win_clock.c
Normal file
160
core/shared/platform/windows/win_clock.c
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2023 Amazon Inc. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "platform_api_vmcore.h"
|
||||||
|
#include <winternl.h>
|
||||||
|
|
||||||
|
#define NANOSECONDS_PER_SECOND 1000000000ULL
|
||||||
|
#define NANOSECONDS_PER_TICK 100
|
||||||
|
|
||||||
|
static int
|
||||||
|
calculate_monotonic_clock_frequency(uint64 *out_frequency)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER frequency;
|
||||||
|
if (!QueryPerformanceFrequency(&frequency)) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*out_frequency = (uint64)frequency.QuadPart;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The implementation below derives from the following source:
|
||||||
|
// https://github.com/WasmEdge/WasmEdge/blob/b70f48c42922ce5ee7730054b6ac0b1615176285/lib/host/wasi/win.h#L210
|
||||||
|
static uint64
|
||||||
|
filetime_to_wasi_timestamp(FILETIME filetime)
|
||||||
|
{
|
||||||
|
static const uint64 ntto_unix_epoch =
|
||||||
|
134774ULL * 86400ULL * NANOSECONDS_PER_SECOND;
|
||||||
|
|
||||||
|
ULARGE_INTEGER temp = { .LowPart = filetime.dwLowDateTime,
|
||||||
|
.HighPart = filetime.dwHighDateTime };
|
||||||
|
|
||||||
|
return (temp.QuadPart * 100ull) - ntto_unix_epoch;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
get_performance_counter_value(uint64 *out_counter)
|
||||||
|
{
|
||||||
|
LARGE_INTEGER counter;
|
||||||
|
if (!QueryPerformanceCounter(&counter)) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
*out_counter = counter.QuadPart;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_clock_res_get(bh_clock_id_t clock_id, uint64 *resolution)
|
||||||
|
{
|
||||||
|
switch (clock_id) {
|
||||||
|
case BH_CLOCK_ID_MONOTONIC:
|
||||||
|
{
|
||||||
|
uint64 frequency;
|
||||||
|
if (calculate_monotonic_clock_frequency(&frequency) == BHT_ERROR) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
const uint64 result = (uint64)NANOSECONDS_PER_SECOND / frequency;
|
||||||
|
*resolution = result;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
case BH_CLOCK_ID_REALTIME:
|
||||||
|
case BH_CLOCK_ID_PROCESS_CPUTIME_ID:
|
||||||
|
case BH_CLOCK_ID_THREAD_CPUTIME_ID:
|
||||||
|
{
|
||||||
|
PULONG maximum_time;
|
||||||
|
PULONG minimum_time;
|
||||||
|
PULONG current_time;
|
||||||
|
NTSTATUS
|
||||||
|
status = NtQueryTimerResolution(&maximum_time, &minimum_time,
|
||||||
|
¤t_time);
|
||||||
|
|
||||||
|
uint64 result = (uint64)current_time * NANOSECONDS_PER_TICK;
|
||||||
|
*resolution = result / (uint64)NANOSECONDS_PER_SECOND;
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
os_clock_time_get(bh_clock_id_t clock_id, uint64 precision, uint64 *time)
|
||||||
|
{
|
||||||
|
switch (clock_id) {
|
||||||
|
case BH_CLOCK_ID_REALTIME:
|
||||||
|
{
|
||||||
|
FILETIME sys_now;
|
||||||
|
#if NTDDI_VERSION >= NTDDI_WIN8
|
||||||
|
GetSystemTimePreciseAsFileTime(&sys_now);
|
||||||
|
#else
|
||||||
|
GetSystemTimeAsFileTime(&SysNow);
|
||||||
|
#endif
|
||||||
|
*time = filetime_to_wasi_timestamp(sys_now);
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
case BH_CLOCK_ID_MONOTONIC:
|
||||||
|
{
|
||||||
|
uint64 frequency;
|
||||||
|
if (calculate_monotonic_clock_frequency(&frequency) == BHT_ERROR) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
uint64 counter;
|
||||||
|
if (get_performance_counter_value(&counter) == BHT_ERROR) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
if (NANOSECONDS_PER_SECOND % frequency == 0) {
|
||||||
|
*time = counter * NANOSECONDS_PER_SECOND / frequency;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
uint64 seconds = counter / frequency;
|
||||||
|
uint64 fractions = counter % frequency;
|
||||||
|
*time = seconds * NANOSECONDS_PER_SECOND
|
||||||
|
+ (fractions * NANOSECONDS_PER_SECOND) / frequency;
|
||||||
|
}
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
case BH_CLOCK_ID_PROCESS_CPUTIME_ID:
|
||||||
|
{
|
||||||
|
FILETIME creation_time;
|
||||||
|
FILETIME exit_time;
|
||||||
|
FILETIME kernel_time;
|
||||||
|
FILETIME user_time;
|
||||||
|
|
||||||
|
if (!GetProcessTimes(GetCurrentProcess(), &creation_time,
|
||||||
|
&exit_time, &kernel_time, &user_time)) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
*time = filetime_to_wasi_timestamp(kernel_time)
|
||||||
|
+ filetime_to_wasi_timestamp(user_time);
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
case BH_CLOCK_ID_THREAD_CPUTIME_ID:
|
||||||
|
{
|
||||||
|
FILETIME creation_time;
|
||||||
|
FILETIME exit_time;
|
||||||
|
FILETIME kernel_time;
|
||||||
|
FILETIME user_time;
|
||||||
|
|
||||||
|
if (!GetProcessTimes(GetCurrentThread(), &creation_time, &exit_time,
|
||||||
|
&kernel_time, &user_time)) {
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
*time = filetime_to_wasi_timestamp(kernel_time)
|
||||||
|
+ filetime_to_wasi_timestamp(user_time);
|
||||||
|
|
||||||
|
return BHT_OK;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
errno = EINVAL;
|
||||||
|
return BHT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
|
@ -364,6 +364,7 @@ CSRCS += nuttx_platform.c \
|
||||||
posix_blocking_op.c \
|
posix_blocking_op.c \
|
||||||
posix_thread.c \
|
posix_thread.c \
|
||||||
posix_time.c \
|
posix_time.c \
|
||||||
|
posix_clock.c \
|
||||||
posix_sleep.c \
|
posix_sleep.c \
|
||||||
mem_alloc.c \
|
mem_alloc.c \
|
||||||
ems_kfc.c \
|
ems_kfc.c \
|
||||||
|
|
|
@ -153,3 +153,9 @@ target_link_libraries (libiwasm ${LLVM_AVAILABLE_LIBS} ${UV_A_LIBS})
|
||||||
if (MINGW)
|
if (MINGW)
|
||||||
target_link_libraries (libiwasm ws2_32)
|
target_link_libraries (libiwasm ws2_32)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
target_link_libraries(libiwasm ntdll)
|
||||||
|
|
||||||
|
target_link_libraries(iwasm ntdll)
|
||||||
|
endif()
|
||||||
|
|
Loading…
Reference in New Issue
Block a user