POSIX leaves the signedness of time_t and clock_t unspecified, but
mainstream implementations (Linux glibc/musl, the BSDs, macOS, RTEMS,
Zephyr's POSIX layer, Windows _time64) expose time_t as signed 64-bit.
NuttX has historically used uint64_t only because it was tied to the
CONFIG_SYSTEM_TIME64 knob; with that gone, switch:
time_t : uint64_t -> int64_t
clock_t : uint64_t -> int64_t
CLOCK_MAX: UINT64_MAX -> INT64_MAX
This lets (time_t)-1 sentinels, negative tick deltas, and host-side
headers behave as on every other POSIX system without source churn.
Headers updated:
- include/sys/types.h, include/limits.h, include/nuttx/clock.h
- include/nuttx/fs/hostfs.h (nuttx_time_t alias)
- include/nuttx/{mqueue.h,wdog.h,wqueue.h,timers/clkcnt.h}
Because clock_t is now signed 64-bit, the NuttX-internal sclock_t
alias becomes redundant: every sclock_t/SCLOCK_MAX use is folded
back to clock_t/CLOCK_MAX (notably in sched/wdog, sched/mqueue,
sched/sched, sched/clock, sched/timer, libs/libc/time, fs/vfs and
the drivers/arch consumers below).
Tick/period constants (NSEC_PER_SEC, USEC_PER_SEC, MSEC_PER_SEC,
SEC_PER_MIN, ...) in include/nuttx/clock.h are retyped from "long"
literals to INT64_C(...) so that 64-bit arithmetic no longer
depends on the host's long width.
Strip now-redundant (time_t)/(clock_t)/(unsigned long) casts and
unsigned-only branches across the tree:
- arch RTC / oneshot / tickless lowerhalfs:
arm: cxd56xx, efm32, imxrt, lc823450, max326xx, sam34, sama5,
samd5e5, samv7, stm32, stm32f7, stm32h7, stm32l4, stm32wb,
xmc4
mips: pic32mz sparc: bm3803 x86_64: intel64
risc-v/xtensa: espressif (esp_i2c[_slave], esp_rtc,
esp32c3{_i2c,_rtc,_wifi_adapter}, esp32{,s2,s3}_*),
mpfs_perf
- drivers: audio/tone, input/aw86225, power/pm/{activity,
stability}_governor, rpmsg/rpmsg_ping,
timers/{ds3231,mcp794xx,pcf85263,rx8010},
wireless/ieee80211/bcm43xxx, wireless/spirit/spirit_spi
- core: fs/vfs/{fs_poll,fs_timerfd}, mm/iob/iob_alloc,
libs/libc/{netdb/lib_dnscache,time/{lib_calendar2utc,
lib_time}}, net/icmp/icmp_pmtu, net/icmpv6/icmpv6_pmtu,
net/ipfrag, net/tcp/{tcp.h,tcp_timer},
net/utils/net_snoop, net/mld/mld_query (drop the now-dead
mld_mrc2mrd helper since signed math handles it directly),
sched/clock/{clock,clock_initialize},
sched/sched/{sched_profil,sched_setparam,sched_setscheduler},
sched/pthread/pthread_create,
sched/wdog/{wd_gettime,wd_start,wdog.h},
sched/timer/timer_gettime, sched/mqueue/*
Flip the few in-tree printf format strings that assumed an
unsigned 64-bit tv_sec:
* drivers/rpmsg/rpmsg_ping.c PRIu64 -> PRId64
* arch/xtensa/src/esp32{,s2,s3}/esp32*_oneshot_lowerhalf.c
PRIu32 (already wrong) -> PRId64
Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
debug.h is a NuttX-specific, non-POSIX header. Placing it in the
top-level include/ directory creates naming conflicts with external
projects that define their own debug.h.
This commit moves the canonical header to include/nuttx/debug.h,
following the NuttX convention for non-POSIX/non-standard headers,
and updates all in-tree references.
A backward-compatibility shim is left at include/debug.h that
emits a deprecation #warning and re-includes <nuttx/debug.h>,
allowing out-of-tree code to continue building while migrating.
Signed-off-by: Piyush Patle <piyushpatle228@gmail.com>
Add support for running the OS in tickless mode with hrtimer, allowing
the scheduler to operate without periodic ticks while maintaining
high-resolution timer functionality.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
This commit simplified the wdog expiration handling by introducing the
`g_sched_event` timer.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
If the wdog use the fine-grained spin-lock, and allow the callback execution without the lock held, there will be incorrect interleaving.
E.g. The first `nxsem_timeout` callback function caused the second semaphore wait to fail.
Core 0 [nxsem_clockwait] | Core 1
enter_critical_section() | ...
wd_start(nxsem_timeout) | ...
nxsem_wait(sem) | wd_expiration() --> nxsem_timeout
wd_cancel(&rtcb->waitdog) | try enter_critical_section()
leave_critical_section() | Failed retry...
....nxsem_clockwait | Failed retry...
enter_critical_section() | Failed retry...
wd_start(nxsem_timeout) | Failed retry...
nxsem_wait(sem) | Core 1 enter the critical section
| nxsem_wait_irq(wtcb, ETIMEDOUT) -> incorrectly wake-up the rtcb.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit reduced 1 write operation for wdog deleting and decoupled
the WDOG_ISACTIVE with the list implementation.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit moved the g_wdtimernested to sched_timerexpiration, since
wdog and hrtimer can share it.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit changed the return value semantics.
In past designs, timers that were expected to fire immediately were delayed by at least one tick, resulting in a decrease in real-time performance.
This commit re-encoded the return value to allow the timers fire
immediately.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
Move wd_start() to an inline function to reduce function call
overhead and improve performance in time-critical watchdog operations.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
The current implementation allows the delay passed to wd_start() to be
equal to WDOG_MAX_DELAY. However, since clock_delay2abstick() internally
increments the delay by one tick, using a delay equal to WDOG_MAX_DELAY
will cause an overflow and make the clock comparison invalid.
This patch fixes the issue by disallowing the delay to be equal to
WDOG_MAX_DELAY.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
Use list_in_list() to determine whether a watchdog is active,
eliminating the need to set the watchdog function pointer to NULL
as an indicator of inactivity.
Signed-off-by: Chengdong Wang wangchengdong@lixiang.com
Currently, wd_timer() obtains the current systick
from the input parameter, and the wdog processes
the list without updating the systick value.
This is not incorrect, as the systick should continue
to increase while the watchdog is processing callbacks.
This patch addresses the issue by retrieving the updated
systick value after each watchdog node loop.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
The wdog implementation redefined `list_node`, which could cause
conflicts or unexpected behavior when both `wdog/wdog.h` and
`list.h` are included in the same source file. This patch removes
the redundant definition to avoid such issues.
Signed-off-by: Chengdong Wang <wangchengdong@lixiang.com>
For better simplicity, this commit replaced the periodical wdog APIs with the more expressive wd_start_next. The wd_start_next restarts watchdog timer based on the last expiration time.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit changed the type of the delay ticks to the unsigned, which can reduce the useless branch conditions
Besides, this commit added max delay tick limitation to fix incorrect timing behavior if we delay SCLOCK_MAX in the SMP build.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
In case the wdog has already completed when calling cancel, the cancel is
supposed to just return OK.
Signed-off-by: Jukka Laitinen <jukka.laitinen@tii.ae>
This commit added a macro function clock_delay2abstick to calculate the
absolute tick after the delay.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
To improve the absolute timer accuracy, this commit move the tick++ to relative wdog timer.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
For the watchdog list and the workqueue list, we wonder whether the list head has changed after the insertion. In the original implementation, we have to access the list->next field and compare the result to the currently inserted node. In this commit, we mark the list head before the insertion and comparing the current traversed node with the list head we marked, which can avoid accessing the list->next and is more cache-friendly.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit addresses an issue where calling `wd_cancel_period` within the periodic watchdog callback would fail to cancel the watchdog timer.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
In the original implementation, if wdog is not ACTIVE, -EINVAL will be returned. The rp2040 i2c driver relies on this semantics to correctly release the semaphore.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
Most tools used for compliance and SBOM generation use SPDX identifiers
This change brings us a step closer to an easy SBOM generation.
Signed-off-by: Alin Jerpelea <alin.jerpelea@sony.com>
After these wdog refactor:
We conducted a latency measurement using the rt-tests/cyclictest (commit cadd661) on an x86_64 NUC12 equipped with an i7-1255U processor and 16GB of LPDDR5 memory. The specific command used for this microbenchmark was cyclictest -q -l 100000 -h 30000, which is designed to assess the responsiveness of the cyclic timer.
The findings from our benchmark are summarized below, highlighting the minimum, median, and maximum latency values for each operating system tested:
Operating System Minimum Latency (us) Median Latency (us) Maximum Latency (us)
Linux 48 53 410
PreemptRT 6 57 148
Xenomai 53 53 64
NuttX 64 626 1212
NuttX (refactor) 1 1 3
In this table, "Min" indicates the shortest latency observed, "Median" represents the middle value of the latency distribution, and "Max" denotes the longest latency encountered.
The systems tested were as follows:
Linux: ACRN version 6.1.80 (commit f528146)
PreemptRT: Linux kernel 5.4.251 with the 5.4.254-rt85 patch applied
Xenomai: Linux kernel 5.4.251 patched with ipipe-core-5.4.239-x86-13
These results clearly demonstrate the varying performance of different operating systems in terms of timer latency, the refactored NuttX showing particularly low latency values.
Signed-off-by: ligd <liguiding1@xiaomi.com>
Now we have CONFIG_USEC_PER_TICK, and for our timer system, all the calculation used 'tick'.
And all the timespec should change to 'tick' before use wd_start(), so USEC2TICK() can NOT be avoided.
Then there must be an 'less then one tick' loss.
One resolution:
ticks++ anyway when wd_start(). But this will caused time expired more a tick.
Another resolution:
Change the testcase, and allow the following logic:
t1 = current_time();
sleep(3);
t2 = current_time();
allow: t2 - t1 >= 3;
(original test must be: t2- t1 > 3)
The original test think the time must be elapse-ing, and the (t2 - t1) must bigger then 3,
but in our system, we use 'tick' as the minimal wdog unit, then there must a precision loss.
Now we choose first resolution.
Signed-off-by: ligd <liguiding1@xiaomi.com>
For the nested interrupt, one thing should decleared:
We are in ISR context, but no meaning we are disabled the interrupts.
Signed-off-by: ligd <liguiding1@xiaomi.com>
This patch moved the g_wdtimernested to wd_start.c
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
Signed-off-by: ligd <liguiding1@xiaomi.com>
If g_wdactivelist has been changed in the wdog callback, the list traversal with next pointer will cause problem.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
Signed-off-by: ligd <liguiding1@xiaomi.com>
This commit refactors the wdog module to use absolute time representation internally. The main improvements include:
1. Fixed recursive watchdog handling caused by calling wd_start within watchdog timeout callback function.
2. Simplified timer processing to improve performance and enhance code readability.
3. Improved accuracy of timers.
4. Reduced critical section and interrupt disable time, improving real-time performance.
Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
Signed-off-by: ligd <liguiding1@xiaomi.com>