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

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

commit edf89ddedd1f01c34df7f0c0c5bc35be6e323515
Author: wangchengdong <[email protected]>
AuthorDate: Tue Dec 16 15:08:29 2025 +0800

    sched/hrtimer: add safe synchronous hrtimer cancel API
    
    Add a safe synchronous hrtimer cancel API, hrtimer_cancel_sync().
    If the timer callback is currently executing, this function waits
    until the callback has completed and the timer state transitions
    to HRTIMER_STATE_INACTIVE.
    
    Signed-off-by: Chengdong Wang <[email protected]>
---
 Documentation/reference/os/time_clock.rst | 31 +++++++++--
 include/nuttx/hrtimer.h                   | 23 +++++++++
 sched/hrtimer/hrtimer_cancel.c            | 86 +++++++++++++++++++++++++++----
 3 files changed, 128 insertions(+), 12 deletions(-)

diff --git a/Documentation/reference/os/time_clock.rst 
b/Documentation/reference/os/time_clock.rst
index e2f7f4a9ace..49d88b057a4 100644
--- a/Documentation/reference/os/time_clock.rst
+++ b/Documentation/reference/os/time_clock.rst
@@ -678,6 +678,7 @@ to communicate with tasks.
 
 - :c:func:`hrtimer_init`
 - :c:func:`hrtimer_cancel`
+- :c:func:`hrtimer_cancel_sync`
 - :c:func:`hrtimer_start`
 - High-resolution Timer Callback
 
@@ -698,9 +699,33 @@ to communicate with tasks.
 
 .. c:function:: int hrtimer_cancel(FAR hrtimer_t *hrtimer)
 
-  This function cancels a high-resolution timer if it is pending.
-  The timer callback will not be called if the timer was successfully
-  canceled.
+  If the timer is armed but has not yet expired, it will be removed from
+  the timer queue and the callback will not be invoked.
+
+  If the timer callback is currently executing, this function will mark
+  the timer as canceled and return immediately. The running callback is
+  allowed to complete, but it will not be invoked again.
+
+  This function is non-blocking and does not wait for a running callback
+  to finish.
+
+  :param hrtimer: Timer instance to cancel
+
+  :return: ``OK`` on success; negated errno on failure.
+
+  **POSIX Compatibility:** This is a NON-POSIX interface.
+
+.. c:function:: int hrtimer_cancel_sync(FAR hrtimer_t *hrtimer)
+
+  Cancel a high-resolution timer and wait synchronously until the timer
+  becomes inactive.
+
+  This function first calls hrtimer_cancel() to request cancellation of
+  the timer.  If the timer callback is currently executing, this function
+  will wait until the callback has completed and the timer state has
+  transitioned to HRTIMER_STATE_INACTIVE.
+
+  This function may sleep and must not be called from interrupt context.
 
   :param hrtimer: Timer instance to cancel
 
diff --git a/include/nuttx/hrtimer.h b/include/nuttx/hrtimer.h
index ddbff6707d6..3f68adf6f08 100644
--- a/include/nuttx/hrtimer.h
+++ b/include/nuttx/hrtimer.h
@@ -168,6 +168,29 @@ void hrtimer_init(FAR hrtimer_t *hrtimer,
 
 int hrtimer_cancel(FAR hrtimer_t *hrtimer);
 
+/****************************************************************************
+ * Name: hrtimer_cancel_sync
+ *
+ * Description:
+ *   Cancel a high-resolution timer and wait until it becomes inactive.
+ *
+ *   - Calls hrtimer_cancel() to request timer cancellation.
+ *   - If the timer callback is running, waits until it completes and
+ *     the timer state transitions to HRTIMER_STATE_INACTIVE.
+ *   - If sleeping is allowed (normal task context), yields CPU briefly
+ *     to avoid busy-waiting.
+ *   - Otherwise (interrupt or idle task context), spins until completion.
+ *
+ * Input Parameters:
+ *   hrtimer - Pointer to the high-resolution timer instance to cancel.
+ *
+ * Returned Value:
+ *   OK (0) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int hrtimer_cancel_sync(FAR hrtimer_t *hrtimer);
+
 /****************************************************************************
  * Name: hrtimer_start
  *
diff --git a/sched/hrtimer/hrtimer_cancel.c b/sched/hrtimer/hrtimer_cancel.c
index 44dc7b1784f..bf974d240aa 100644
--- a/sched/hrtimer/hrtimer_cancel.c
+++ b/sched/hrtimer/hrtimer_cancel.c
@@ -6,7 +6,7 @@
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
  * this work for additional information regarding copyright ownership.  The
- * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * ASF licenses this file under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance with the
  * License.  You may obtain a copy of the License at
  *
@@ -32,6 +32,14 @@
 
 #include "hrtimer/hrtimer.h"
 
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Delay used while waiting for a running hrtimer callback to complete */
+
+#define HRTIMER_CANCEL_SYNC_DELAY_MS  5
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -46,8 +54,8 @@
  *   hrtimer red-black tree and will not be executed.
  *
  *   If the timer callback is currently executing, the timer will be marked
- *   as canceled. The running callback is allowed to complete, but it will
- *   not be re-armed or executed again.
+ *   as canceled.  The running callback is allowed to complete, but the timer
+ *   will not be re-armed or executed again.
  *
  *   If the canceled timer was the earliest (head) timer in the tree, the
  *   expiration of the underlying hardware timer will be updated to:
@@ -65,17 +73,18 @@
  *   OK (0) on success; a negated errno value on failure.
  *
  * Assumptions/Notes:
- *   - This function acquires the global hrtimer spinlock to protect the
- *     red-black tree and timer state.
+ *   - This function acquires the global hrtimer spinlock to protect both
+ *     the red-black tree and the timer state.
  *   - The caller must ensure that the timer structure is not freed until
  *     it is guaranteed that any running callback has returned.
+ *
  ****************************************************************************/
 
 int hrtimer_cancel(FAR hrtimer_t *hrtimer)
 {
   FAR hrtimer_t *first;
-  irqstate_t flags;
-  int ret = OK;
+  irqstate_t     flags;
+  int            ret = OK;
 
   DEBUGASSERT(hrtimer != NULL);
 
@@ -83,7 +92,7 @@ int hrtimer_cancel(FAR hrtimer_t *hrtimer)
 
   flags = spin_lock_irqsave(&g_hrtimer_spinlock);
 
-  /* Capture the current earliest timer before removal */
+  /* Capture the current earliest timer before any modification */
 
   first = (FAR hrtimer_t *)RB_MIN(hrtimer_tree_s, &g_hrtimer_tree);
 
@@ -103,7 +112,7 @@ int hrtimer_cancel(FAR hrtimer_t *hrtimer)
           /* The callback is currently executing.
            *
            * Mark the timer as canceled so it will not be re-armed or
-           * executed again. The running callback is allowed to complete.
+           * executed again.  The running callback is allowed to complete.
            *
            * NOTE: The timer node is expected to have already been removed
            *       from the tree when the callback started executing.
@@ -138,3 +147,62 @@ int hrtimer_cancel(FAR hrtimer_t *hrtimer)
   spin_unlock_irqrestore(&g_hrtimer_spinlock, flags);
   return ret;
 }
+
+/****************************************************************************
+ * Name: hrtimer_cancel_sync
+ *
+ * Description:
+ *   Cancel a high-resolution timer and wait until it becomes inactive.
+ *
+ *   - Calls hrtimer_cancel() to request timer cancellation.
+ *   - If the timer callback is running, waits until it completes and
+ *     the timer state transitions to HRTIMER_STATE_INACTIVE.
+ *   - If sleeping is allowed (normal task context), yields CPU briefly
+ *     to avoid busy-waiting.
+ *   - Otherwise (interrupt or idle task context), spins until completion.
+ *
+ * Input Parameters:
+ *   hrtimer - Pointer to the high-resolution timer instance to cancel.
+ *
+ * Returned Value:
+ *   OK (0) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+int hrtimer_cancel_sync(FAR hrtimer_t *hrtimer)
+{
+  int  ret;
+  bool cansleep;
+
+  DEBUGASSERT(hrtimer != NULL);
+
+  /* Determine whether sleeping is permitted in the current context */
+
+  cansleep = !up_interrupt_context() &&
+             !is_idle_task(this_task());
+
+  /* Request cancellation of the timer */
+
+  ret = hrtimer_cancel(hrtimer);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Wait until the timer transitions to the inactive state.
+   *
+   * If sleeping is permitted, yield the CPU briefly to avoid
+   * busy-waiting.  Otherwise, spin until the callback completes
+   * and the state becomes inactive.
+   */
+
+  while (hrtimer->state != HRTIMER_STATE_INACTIVE)
+    {
+      if (cansleep)
+        {
+          nxsched_msleep(HRTIMER_CANCEL_SYNC_DELAY_MS);
+        }
+    }
+
+  return OK;
+}

Reply via email to