From 45acd9fb9f7efa9fb3d57dc41833658f0a9bf499 Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Tue, 9 Sep 2025 11:16:08 +0200 Subject: [PATCH 1/7] fix(zephyr): Make the simple-file sample compile by commenting nanosleep as a temp solution --- .../libc-wasi/sandboxed-system-primitives/src/posix.c | 4 ++-- core/shared/platform/zephyr/platform_internal.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index 3d90811bca..d20537ad0e 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -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); + // 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); + // nanosleep(&ts, NULL); } break; default: diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h index 7e59faa746..ae2014408a 100644 --- a/core/shared/platform/zephyr/platform_internal.h +++ b/core/shared/platform/zephyr/platform_internal.h @@ -51,6 +51,7 @@ #include #include #include +#include #endif /* end of KERNEL_VERSION_NUMBER < 0x030200 */ #ifdef CONFIG_USERSPACE From c8a7f00326e8dda5451cbfcdbd2598d318546be5 Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:13:45 +0200 Subject: [PATCH 2/7] fix(zephyr): Real os_timespec definition with comments --- .../platform/zephyr/platform_internal.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/core/shared/platform/zephyr/platform_internal.h b/core/shared/platform/zephyr/platform_internal.h index ae2014408a..05481e65e3 100644 --- a/core/shared/platform/zephyr/platform_internal.h +++ b/core/shared/platform/zephyr/platform_internal.h @@ -281,7 +281,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 From 3094ffbdc1d33fccf381869fbb6ebc7778fc0faf Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:18:42 +0200 Subject: [PATCH 3/7] fix(zephyr): Introduce a os_nanosleep function: - Declare it in the api_vm_extension for each platform - Increase the experimental functions doc - Create a os_nanosleep function in a new zephyr_sleep file - add it to the compilation process. --- .../sandboxed-system-primitives/src/posix.c | 4 +- .../platform/include/platform_api_extension.h | 106 ++++++++++++++++-- .../platform/zephyr/shared_platform.cmake | 1 + core/shared/platform/zephyr/zephyr_sleep.c | 106 ++++++++++++++++++ 4 files changed, 204 insertions(+), 13 deletions(-) create mode 100644 core/shared/platform/zephyr/zephyr_sleep.c diff --git a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c index d20537ad0e..bc9c3c9b4b 100644 --- a/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c +++ b/core/iwasm/libraries/libc-wasi/sandboxed-system-primitives/src/posix.c @@ -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: diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index 41ec5742bc..ffd028c1ea 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -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(os_timespec *req, os_timespec *rem); + + +#ifdef __cplusplus +} +#endif + #endif /* #ifndef PLATFORM_API_EXTENSION_H */ diff --git a/core/shared/platform/zephyr/shared_platform.cmake b/core/shared/platform/zephyr/shared_platform.cmake index f424b97204..f0b4a5ecce 100644 --- a/core/shared/platform/zephyr/shared_platform.cmake +++ b/core/shared/platform/zephyr/shared_platform.cmake @@ -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}) diff --git a/core/shared/platform/zephyr/zephyr_sleep.c b/core/shared/platform/zephyr/zephyr_sleep.c new file mode 100644 index 0000000000..e6236ace42 --- /dev/null +++ b/core/shared/platform/zephyr/zephyr_sleep.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + */ + +#include "platform_api_extension.h" + +// #include + +/* + * Assuming CONFIG_POSIX_API=n + * Inspired zephyr/lib/posix/options/clock.c + */ + +__wasi_errno_t +os_nanosleep(os_timespec *req, os_timespec *rem) +{ + // __wasi_errno_t ret; + + // if (req == NULL){ + // return __WASI_EINVAL; + // } + + // /* + // * os_timespec is typedef'ed to struct timespec so it's one to one. + // * Also sys_clock_nanosleep return either: + // * * 0 on sucess + // * * -EINVAL on failure + // */ + // int rc = sys_clock_nanosleep(SYS_CLOCK_REALTIME, 0, req, rem); + // if (0 > rc){ + // return __WASI_EINVAL; + // } + + return __WASI_ESUCCESS; +} + +/* + * Don't exist in v3.7 + * + * Inspired zephyr/lib/posix/options/clock.c on main + */ + +// int sys_clock_nanosleep(int clock_id, int flags, const struct timespec *rqtp, +// struct timespec *rmtp) +// { +// k_timepoint_t end; +// k_timeout_t timeout; +// struct timespec duration; +// const bool update_rmtp = rmtp != NULL; +// const bool abstime = (flags & SYS_TIMER_ABSTIME) != 0; + + +// /* +// * Arguments checks +// */ +// if((clock_id != SYS_CLOCK_MONOTONIC) && +// (clock_id != SYS_CLOCK_REALTIME)){ +// return __WASI_EINVAL; +// } + +// if((rqtp->tv_sec < 0) || +// (rqtp->tv_nsec < 0) || +// (rqtp->tv_nsec >= (long)NSEC_PER_SEC)){ +// return __WASI_EINVAL; +// } + + +// if (abstime) { +// /* convert absolute time to relative time duration */ +// (void)sys_clock_gettime(clock_id, &duration); +// (void)timespec_negate(&duration); +// (void)timespec_add(&duration, rqtp); +// } else { +// duration = *rqtp; +// } + +// /* sleep for relative time duration */ +// if ((sizeof(rqtp->tv_sec) == sizeof(int64_t)) && +// unlikely(rqtp->tv_sec >= (time_t)(UINT64_MAX / NSEC_PER_SEC))) { +// uint64_t ns = (uint64_t)k_sleep(K_SECONDS(duration.tv_sec - 1)) * NSEC_PER_MSEC; +// struct timespec rem = { +// .tv_sec = (time_t)(ns / NSEC_PER_SEC), +// .tv_nsec = ns % NSEC_PER_MSEC, +// }; + +// duration.tv_sec = 1; +// (void)timespec_add(&duration, &rem); +// } + +// timeout = timespec_to_timeout(&duration, NULL); +// end = sys_timepoint_calc(timeout); +// do { +// (void)k_sleep(timeout); +// timeout = sys_timepoint_timeout(end); +// } while (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)); + +// if (update_rmtp) { +// *rmtp = (struct timespec){ +// .tv_sec = 0, +// .tv_nsec = 0, +// }; +// } + +// return 0; +// } From 9658fdd7756b19a172d58d8344752f75241ef193 Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Tue, 9 Sep 2025 12:32:35 +0200 Subject: [PATCH 4/7] fix(zephyr): Add os_nanosleep impleemntation for POSIX platform --- core/shared/platform/common/posix/posix_sleep.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/shared/platform/common/posix/posix_sleep.c b/core/shared/platform/common/posix/posix_sleep.c index fa0645037a..19a81ae01d 100644 --- a/core/shared/platform/common/posix/posix_sleep.c +++ b/core/shared/platform/common/posix/posix_sleep.c @@ -6,6 +6,7 @@ #include #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(os_timespec *req, os_timespec *rem) +{ + int ret; + + ret = nanosleep(req, rem); + + return convert_errno(ret); +} \ No newline at end of file From 01dff3a62707c9942aae6400f8852542d8f4ec0b Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Mon, 15 Sep 2025 14:48:55 +0200 Subject: [PATCH 5/7] fix(zephyr): Provide a Zephyr naive implementation for os_nanosleep. --- .../platform/common/posix/posix_sleep.c | 2 +- .../platform/include/platform_api_extension.h | 2 +- core/shared/platform/zephyr/zephyr_sleep.c | 188 +++++++++--------- 3 files changed, 100 insertions(+), 92 deletions(-) diff --git a/core/shared/platform/common/posix/posix_sleep.c b/core/shared/platform/common/posix/posix_sleep.c index 19a81ae01d..541c671928 100644 --- a/core/shared/platform/common/posix/posix_sleep.c +++ b/core/shared/platform/common/posix/posix_sleep.c @@ -21,7 +21,7 @@ os_usleep(uint32 usec) } __wasi_errno_t -os_nanosleep(os_timespec *req, os_timespec *rem) +os_nanosleep(const os_timespec *req, os_timespec *rem) { int ret; diff --git a/core/shared/platform/include/platform_api_extension.h b/core/shared/platform/include/platform_api_extension.h index ffd028c1ea..14b72a6bfb 100644 --- a/core/shared/platform/include/platform_api_extension.h +++ b/core/shared/platform/include/platform_api_extension.h @@ -1770,7 +1770,7 @@ os_compare_file_handle(os_file_handle handle1, os_file_handle handle2); * __WASI_EINVAL The req input is badly formed. */ __wasi_errno_t -os_nanosleep(os_timespec *req, os_timespec *rem); +os_nanosleep(const os_timespec *req, os_timespec *rem); #ifdef __cplusplus diff --git a/core/shared/platform/zephyr/zephyr_sleep.c b/core/shared/platform/zephyr/zephyr_sleep.c index e6236ace42..fe625aa12e 100644 --- a/core/shared/platform/zephyr/zephyr_sleep.c +++ b/core/shared/platform/zephyr/zephyr_sleep.c @@ -2,105 +2,113 @@ * Copyright (C) 2024 Grenoble INP - ESISAR. All rights reserved. * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception */ - #include "platform_api_extension.h" -// #include - /* - * Assuming CONFIG_POSIX_API=n - * Inspired zephyr/lib/posix/options/clock.c + * 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. */ +#ifdef CONFIG_TIMEOUT_64BIT +static int64_t timespec_to_ticks(const os_timespec *ts); +#else +static uint32_t timespec_to_ticks(const os_timespec *ts); +#endif + __wasi_errno_t -os_nanosleep(os_timespec *req, os_timespec *rem) +os_nanosleep(const os_timespec *req, os_timespec *rem) { - // __wasi_errno_t ret; - - // if (req == NULL){ - // return __WASI_EINVAL; - // } - - // /* - // * os_timespec is typedef'ed to struct timespec so it's one to one. - // * Also sys_clock_nanosleep return either: - // * * 0 on sucess - // * * -EINVAL on failure - // */ - // int rc = sys_clock_nanosleep(SYS_CLOCK_REALTIME, 0, req, rem); - // if (0 > rc){ - // return __WASI_EINVAL; - // } + k_timeout_t timeout; + + if (req == NULL){ + return __WASI_EINVAL; + } + + timeout.ticks = (k_ticks_t) 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 && 0 < rc){ + rem->tv_sec = rc / 1000; + rem->tv_nsec = ( rc % 1000 ) * 1000000; + } return __WASI_ESUCCESS; } -/* - * Don't exist in v3.7 - * - * Inspired zephyr/lib/posix/options/clock.c on main - */ -// int sys_clock_nanosleep(int clock_id, int flags, const struct timespec *rqtp, -// struct timespec *rmtp) -// { -// k_timepoint_t end; -// k_timeout_t timeout; -// struct timespec duration; -// const bool update_rmtp = rmtp != NULL; -// const bool abstime = (flags & SYS_TIMER_ABSTIME) != 0; - - -// /* -// * Arguments checks -// */ -// if((clock_id != SYS_CLOCK_MONOTONIC) && -// (clock_id != SYS_CLOCK_REALTIME)){ -// return __WASI_EINVAL; -// } - -// if((rqtp->tv_sec < 0) || -// (rqtp->tv_nsec < 0) || -// (rqtp->tv_nsec >= (long)NSEC_PER_SEC)){ -// return __WASI_EINVAL; -// } - - -// if (abstime) { -// /* convert absolute time to relative time duration */ -// (void)sys_clock_gettime(clock_id, &duration); -// (void)timespec_negate(&duration); -// (void)timespec_add(&duration, rqtp); -// } else { -// duration = *rqtp; -// } - -// /* sleep for relative time duration */ -// if ((sizeof(rqtp->tv_sec) == sizeof(int64_t)) && -// unlikely(rqtp->tv_sec >= (time_t)(UINT64_MAX / NSEC_PER_SEC))) { -// uint64_t ns = (uint64_t)k_sleep(K_SECONDS(duration.tv_sec - 1)) * NSEC_PER_MSEC; -// struct timespec rem = { -// .tv_sec = (time_t)(ns / NSEC_PER_SEC), -// .tv_nsec = ns % NSEC_PER_MSEC, -// }; - -// duration.tv_sec = 1; -// (void)timespec_add(&duration, &rem); -// } - -// timeout = timespec_to_timeout(&duration, NULL); -// end = sys_timepoint_calc(timeout); -// do { -// (void)k_sleep(timeout); -// timeout = sys_timepoint_timeout(end); -// } while (!K_TIMEOUT_EQ(timeout, K_NO_WAIT)); - -// if (update_rmtp) { -// *rmtp = (struct timespec){ -// .tv_sec = 0, -// .tv_nsec = 0, -// }; -// } - -// return 0; -// } +#ifdef CONFIG_TIMEOUT_64BIT + +static int64_t timespec_to_ticks(const os_timespec *ts) +{ + const uint64_t ticks_per_sec = CONFIG_SYS_CLOCK_TICKS_PER_SEC; + uint64_t ticks = 0; + + if (ts->tv_sec > UINT64_MAX / ticks_per_sec) { + return UINT64_MAX; + } + + ticks = (uint64_t)ts->tv_sec * ticks_per_sec; + + if (ts->tv_nsec > 0) { + uint64_t add = (uint64_t)ts->tv_nsec * ticks_per_sec / 1000000000ULL; + if (ticks > UINT64_MAX - add) { + return UINT64_MAX; + } + ticks += add; + } + + return ticks; +} + +#else /* CONFIG_TIMEOUT_32BIT */ + +static uint32_t timespec_to_ticks(const os_timespec *ts) +{ + const uint32_t ticks_per_sec = CONFIG_SYS_CLOCK_TICKS_PER_SEC; + uint32_t ticks = 0; + + if (ts->tv_sec > UINT32_MAX / ticks_per_sec) { + return UINT32_MAX; + } + + ticks = (uint32_t)ts->tv_sec * ticks_per_sec; + + if (ts->tv_nsec > 0) { + uint64_t add64 = (uint64_t)ts->tv_nsec * ticks_per_sec; + uint32_t add = (uint32_t)(add64 / 1000000000ULL); + if (ticks > UINT32_MAX - add) { + return UINT32_MAX; + } + ticks += add; + } + + return ticks; +} + +#endif /* CONFIG_TIMEOUT_64BIT */ \ No newline at end of file From d9b5d66774ddad6907737527dcca7ee7e8c217a2 Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Mon, 15 Sep 2025 15:59:08 +0200 Subject: [PATCH 6/7] fix(zephyr): Refactor the nanosleep and helpers functions --- core/shared/platform/zephyr/zephyr_sleep.c | 98 ++++++++++++---------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/core/shared/platform/zephyr/zephyr_sleep.c b/core/shared/platform/zephyr/zephyr_sleep.c index fe625aa12e..42755ec5a4 100644 --- a/core/shared/platform/zephyr/zephyr_sleep.c +++ b/core/shared/platform/zephyr/zephyr_sleep.c @@ -30,22 +30,32 @@ * Note: this assumes `CONFIG_POSIX_API=n` in the Zephyr application. */ -#ifdef CONFIG_TIMEOUT_64BIT -static int64_t timespec_to_ticks(const os_timespec *ts); -#else -static uint32_t timespec_to_ticks(const os_timespec *ts); -#endif +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; } - timeout.ticks = (k_ticks_t) timespec_to_ticks(req); + if (req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000) { + 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: @@ -53,62 +63,58 @@ os_nanosleep(const os_timespec *req, os_timespec *rem) * * >0 remaining time in ms (due to k_wakeup). */ int32_t rc = k_sleep(timeout); - if (rem != NULL && 0 < rc){ - rem->tv_sec = rc / 1000; - rem->tv_nsec = ( rc % 1000 ) * 1000000; + if (rem != NULL) { + if (rc > 0) { + +#ifdef CONFIG_TIMEOUT_64BIT + rem_ticks = (k_ticks_t)((uint64_t)rc * CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000); +#else /* CONFIG_TIMEOUT_32BIT */ + uint64_t temp_ticks = (uint64_t)rc * CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000; + 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; } -#ifdef CONFIG_TIMEOUT_64BIT - -static int64_t timespec_to_ticks(const os_timespec *ts) +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 ticks = 0; + uint64_t total_ns, ticks; - if (ts->tv_sec > UINT64_MAX / ticks_per_sec) { - return UINT64_MAX; - } + total_ns = (uint64_t)ts->tv_sec * 1000000000ULL + (uint64_t)ts->tv_nsec; + ticks = total_ns * ticks_per_sec / 1000000000ULL; - ticks = (uint64_t)ts->tv_sec * ticks_per_sec; - - if (ts->tv_nsec > 0) { - uint64_t add = (uint64_t)ts->tv_nsec * ticks_per_sec / 1000000000ULL; - if (ticks > UINT64_MAX - add) { - return UINT64_MAX; - } - ticks += add; +#ifdef CONFIG_TIMEOUT_64BIT + if (ticks > INT64_MAX) { + return INT64_MAX; } +#else /* CONFIG_TIMEOUT_32BIT */ + if (ticks > UINT32_MAX) { + return UINT32_MAX; + } +#endif - return ticks; + return (k_ticks_t)ticks; } -#else /* CONFIG_TIMEOUT_32BIT */ - -static uint32_t timespec_to_ticks(const os_timespec *ts) +static void ticks_to_timespec(k_ticks_t ticks, os_timespec *ts) { - const uint32_t ticks_per_sec = CONFIG_SYS_CLOCK_TICKS_PER_SEC; - uint32_t ticks = 0; - - if (ts->tv_sec > UINT32_MAX / ticks_per_sec) { - return UINT32_MAX; - } - - ticks = (uint32_t)ts->tv_sec * ticks_per_sec; + const uint64_t ticks_per_sec = CONFIG_SYS_CLOCK_TICKS_PER_SEC; + uint64_t total_ns; - if (ts->tv_nsec > 0) { - uint64_t add64 = (uint64_t)ts->tv_nsec * ticks_per_sec; - uint32_t add = (uint32_t)(add64 / 1000000000ULL); - if (ticks > UINT32_MAX - add) { - return UINT32_MAX; - } - ticks += add; + if (ts == NULL) { + return; } - return ticks; -} + total_ns = ((uint64_t)ticks * 1000000000ULL) / ticks_per_sec; -#endif /* CONFIG_TIMEOUT_64BIT */ \ No newline at end of file + ts->tv_sec = (long)(total_ns / 1000000000ULL); + ts->tv_nsec = (long)(total_ns % 1000000000ULL); +} \ No newline at end of file From b69ff79e706040f843f41f43d8c86561735e4edc Mon Sep 17 00:00:00 2001 From: Lucas Abad <149054121+lucasAbadFr@users.noreply.github.com> Date: Mon, 15 Sep 2025 16:25:08 +0200 Subject: [PATCH 7/7] fix(zephyr): Use zephyr macros instead of hardcoded values --- core/shared/platform/zephyr/zephyr_sleep.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/shared/platform/zephyr/zephyr_sleep.c b/core/shared/platform/zephyr/zephyr_sleep.c index 42755ec5a4..8de9c73227 100644 --- a/core/shared/platform/zephyr/zephyr_sleep.c +++ b/core/shared/platform/zephyr/zephyr_sleep.c @@ -43,7 +43,7 @@ os_nanosleep(const os_timespec *req, os_timespec *rem) return __WASI_EINVAL; } - if (req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= 1000000000) { + if (req->tv_sec < 0 || req->tv_nsec < 0 || req->tv_nsec >= NSEC_PER_SEC) { return __WASI_EINVAL; } @@ -67,9 +67,9 @@ os_nanosleep(const os_timespec *req, os_timespec *rem) if (rc > 0) { #ifdef CONFIG_TIMEOUT_64BIT - rem_ticks = (k_ticks_t)((uint64_t)rc * CONFIG_SYS_CLOCK_TICKS_PER_SEC / 1000); + 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 / 1000; + 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); @@ -88,8 +88,8 @@ 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 * 1000000000ULL + (uint64_t)ts->tv_nsec; - ticks = total_ns * ticks_per_sec / 1000000000ULL; + 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) { @@ -113,8 +113,8 @@ static void ticks_to_timespec(k_ticks_t ticks, os_timespec *ts) return; } - total_ns = ((uint64_t)ticks * 1000000000ULL) / ticks_per_sec; + total_ns = ((uint64_t)ticks * NSEC_PER_SEC) / ticks_per_sec; - ts->tv_sec = (long)(total_ns / 1000000000ULL); - ts->tv_nsec = (long)(total_ns % 1000000000ULL); + ts->tv_sec = (long)(total_ns / NSEC_PER_SEC); + ts->tv_nsec = (long)(total_ns % NSEC_PER_SEC); } \ No newline at end of file