mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2026-04-18 18:18:44 +00:00
Merge eefabe2f62 into 389d2060df
This commit is contained in:
commit
5d1bdc0212
|
|
@ -2139,7 +2139,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
|
||||||
// nanosleep(). This is incorrect, but good enough for now.
|
// nanosleep(). This is incorrect, but good enough for now.
|
||||||
os_timespec ts;
|
os_timespec ts;
|
||||||
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
||||||
nanosleep(&ts, NULL);
|
os_nanosleep(&ts, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case __WASI_CLOCK_REALTIME:
|
case __WASI_CLOCK_REALTIME:
|
||||||
|
|
@ -2167,7 +2167,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
|
||||||
// Relative sleeps can be done using nanosleep().
|
// Relative sleeps can be done using nanosleep().
|
||||||
os_timespec ts;
|
os_timespec ts;
|
||||||
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
||||||
nanosleep(&ts, NULL);
|
os_nanosleep(&ts, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -18,3 +18,38 @@ os_usleep(uint32 usec)
|
||||||
ret = nanosleep(&ts, NULL);
|
ret = nanosleep(&ts, NULL);
|
||||||
return ret == 0 ? 0 : -1;
|
return ret == 0 ? 0 : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function relies on a small workaround (hardcoded errno values)
|
||||||
|
* to avoid including <errno.h> or the project-specific `libc_errno.h`,
|
||||||
|
* thus preventing changes to the current CMake configuration.
|
||||||
|
*/
|
||||||
|
__wasi_errno_t
|
||||||
|
os_nanosleep(const os_timespec *req, os_timespec *rem)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
__wasi_errno_t wasi_ret = __WASI_ESUCCESS;
|
||||||
|
|
||||||
|
ret = nanosleep(req, rem);
|
||||||
|
|
||||||
|
switch(ret)
|
||||||
|
{
|
||||||
|
case 14 /* EFAULT */:
|
||||||
|
{
|
||||||
|
wasi_ret = __WASI_EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4 /* EINTR */:
|
||||||
|
{
|
||||||
|
wasi_ret = __WASI_EFAULT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 22 /* EINVAL */:
|
||||||
|
{
|
||||||
|
wasi_ret = __WASI_EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return wasi_ret;
|
||||||
|
}
|
||||||
|
|
@ -1669,28 +1669,112 @@ __wasi_errno_t
|
||||||
os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
|
os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
|
||||||
__wasi_timestamp_t *time);
|
__wasi_timestamp_t *time);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Experimental */
|
/****************************************************
|
||||||
|
* Section 5 *
|
||||||
|
* Experimental functions *
|
||||||
|
****************************************************/
|
||||||
|
|
||||||
/* Used in posix.c around L2259 and expect the return code
|
/**
|
||||||
* of ioctl() directly.
|
* NOTES:
|
||||||
|
* The bellow functions were defined after increasing the support for the
|
||||||
|
* Zephyr platform to get the full WASI libc running.
|
||||||
|
*
|
||||||
|
* If you don't need to support WASI libc, there is no need to implement these
|
||||||
|
* APIs.
|
||||||
|
*
|
||||||
|
* We could also move these definitions to the proper sections
|
||||||
|
* (File, Time, ...) but still keep them here until we get more feedback or
|
||||||
|
* observe edges cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Control device.
|
||||||
|
*
|
||||||
|
* The `ioctl` function was one of the POSIX function used without platform
|
||||||
|
* abastraction API in the `sandboxed-system-primitives` and particularly in the
|
||||||
|
* `wasmtime_ssp_poll_oneoff` function.
|
||||||
|
*
|
||||||
|
* @param handle A platform file handler.
|
||||||
|
* @param request A platform-dependent request code.
|
||||||
|
* @param argp Usually an untyped pointer to memory.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* __WASI_ESUCCESS On success
|
||||||
|
* __WASI_EBADF handle is not a valid file handler.
|
||||||
|
* __WASI_EFAULT argp references an inaccessible memory area.
|
||||||
|
* __WASI_EINVAL request or argp is not valid.
|
||||||
|
* __WASI_ENOTTY handle is not associated with a character special device.
|
||||||
|
* __WASI_ENOTTY The specified request does not apply to the kind of
|
||||||
|
* object that the file handler handle references.
|
||||||
|
*
|
||||||
|
* NOTE: We seem to only use/support the `FIONREAD` request code:
|
||||||
|
*
|
||||||
|
* FIONREAD Get the number of bytes in the input buffer.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
os_ioctl(os_file_handle handle, int request, ...);
|
os_ioctl(os_file_handle handle, int request, ...);
|
||||||
|
|
||||||
/* Higher level API:
|
/**
|
||||||
|
* @brief Wait for some event on a file descriptor.
|
||||||
|
*
|
||||||
|
* For more context, the higher level API `blocking_op_poll`.
|
||||||
|
*
|
||||||
* __wasi_errno_t
|
* __wasi_errno_t
|
||||||
* blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds,
|
* blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds,
|
||||||
* os_nfds_t nfds, int timeout_ms, int *retp)
|
* os_nfds_t nfds, int timeout_ms, int *retp)
|
||||||
* Already format the errno and expect the return code of poll() directly.
|
*
|
||||||
|
* Format the error code (errno) and expect the return code of (POSIX) `poll()`
|
||||||
|
* directly hence the `int` return type.
|
||||||
|
*
|
||||||
|
* @param pfds A poll file descriptors array
|
||||||
|
* @param nfs The size of the poll file descriptors array
|
||||||
|
* @param timeout Specify the number of ms that poll is busy waiting.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
os_poll(os_poll_file_handle *pfds, os_nfds_t nfs, int timeout);
|
os_poll(os_poll_file_handle *pfds, os_nfds_t nfs, int timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Compare two platform's file handle/descriptor.
|
||||||
|
*
|
||||||
|
* This function should ALWAYS be used when comparaing file handlers because
|
||||||
|
* for some platforms (Windows, Zephyr, etc...) the `os_file_handle` type is
|
||||||
|
* a structure and not a primary type like for POSIX.
|
||||||
|
*
|
||||||
|
* @param handle1 First file handle or constant.
|
||||||
|
* @param handle2 Second file handle.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* true The file handlers are similar.
|
||||||
|
* false The file handlers don't match.
|
||||||
|
*/
|
||||||
bool
|
bool
|
||||||
os_compare_file_handle(os_file_handle handle1, os_file_handle handle2);
|
os_compare_file_handle(os_file_handle handle1, os_file_handle handle2);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief high-resolution sleep
|
||||||
|
*
|
||||||
|
* The `nanosleep` function was the last POSIX function used without platform
|
||||||
|
* abastraction API in the `sandboxed-system-primitives` and particularly in the
|
||||||
|
* `wasmtime_ssp_poll_oneoff` function.
|
||||||
|
*
|
||||||
|
* @param req time requiered to sleep.
|
||||||
|
* @param rem remaining time in the case that the function is interrupted.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* __WASI_ESUCCESS On success
|
||||||
|
* __WASI_EFAULT Problem with copying information.
|
||||||
|
* __WASI_EINTR The sleep has been interrupted.
|
||||||
|
* __WASI_EINVAL The req input is badly formed.
|
||||||
|
*/
|
||||||
|
__wasi_errno_t
|
||||||
|
os_nanosleep(const os_timespec *req, os_timespec *rem);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* #ifndef PLATFORM_API_EXTENSION_H */
|
#endif /* #ifndef PLATFORM_API_EXTENSION_H */
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@
|
||||||
#include <zephyr/net/net_core.h>
|
#include <zephyr/net/net_core.h>
|
||||||
#include <zephyr/net/net_context.h>
|
#include <zephyr/net/net_context.h>
|
||||||
#include <zephyr/net/socket.h>
|
#include <zephyr/net/socket.h>
|
||||||
|
#include <zephyr/fs/fs.h>
|
||||||
#endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */
|
#endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */
|
||||||
|
|
||||||
#ifdef CONFIG_USERSPACE
|
#ifdef CONFIG_USERSPACE
|
||||||
|
|
@ -300,7 +301,24 @@ typedef unsigned int os_nfds_t;
|
||||||
|
|
||||||
#define FIONREAD ZFD_IOCTL_FIONREAD
|
#define FIONREAD ZFD_IOCTL_FIONREAD
|
||||||
|
|
||||||
typedef struct timespec os_timespec;
|
/*
|
||||||
|
* The previous `os_timespec` was a forward declaration:
|
||||||
|
*
|
||||||
|
* typedef struct timespec os_timespec;
|
||||||
|
*
|
||||||
|
* It was not bad as is, but seemed to not be included from anywhere.
|
||||||
|
* As of Zephyr v3.7.0 (LTS) the `timespec` struct is only declared with the
|
||||||
|
* configuration `CONFIG_POSIX_API` enabled which is not a prefered
|
||||||
|
* configuration for the Zephyr port.
|
||||||
|
*
|
||||||
|
* NOTE: If Zephyr later exposes `struct timespec` without requiring
|
||||||
|
* CONFIG_POSIX_API, this definition should be replaced by an alias.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int64_t tv_sec;
|
||||||
|
long tv_nsec;
|
||||||
|
} os_timespec;
|
||||||
|
|
||||||
|
|
||||||
#ifndef CLOCK_REALTIME
|
#ifndef CLOCK_REALTIME
|
||||||
#define CLOCK_REALTIME 1
|
#define CLOCK_REALTIME 1
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ if (NOT WAMR_BUILD_LIBC_WASI EQUAL 1)
|
||||||
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_socket.c)
|
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_socket.c)
|
||||||
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_file.c)
|
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_file.c)
|
||||||
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_clock.c)
|
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_clock.c)
|
||||||
|
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_sleep.c)
|
||||||
else()
|
else()
|
||||||
include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake)
|
include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake)
|
||||||
set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE})
|
set(source_all ${source_all} ${PLATFORM_COMMON_LIBC_UTIL_SOURCE})
|
||||||
|
|
|
||||||
120
core/shared/platform/zephyr/zephyr_sleep.c
Normal file
120
core/shared/platform/zephyr/zephyr_sleep.c
Normal file
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved.
|
||||||
|
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||||
|
*/
|
||||||
|
#include "platform_api_extension.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In Zephyr v3.7, there is no simple way to get a `nanosleep` implementation.
|
||||||
|
* But in the later version the Zephyr community introduced some clock APIs
|
||||||
|
* and their POSIX compatibility layer.
|
||||||
|
*
|
||||||
|
* Relevant Zephyr sources:
|
||||||
|
* - zephyr/include/zephyr/sys/clock.h
|
||||||
|
* - Zephyr/lib/os/clock.c
|
||||||
|
* POSIX layer:
|
||||||
|
* - zephyr/lib/posix/options/clock.c
|
||||||
|
*
|
||||||
|
* Instead of re-implementing the full Clock APIs, this file provides a naive
|
||||||
|
* `nanosleep` implementation based on the Zephyr thread API (`k_sleep`).
|
||||||
|
*
|
||||||
|
* Limitations:
|
||||||
|
* Maximum sleep duration is limited by UINT32_MAX or UINT64_MAX ticks
|
||||||
|
* (≈ 4,294,967,295 and 18,446,744,073,709,551,615 respectively).
|
||||||
|
*
|
||||||
|
* Example at a "slow" clock rate of 50 kHz:
|
||||||
|
* - UINT32_MAX: ~85 899s (~23 hours)
|
||||||
|
* - UINT64_MAX: ~368 934 881 474 191s (~11.7 millions years)
|
||||||
|
* Clearly, `nanosleep` should not be used for such long durations.
|
||||||
|
*
|
||||||
|
* Note: this assumes `CONFIG_POSIX_API=n` in the Zephyr application.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static k_ticks_t timespec_to_ticks(const os_timespec *ts);
|
||||||
|
static void ticks_to_timespec(k_ticks_t ticks, os_timespec *ts);
|
||||||
|
|
||||||
|
__wasi_errno_t
|
||||||
|
os_nanosleep(const os_timespec *req, os_timespec *rem)
|
||||||
|
{
|
||||||
|
k_timeout_t timeout;
|
||||||
|
k_ticks_t rem_ticks;
|
||||||
|
|
||||||
|
if (req == NULL){
|
||||||
|
return __WASI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= NSEC_PER_SEC) {
|
||||||
|
return __WASI_EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req->tv_sec == 0 && req->tv_nsec == 0) {
|
||||||
|
if (rem != NULL) {
|
||||||
|
rem->tv_sec = 0;
|
||||||
|
rem->tv_nsec = 0;
|
||||||
|
}
|
||||||
|
return __WASI_ESUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout.ticks = timespec_to_ticks(req);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function `int32_t k_sleep(k_timeout_t timeout)` return either:
|
||||||
|
* * 0 requested time elaspsed.
|
||||||
|
* * >0 remaining time in ms (due to k_wakeup).
|
||||||
|
*/
|
||||||
|
int32_t rc = k_sleep(timeout);
|
||||||
|
if (rem != NULL) {
|
||||||
|
if (rc > 0) {
|
||||||
|
|
||||||
|
#ifdef CONFIG_TIMEOUT_64BIT
|
||||||
|
rem_ticks = (k_ticks_t)((uint64_t)rc * CONFIG_SYS_CLOCK_TICKS_PER_SEC / MSEC_PER_SEC);
|
||||||
|
#else /* CONFIG_TIMEOUT_32BIT */
|
||||||
|
uint64_t temp_ticks = (uint64_t)rc * CONFIG_SYS_CLOCK_TICKS_PER_SEC / MSEC_PER_SEC;
|
||||||
|
rem_ticks = (k_ticks_t)(temp_ticks > UINT32_MAX ? UINT32_MAX : temp_ticks);
|
||||||
|
#endif
|
||||||
|
ticks_to_timespec(rem_ticks, rem);
|
||||||
|
} else {
|
||||||
|
rem->tv_sec = 0;
|
||||||
|
rem->tv_nsec = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return __WASI_ESUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static k_ticks_t timespec_to_ticks(const os_timespec *ts)
|
||||||
|
{
|
||||||
|
const uint64_t ticks_per_sec = CONFIG_SYS_CLOCK_TICKS_PER_SEC;
|
||||||
|
uint64_t total_ns, ticks;
|
||||||
|
|
||||||
|
total_ns = (uint64_t)ts->tv_sec * NSEC_PER_SEC + (uint64_t)ts->tv_nsec;
|
||||||
|
ticks = total_ns * ticks_per_sec / NSEC_PER_SEC;
|
||||||
|
|
||||||
|
#ifdef CONFIG_TIMEOUT_64BIT
|
||||||
|
if (ticks > INT64_MAX) {
|
||||||
|
return INT64_MAX;
|
||||||
|
}
|
||||||
|
#else /* CONFIG_TIMEOUT_32BIT */
|
||||||
|
if (ticks > UINT32_MAX) {
|
||||||
|
return UINT32_MAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (k_ticks_t)ticks;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ticks_to_timespec(k_ticks_t ticks, os_timespec *ts)
|
||||||
|
{
|
||||||
|
const uint64_t ticks_per_sec = CONFIG_SYS_CLOCK_TICKS_PER_SEC;
|
||||||
|
uint64_t total_ns;
|
||||||
|
|
||||||
|
if (ts == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
total_ns = ((uint64_t)ticks * NSEC_PER_SEC) / ticks_per_sec;
|
||||||
|
|
||||||
|
ts->tv_sec = (long)(total_ns / NSEC_PER_SEC);
|
||||||
|
ts->tv_nsec = (long)(total_ns % NSEC_PER_SEC);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user