This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 64a7049decb0671a76e7a6d1585eed8bece344df Author: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> AuthorDate: Fri May 9 20:07:58 2025 +0800 clock: Add clock_delay2abstick. This commit added a macro function clock_delay2abstick to calculate the absolute tick after the delay. Signed-off-by: ouyangxiangzhen <ouyangxiangz...@xiaomi.com> --- include/nuttx/clock.h | 22 ++++++++++++++++++++++ sched/semaphore/sem_tickwait.c | 2 +- sched/signal/sig_timedwait.c | 10 +--------- sched/timer/timer_settime.c | 15 ++------------- sched/wdog/wd_start.c | 18 +----------------- sched/wqueue/kwork_queue.c | 10 +--------- 6 files changed, 28 insertions(+), 49 deletions(-) diff --git a/include/nuttx/clock.h b/include/nuttx/clock.h index 13074e2587..8aa9f06ac0 100644 --- a/include/nuttx/clock.h +++ b/include/nuttx/clock.h @@ -384,6 +384,28 @@ EXTERN volatile clock_t g_system_ticks; #define clock_time2nsec(ts) \ ((uint64_t)(ts)->tv_sec * NSEC_PER_SEC + (uint64_t)(ts)->tv_nsec) +/* Calculate delay+1, forcing the delay into a range that we can handle. + * + * NOTE that one is added to the delay. This is correct and must not be + * changed: The contract for the use wdog_start is that the wdog will + * delay FOR AT LEAST as long as requested, but may delay longer due to + * variety of factors. The wdog logic has no knowledge of the the phase + * of the system timer when it is started: The next timer interrupt may + * occur immediately or may be delayed for almost a full cycle. In order + * to meet the contract requirement, the requested time is also always + * incremented by one so that the delay is always at least as long as + * requested. + * + * E.g. delay+1 can prevent the insufficient sleep time if we are + * currently near the boundary to the next tick. + * | current_tick | current_tick + 1 | current_tick + 2 | .... | + * | ^ Here we get the current tick + * In this case we delay 1 tick, timer will be triggered at + * current_tick + 1, which is not enough for at least 1 tick. + */ + +#define clock_delay2abstick(delay) (clock_systime_ticks() + (delay) + 1) + /**************************************************************************** * Name: clock_timespec_add * diff --git a/sched/semaphore/sem_tickwait.c b/sched/semaphore/sem_tickwait.c index afd4aef9d4..b5c08ca4fe 100644 --- a/sched/semaphore/sem_tickwait.c +++ b/sched/semaphore/sem_tickwait.c @@ -150,7 +150,7 @@ out: int nxsem_tickwait_uninterruptible(FAR sem_t *sem, uint32_t delay) { - clock_t end = clock_systime_ticks() + delay + 1; + clock_t end = clock_delay2abstick(delay); int ret; for (; ; ) diff --git a/sched/signal/sig_timedwait.c b/sched/signal/sig_timedwait.c index dec5ea3776..d396f5577c 100644 --- a/sched/signal/sig_timedwait.c +++ b/sched/signal/sig_timedwait.c @@ -304,15 +304,7 @@ int nxsig_clockwait(int clockid, int flags, if ((flags & TIMER_ABSTIME) == 0) { - /* delay+1 is to prevent the insufficient sleep time if we are - * currently near the boundary to the next tick. - * | current_tick | current_tick + 1 | current_tick + 2 | .... | - * | ^ Here we get the current tick - * In this case we delay 1 tick, timer will be triggered at - * current_tick + 1, which is not enough for at least 1 tick. - */ - - expect = clock_systime_ticks() + clock_time2ticks(rqtp) + 1; + expect = clock_delay2abstick(clock_time2ticks(rqtp)); wd_start_abstick(&rtcb->waitdog, expect, nxsig_timeout, (uintptr_t)rtcb); } diff --git a/sched/timer/timer_settime.c b/sched/timer/timer_settime.c index 0c714c41a0..656807fe82 100644 --- a/sched/timer/timer_settime.c +++ b/sched/timer/timer_settime.c @@ -316,9 +316,7 @@ int timer_settime(timer_t timerid, int flags, { /* Calculate a delay corresponding to the absolute time in 'value' */ - clock_abstime2ticks(timer->pt_clock, &value->it_value, - &timer->pt_expected); - timer->pt_expected += clock_systime_ticks(); + clock_abstime2ticks(timer->pt_clock, &value->it_value, &delay); } else { @@ -328,18 +326,9 @@ int timer_settime(timer_t timerid, int flags, */ delay = clock_time2ticks(&value->it_value); - timer->pt_expected = clock_systime_ticks() + delay; } - /* This is to prevent the insufficient sleep time if we are - * currently near the boundary to the next tick. - * | current_tick | current_tick + 1 | current_tick + 2 | .... | - * | ^ Here we get the current tick - * In this case we delay 1 tick, timer will be triggered at - * current_tick + 1, which is not enough for at least 1 tick. - */ - - timer->pt_expected += 1; + timer->pt_expected = clock_delay2abstick(delay); /* Then start the watchdog */ diff --git a/sched/wdog/wd_start.c b/sched/wdog/wd_start.c index 409fada383..eed0c34a83 100644 --- a/sched/wdog/wd_start.c +++ b/sched/wdog/wd_start.c @@ -416,23 +416,7 @@ int wd_start(FAR struct wdog_s *wdog, sclock_t delay, return -EINVAL; } - /* Calculate delay+1, forcing the delay into a range that we can handle. - * - * NOTE that one is added to the delay. This is correct and must not be - * changed: The contract for the use wdog_start is that the wdog will - * delay FOR AT LEAST as long as requested, but may delay longer due to - * variety of factors. The wdog logic has no knowledge of the the phase - * of the system timer when it is started: The next timer interrupt may - * occur immediately or may be delayed for almost a full cycle. In order - * to meet the contract requirement, the requested time is also always - * incremented by one so that the delay is always at least as long as - * requested. - * - * There is extensive documentation about this time issue elsewhere. - */ - - return wd_start_abstick(wdog, clock_systime_ticks() + delay + 1, - wdentry, arg); + return wd_start_abstick(wdog, clock_delay2abstick(delay), wdentry, arg); } /**************************************************************************** diff --git a/sched/wqueue/kwork_queue.c b/sched/wqueue/kwork_queue.c index 1e5a8dec2b..e91c664b06 100644 --- a/sched/wqueue/kwork_queue.c +++ b/sched/wqueue/kwork_queue.c @@ -88,15 +88,7 @@ int work_queue_period_wq(FAR struct kwork_wqueue_s *wqueue, return -EINVAL; } - /* delay+1 is to prevent the insufficient sleep time if we are - * currently near the boundary to the next tick. - * | current_tick | current_tick + 1 | current_tick + 2 | .... | - * | ^ Here we get the current tick - * In this case we delay 1 tick, timer will be triggered at - * current_tick + 1, which is not enough for at least 1 tick. - */ - - expected = clock_systime_ticks() + delay + 1; + expected = clock_delay2abstick(delay); /* Interrupts are disabled so that this logic can be called from with * task logic or from interrupt handling logic.