This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 7fd17c9d7cf9ca9bc1fd5a7655951908ce23b881
Author: Marco Casaroli <[email protected]>
AuthorDate: Sun Jul 26 17:24:57 2026 +0200

    arch/x86_64: do not wrap the HPET oneshot on a deadline that has passed.
    
    intel64_timer_start_absolute() computed "expected - current_us" unsigned.  A
    watchdog started with a delay of zero asks for a deadline that is already
    current, the subtraction wraps to nearly 2^64, and the comparator is set so
    far ahead that the timer never fires.  The CONFIG_INTEL64_HPET_MIN_DELAY
    clamp in intel64_oneshot_start() cannot help: the wrapped value is enormous,
    not small.
    
    Ask for the shortest delay the hardware can take instead of wrapping, and 
let
    that existing minimum-delay logic pick it.
    
    It presents as ostest hanging in wdog_test with no output and no fault.
    apps/testing/ostest/wdog.c:281 calls wdtest_once(&test_wdog, param, 0), and
    NSEC2TICK() takes the next few delays (1ns, 10ns, ...) to zero ticks as 
well;
    wdtest_once() then spins forever in its "wait until the callback is 
triggered
    exactly once" loop.
    
    Impact: runtime, ARCH_INTEL64_HPET_ALARM only.
    
    Assisted-by: Claude:claude-opus-5
    Signed-off-by: Marco Casaroli <[email protected]>
---
 arch/x86_64/src/intel64/intel64_oneshot_lower.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86_64/src/intel64/intel64_oneshot_lower.c 
b/arch/x86_64/src/intel64/intel64_oneshot_lower.c
index 86e8ecdd75a..40fbeec7754 100644
--- a/arch/x86_64/src/intel64/intel64_oneshot_lower.c
+++ b/arch/x86_64/src/intel64/intel64_oneshot_lower.c
@@ -149,10 +149,14 @@ static void intel64_timer_start_absolute(struct 
oneshot_lowerhalf_s *lower,
     (struct intel64_oneshot_lowerhalf_s *)lower;
   irqstate_t flags    = spin_lock_irqsave(&g_oneshotlow_spin);
   int        ret      = intel64_oneshot_current(&priv->oneshot, &current_us);
-  uint64_t   delta_us = expected - current_us;
+  uint64_t   delta_us;
 
   DEBUGASSERT(ret == OK);
 
+  /* Use the shortest delay when the deadline has passed. */
+
+  delta_us = expected > current_us ? expected - current_us : 0;
+
   ts.tv_sec  = delta_us / USEC_PER_SEC;
   ts.tv_nsec = delta_us % USEC_PER_SEC * 1000ull;
   ret = intel64_oneshot_start(&priv->oneshot, intel64_oneshot_handler,

Reply via email to