clock: Add clock_delay2abstick.

This commit added a macro function clock_delay2abstick to calculate the
absolute tick after the delay.

Signed-off-by: ouyangxiangzhen <ouyangxiangzhen@xiaomi.com>
This commit is contained in:
ouyangxiangzhen 2025-05-09 20:07:58 +08:00 committed by Xiang Xiao
parent 2e8583f759
commit 64a7049dec
6 changed files with 28 additions and 49 deletions

View file

@ -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
*

View file

@ -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 (; ; )

View file

@ -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);
}

View file

@ -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 */

View file

@ -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);
}
/****************************************************************************

View file

@ -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.