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>
In the 'wd_timer',the callback function executed by 'wd_expiration' could call wd_start,and g_wdtickbase might be updated.Subsequently, g_wdtickbase is incremented by the value of ticks, causing g_wdtickbase to be greater than the actual passage of time.
Signed-off-by: yangguangcai <yangguangcai@xiaomi.com>
1. Update all CMakeLists.txt to adapt to new layout
2. Fix cmake build break
3. Update all new file license
4. Fully compatible with current compilation environment(use configure.sh or cmake as you choose)
------------------
How to test
From within nuttx/. Configure:
cmake -B build -DBOARD_CONFIG=sim/nsh -GNinja
cmake -B build -DBOARD_CONFIG=sim:nsh -GNinja
cmake -B build -DBOARD_CONFIG=sabre-6quad/smp -GNinja
cmake -B build -DBOARD_CONFIG=lm3s6965-ek/qemu-flat -GNinja
(or full path in custom board) :
cmake -B build -DBOARD_CONFIG=$PWD/boards/sim/sim/sim/configs/nsh -GNinja
This uses ninja generator (install with sudo apt install ninja-build). To build:
$ cmake --build build
menuconfig:
$ cmake --build build -t menuconfig
--------------------------
2. cmake/build: reformat the cmake style by cmake-format
https://github.com/cheshirekow/cmake_format
$ pip install cmakelang
$ for i in `find -name CMakeLists.txt`;do cmake-format $i -o $i;done
$ for i in `find -name *\.cmake`;do cmake-format $i -o $i;done
Co-authored-by: Matias N <matias@protobits.dev>
Signed-off-by: chao an <anchao@xiaomi.com>