Skip to content

sys: clock: add sys_clock api and remove posix from iso c time #90096

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion MAINTAINERS.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2556,7 +2556,6 @@ Utilities:
- tests/unit/list/
- tests/unit/intmath/
- tests/unit/pot/
- tests/lib/time/
- tests/lib/onoff/
- tests/lib/sys_util/
- tests/lib/sprintf/
Expand Down
3 changes: 3 additions & 0 deletions doc/releases/release-notes-4.2.rst
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,9 @@ New APIs and options

* :c:func:`util_eq`
* :c:func:`util_memeq`
* :c:func:`sys_clock_gettime`
* :c:func:`sys_clock_settime`
* :c:func:`sys_clock_nanosleep`

* LoRaWAN
* :c:func:`lorawan_request_link_check`
Expand Down
7 changes: 4 additions & 3 deletions include/zephyr/posix/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,14 @@ struct itimerspec {
#include <errno.h>
#include <zephyr/posix/posix_types.h>
#include <zephyr/posix/signal.h>
#include <zephyr/sys/clock.h>

#ifdef __cplusplus
extern "C" {
#endif

#ifndef CLOCK_REALTIME
#define CLOCK_REALTIME 1
#define CLOCK_REALTIME SYS_CLOCK_REALTIME
#endif

#ifndef CLOCK_PROCESS_CPUTIME_ID
Expand All @@ -78,11 +79,11 @@ extern "C" {
#endif

#ifndef CLOCK_MONOTONIC
#define CLOCK_MONOTONIC 4
#define CLOCK_MONOTONIC SYS_CLOCK_MONOTONIC
#endif

#ifndef TIMER_ABSTIME
#define TIMER_ABSTIME 4
#define TIMER_ABSTIME SYS_TIMER_ABSTIME
#endif

int clock_gettime(clockid_t clock_id, struct timespec *ts);
Expand Down
134 changes: 134 additions & 0 deletions include/zephyr/sys/clock.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
/*
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A new sys/clock.h header may seem a bit confusing given that we have a sys_clock.h already

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with this point. This can be a bit confusing, and given that this is a new API class, would you be ok to discuss this tomorrow in the Architecture WG @cfriedt?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Of course - I agree that it was a little weird how we have a sys_clock.h and a sys/clock.h.

Copy link
Member Author

@cfriedt cfriedt May 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@carlescufi - what do you suggest we do in terms of sys_clock.h and sys/clock.h? I kind of like the sys/clock.h header better (🤷‍♂️ ) but sys_clock.h has already existed for a long time.

Would it be sufficient to merge the two files into sys/clock.h and have sys_clock.h include sys/clock.h?

We could at some point deprecate sys_clock.h

The alternative is moving sys/clock.h contents into sys_clock.h, but then we have to live wth a kind of oddly named file. Merging the headers could also happen outside of this PR.

There seem to be no conflicting toolchain paths that would interfere with sys/clock.h.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here one can have quite different opinions, so just my two cents: To me it looks like this is a addon that would fit better in timeutil.h/c than in sys_clock.
I would really not rename the current sys_clock.h (that would cause quite a bit of churn).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To me it looks like this is a addon that would fit better in timeutil.h/c than in sys_clock.

Although the added sys_clock API uses timeutil APIs, those are quite different and have very different purposes.

I originally thought that this code should have the k_ prefix, but @peter-mitsis suggested it be given the sys_ prefix. I'm inclined to agree with him here.

The added code does what much of the sys_clock code does today, which is to deal with ticks and represent system clock interfaces (in more or less abstract ways).

I would really not rename the current sys_clock.h (that would cause quite a bit of churn).

If you re-read my suggestion, there was no mention of renaming sys_clock.h .

It was to merge the contents of the two headers (sys_clock.h and sys/clock.h) into one, keep them both, have one include the other. Presumably into sys/clock.h because the other is kind of oddly named.

One file could eventually be deprecated (the smaller of the two), but there is no rush to do that.

So no "churn".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that simply merging the contents of the two headers will result in compile failures, so I don't think it will be done in this PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I personally don't mind either way, as long as we do not introduce this confusion of sys_clock vs sys/clock. Personally I am in favor of having it use the sys_ prefix, so for me perhaps the best long-term solution would be to keep a sys_clock.h that only includes the new sys/clock.h that then has the contents of both.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cfriedt I still see sys_clock.h and sys/clock.h with different contents. Can we move the contents of sys_clock.h to the new sys/clock.h?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see you are testing it in a draft PR :) thanks!

* Copyright (c) 2025 Tenstorrent AI ULC
*
* SPDX-License-Identifier: Apache-2.0
*/

/**
* @file
* @brief System clock APIs
*
* APIs for getting, setting, and sleeping with respect to system clocks.
*/

#ifndef ZEPHYR_INCLUDE_SYSCLOCK_H_
#define ZEPHYR_INCLUDE_SYSCLOCK_H_

#include <time.h>

#include <zephyr/toolchain.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
* @addtogroup clock_apis
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the PR title/description and content, I'm not sure if this PR tries to add a new API set (and happened to also use by mistake the sys_clock prefix), or tries to expand the "System Clock APIs".

If this is meant to be a new set:
I guess this would need to be added to a new doxygen group, marked as experimental and its version set to 0.1
https://docs.zephyrproject.org/latest/develop/api/api_lifecycle.html#experimental
with another API prefix.

In any case, I think it would need to follow this process:
https://docs.zephyrproject.org/latest/contribute/proposals_and_rfcs.html#proposals-and-rfcs

Copy link
Member Author

@cfriedt cfriedt May 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR is expanding the "System Clock APIs".

It's hardly experimental. The same code has been used already in Zephyr for many years, and for the most part, this PR is just shuffling existing code around.

But sure, I will put together an RFC, likely not in time for tomorrow's arch meeting.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given there are a few RFCs on this topic already, I think we can skip making a new one.

* @{
*/

/**
* @brief The real-time clock (i.e. "wall clock")
*
* This clock is used to measure time since the epoch (1970-01-01 00:00:00 UTC).
*
* It is not a steady clock; i.e. it may be adjusted for a number of reasons from initialization
* of a hardware real-time-clock, to network-time synchronization, to manual adjustment from the
* application.
*/
#define SYS_CLOCK_REALTIME 1

/**
* @brief The monotonic clock
*
* This steady clock is used to measure time since the system booted. Time from this clock is
* always monotonically increasing.
*/
#define SYS_CLOCK_MONOTONIC 4

/**
* @brief The flag used for specifying absolute timeouts
*
* This flag may be passed to @ref sys_clock_nanosleep to indicate the requested timeout is an
* absolute time with respect to the specified clock.
*/
#define SYS_TIMER_ABSTIME 4

/**
* @brief Get the offset @ref SYS_CLOCK_REALTIME with respect to @ref SYS_CLOCK_MONOTONIC
*
* The "wall clock" (i.e. @ref SYS_CLOCK_REALTIME) depends on a base time that is set by the
* system. The base time may be updated for a number of reasons, such as initialization of a
* hardware real-time-clock (RTC), network time protocol (NTP) synchronization, or manual
* adjustment by the application.
*
* This function retrieves the current time offset, as a `timespec` object, for
* @ref SYS_CLOCK_REALTIME, with respect to @ref SYS_CLOCK_MONOTONIC, and writes it to the
* provided memory location pointed-to by @a tp.
*
* @note This function may assert if @a tp is NULL.
*
* @param tp Pointer to memory where time will be written.
*/
__syscall void sys_clock_getrtoffset(struct timespec *tp);

/**
* @brief Get the current time from the specified clock
*
* @param clock_id The clock from which to query time.
* @param tp Pointer to memory where time will be written.
* @retval 0 on success.
* @retval -EINVAL when an invalid @a clock_id is specified.
*/
int sys_clock_gettime(int clock_id, struct timespec *tp);

/**
* @brief Set the current time for the specified clock
*
* @param clock_id The clock for which the time should be set.
* @param tp Pointer to memory specifying the desired time.
* @retval 0 on success.
* @retval -EINVAL when an invalid @a clock_id is specified or when @a tp contains nanoseconds
* outside of the range `[0, 999999999]`.
*/
__syscall int sys_clock_settime(int clock_id, const struct timespec *tp);

/**
* @brief Sleep for the specified amount of time with respect to the specified clock.
*
* This function will cause the calling thread to sleep either
* - until the absolute time specified by @a rqtp (if @a flags includes @ref SYS_TIMER_ABSTIME), or
* - until the relative time specified by @a rqtp (if @a flags does not include
* @ref SYS_TIMER_ABSTIME).
*
* The accepted values for @a clock_id include
* - @ref SYS_CLOCK_REALTIME
* - @ref SYS_CLOCK_MONOTONIC
*
* If @a rmtp is not NULL, and the thread is awoken prior to the time specified by @a rqtp, then
* any remaining time will be written to @a rmtp. If the thread has slept for at least the time
* specified by @a rqtp, then @a rmtp will be set to zero.
*
* @param clock_id The clock to by which to sleep.
* @param flags Flags to modify the behavior of the sleep operation.
* @param rqtp Pointer to the requested time to sleep.
* @param rmtp Pointer to memory into which to copy the remaining time, if any.
*
* @retval 0 on success.
* @retval -EINVAL when an invalid @a clock_id, when @a rqtp contains nanoseconds outside of the
* range `[0, 999999999]`, or when @a rqtp contains a negative value.
*/
__syscall int sys_clock_nanosleep(int clock_id, int flags, const struct timespec *rqtp,
struct timespec *rmtp);

/**
* @}
*/

#include <zephyr/syscalls/clock.h>

#ifdef __cplusplus
}
#endif

#endif
5 changes: 4 additions & 1 deletion lib/libc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ config MINIMAL_LIBC
imply COMMON_LIBC_MALLOC
imply COMMON_LIBC_CALLOC
imply COMMON_LIBC_REALLOCARRAY
imply COMMON_LIBC_TIME
help
Build with minimal C library.

Expand All @@ -96,6 +97,7 @@ config PICOLIBC
select TC_PROVIDES_POSIX_C_LANG_SUPPORT_R
imply COMMON_LIBC_MALLOC
imply COMMON_LIBC_ABORT
imply COMMON_LIBC_TIME
depends on PICOLIBC_SUPPORTED
help
Build with picolibc library. The picolibc library is built as
Expand All @@ -116,6 +118,7 @@ config NEWLIB_LIBC
imply POSIX_FILE_SYSTEM_ALIAS_FSTAT
imply POSIX_MULTI_PROCESS_ALIAS_GETPID
imply POSIX_SIGNALS_ALIAS_KILL
imply COMMON_LIBC_TIME
help
Build with newlib library. The newlib library is expected to be
part of the SDK in this case.
Expand All @@ -137,7 +140,7 @@ config IAR_LIBC
depends on IAR_LIBC_SUPPORTED
depends on "$(ZEPHYR_TOOLCHAIN_VARIANT)" = "iar"
select COMMON_LIBC_STRNLEN
select COMMON_LIBC_TIME if POSIX_TIMERS
select COMMON_LIBC_TIME
help
Use the full IAR Compiler runtime libraries.
A reduced Zephyr minimal libc will be used for library functionality
Expand Down
7 changes: 6 additions & 1 deletion lib/libc/common/source/thrd/thrd.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#include <zephyr/kernel.h>
#include <zephyr/posix/pthread.h>
#include <zephyr/posix/sched.h>
#include <zephyr/sys/clock.h>

struct thrd_trampoline_arg {
thrd_start_t func;
Expand Down Expand Up @@ -44,7 +45,11 @@ thrd_t thrd_current(void)

int thrd_sleep(const struct timespec *duration, struct timespec *remaining)
{
return nanosleep(duration, remaining);
if (sys_clock_nanosleep(SYS_CLOCK_REALTIME, 0, duration, remaining) != 0) {
return thrd_error;
}

return thrd_success;
}

void thrd_yield(void)
Expand Down
9 changes: 5 additions & 4 deletions lib/libc/common/source/time/time.c
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
/*
* Copyright (c) 2021 Golioth, Inc.
* Copyright (c) 2025 Tenstorrent AI ULC
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <errno.h>
#include <time.h>

/* clock_gettime() prototype */
#include <zephyr/posix/time.h>
#include <zephyr/sys/clock.h>

time_t time(time_t *tloc)
{
struct timespec ts;
int ret;

ret = clock_gettime(CLOCK_REALTIME, &ts);
ret = sys_clock_gettime(SYS_CLOCK_REALTIME, &ts);
if (ret < 0) {
/* errno is already set by clock_gettime */
errno = -ret;
return (time_t) -1;
}

Expand Down
2 changes: 2 additions & 0 deletions lib/os/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
# SPDX-License-Identifier: Apache-2.0

zephyr_syscall_header(
${ZEPHYR_BASE}/include/zephyr/sys/clock.h
${ZEPHYR_BASE}/include/zephyr/sys/mutex.h
)

zephyr_sources(
cbprintf_packaged.c
clock.c
printk.c
sem.c
thread_entry.c
Expand Down
Loading
Loading