mirror of
https://github.com/bytecodealliance/wasm-micro-runtime.git
synced 2026-01-20 08:16:41 +00:00
Merge 505eb2dd2f into 257d475293
This commit is contained in:
commit
b0ad4bf917
|
|
@ -2135,7 +2135,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
|
|||
// nanosleep(). This is incorrect, but good enough for now.
|
||||
os_timespec ts;
|
||||
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
||||
nanosleep(&ts, NULL);
|
||||
os_nanosleep(&ts, NULL);
|
||||
}
|
||||
break;
|
||||
case __WASI_CLOCK_REALTIME:
|
||||
|
|
@ -2163,7 +2163,7 @@ wasmtime_ssp_poll_oneoff(wasm_exec_env_t exec_env, struct fd_table *curfds,
|
|||
// Relative sleeps can be done using nanosleep().
|
||||
os_timespec ts;
|
||||
convert_timestamp(in[0].u.u.clock.timeout, &ts);
|
||||
nanosleep(&ts, NULL);
|
||||
os_nanosleep(&ts, NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <time.h>
|
||||
|
||||
#include "platform_api_extension.h"
|
||||
#include "libc_errno.h"
|
||||
|
||||
int
|
||||
os_usleep(uint32 usec)
|
||||
|
|
@ -18,3 +19,13 @@ os_usleep(uint32 usec)
|
|||
ret = nanosleep(&ts, NULL);
|
||||
return ret == 0 ? 0 : -1;
|
||||
}
|
||||
|
||||
__wasi_errno_t
|
||||
os_nanosleep(const os_timespec *req, os_timespec *rem)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = nanosleep(req, rem);
|
||||
|
||||
return convert_errno(ret);
|
||||
}
|
||||
|
|
@ -1669,28 +1669,112 @@ __wasi_errno_t
|
|||
os_clock_time_get(__wasi_clockid_t clock_id, __wasi_timestamp_t precision,
|
||||
__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
|
||||
os_ioctl(os_file_handle handle, int request, ...);
|
||||
|
||||
/* Higher level API:
|
||||
* __wasi_errno_t
|
||||
* blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds,
|
||||
* os_nfds_t nfds, int timeout_ms, int *retp)
|
||||
* Already format the errno and expect the return code of poll() directly.
|
||||
/**
|
||||
* @brief Wait for some event on a file descriptor.
|
||||
*
|
||||
* For more context, the higher level API `blocking_op_poll`.
|
||||
*
|
||||
* __wasi_errno_t
|
||||
* blocking_op_poll(wasm_exec_env_t exec_env, os_poll_file_handle *pfds,
|
||||
* os_nfds_t nfds, int timeout_ms, int *retp)
|
||||
*
|
||||
* 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
|
||||
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
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -67,6 +67,7 @@
|
|||
#include <zephyr/net/net_core.h>
|
||||
#include <zephyr/net/net_context.h>
|
||||
#include <zephyr/net/socket.h>
|
||||
#include <zephyr/fs/fs.h>
|
||||
#endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
|
@ -300,7 +301,24 @@ typedef unsigned int os_nfds_t;
|
|||
|
||||
#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
|
||||
#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_file.c)
|
||||
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_clock.c)
|
||||
list(REMOVE_ITEM source_all ${PLATFORM_SHARED_DIR}/zephyr_sleep.c)
|
||||
else()
|
||||
include (${CMAKE_CURRENT_LIST_DIR}/../common/libc-util/platform_common_libc_util.cmake)
|
||||
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