Skip to content

Commit 8bcf005

Browse files
cfriedtcarlescufi
authored andcommitted
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 <[email protected]>
1 parent 8c29aa9 commit 8bcf005

File tree

3 files changed

+65
-0
lines changed

3 files changed

+65
-0
lines changed

include/posix/time.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ int timer_delete(timer_t timerid);
9191
int timer_gettime(timer_t timerid, struct itimerspec *its);
9292
int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
9393
struct itimerspec *ovalue);
94+
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
9495

9596
#ifdef __cplusplus
9697
}

lib/posix/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ zephyr_library_sources_ifdef(CONFIG_POSIX_MQUEUE mqueue.c)
2424
zephyr_library_sources_ifdef(CONFIG_POSIX_FS fs.c)
2525
zephyr_library_sources_ifdef(CONFIG_EVENTFD eventfd.c)
2626

27+
if(NOT (CONFIG_BOARD_NATIVE_POSIX OR CONFIG_BOARD_NATIVE_POSIX_64BIT))
28+
zephyr_library_sources(nanosleep.c)
29+
endif()
30+
2731
zephyr_library_include_directories(
2832
${ZEPHYR_BASE}/kernel/include
2933
${ZEPHYR_BASE}/arch/${ARCH}/include

lib/posix/nanosleep.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2018 Friedt Professional Engineering Services, Inc
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <stdint.h>
8+
#include <kernel.h>
9+
#include <limits.h>
10+
#include <errno.h>
11+
/* required for struct timespec */
12+
#include <posix/time.h>
13+
#include <sys_clock.h>
14+
15+
/**
16+
* @brief Suspend execution for nanosecond intervals.
17+
*
18+
* See IEEE 1003.1
19+
*/
20+
int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
21+
{
22+
uint64_t ns;
23+
const bool update_rmtp = rmtp != NULL;
24+
25+
if (rqtp == NULL) {
26+
errno = EFAULT;
27+
return -1;
28+
}
29+
30+
if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0
31+
|| rqtp->tv_nsec >= NSEC_PER_SEC) {
32+
errno = EINVAL;
33+
return -1;
34+
}
35+
36+
if (rqtp->tv_sec == 0 && rqtp->tv_nsec == 0) {
37+
goto do_rmtp_update;
38+
}
39+
40+
if (unlikely(rqtp->tv_sec >= ULLONG_MAX / NSEC_PER_SEC)) {
41+
/* If a user passes this in, we could be here a while, but
42+
* at least it's technically correct-ish
43+
*/
44+
ns = rqtp->tv_nsec + NSEC_PER_SEC;
45+
k_sleep(K_SECONDS(rqtp->tv_sec - 1));
46+
} else {
47+
ns = rqtp->tv_sec * NSEC_PER_SEC + rqtp->tv_nsec;
48+
}
49+
50+
/* currently we have no mechanism to achieve greater resolution */
51+
k_busy_wait(ns / NSEC_PER_USEC);
52+
53+
do_rmtp_update:
54+
if (update_rmtp) {
55+
rmtp->tv_sec = 0;
56+
rmtp->tv_nsec = 0;
57+
}
58+
59+
return 0;
60+
}

0 commit comments

Comments
 (0)