lib: posix: nanosleep
This change adds support for nanosleep(2) documented at https://pubs.opengroup.org/onlinepubs/9699919799/functions/nanosleep.html N.B: Currently, this provides no better resolution than k_busy_wait() Fixes #25554 Signed-off-by: Christopher Friedt <chrisfriedt@gmail.com>
This commit is contained in:
parent
8c29aa9881
commit
8bcf005084
|
@ -91,6 +91,7 @@ int timer_delete(timer_t timerid);
|
|||
int timer_gettime(timer_t timerid, struct itimerspec *its);
|
||||
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
|
||||
struct itimerspec *ovalue);
|
||||
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -24,6 +24,10 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c)
|
|||
zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c)
|
||||
zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c)
|
||||
|
||||
if(NOT (CONFIG_BOARD_NATIVE_POSIX OR CONFIG_BOARD_NATIVE_POSIX_64BIT))
|
||||
zephyr_library_sources(nanosleep.c)
|
||||
endif()
|
||||
|
||||
zephyr_library_include_directories(
|
||||
${ZEPHYR_BASE}/kernel/include
|
||||
${ZEPHYR_BASE}/arch/${ARCH}/include
|
||||
|
|
60
lib/posix/nanosleep.c
Normal file
60
lib/posix/nanosleep.c
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* Copyright (c) 2018 Friedt Professional Engineering Services, Inc
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <kernel.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
/* required for struct timespec */
|
||||
#include <posix/time.h>
|
||||
#include <sys_clock.h>
|
||||
|
||||
/**
|
||||
* @brief Suspend execution for nanosecond intervals.
|
||||
*
|
||||
* See IEEE 1003.1
|
||||
*/
|
||||
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||
{
|
||||
uint64_t ns;
|
||||
const bool update_rmtp = rmtp != NULL;
|
||||
|
||||
if (rqtp == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0
|
||||
|| rqtp->tv_nsec >= NSEC_PER_SEC) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rqtp->tv_sec == 0 && rqtp->tv_nsec == 0) {
|
||||
goto do_rmtp_update;
|
||||
}
|
||||
|
||||
if (unlikely(rqtp->tv_sec >= ULLONG_MAX / NSEC_PER_SEC)) {
|
||||
/* If a user passes this in, we could be here a while, but
|
||||
* at least it's technically correct-ish
|
||||
*/
|
||||
ns = rqtp->tv_nsec + NSEC_PER_SEC;
|
||||
k_sleep(K_SECONDS(rqtp->tv_sec - 1));
|
||||
} else {
|
||||
ns = rqtp->tv_sec * NSEC_PER_SEC + rqtp->tv_nsec;
|
||||
}
|
||||
|
||||
/* currently we have no mechanism to achieve greater resolution */
|
||||
k_busy_wait(ns / NSEC_PER_USEC);
|
||||
|
||||
do_rmtp_update:
|
||||
if (update_rmtp) {
|
||||
rmtp->tv_sec = 0;
|
||||
rmtp->tv_nsec = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in a new issue