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-apps.git

commit 524692e1ae9dbf271f819b474e5165ccc26bd0dc
Author: ouyangxiangzhen <[email protected]>
AuthorDate: Fri Apr 10 16:23:26 2026 +0800

    ostest/hrtimer: Fix starvation issues.
    
    On some platform, CPU resource is not sufficient to run hrtimer_test 
correctly. This commit fixed starvation issues.
    
    Assisted-By: mimo-v2.6-pro
    Signed-off-by: ouyangxiangzhen <[email protected]>
---
 testing/ostest/hrtimer.c | 110 ++++++++++++++++++++++-------------------------
 1 file changed, 52 insertions(+), 58 deletions(-)

diff --git a/testing/ostest/hrtimer.c b/testing/ostest/hrtimer.c
index 8490234e3..960444d7c 100644
--- a/testing/ostest/hrtimer.c
+++ b/testing/ostest/hrtimer.c
@@ -43,9 +43,9 @@
 
 /* HRTimer test constants */
 
-#define HRTIMER_TEST_RAND_ITER (1024 * 2)             /* Random delay 
iterations */
-#define HRTIMER_TEST_CSECTION  1024                   /* Critical section 
iterations */
-#define HRTIMER_TEST_THREAD_NR (CONFIG_SMP_NCPUS * 8) /* Test threads */
+#define HRTIMER_TEST_RAND_ITER (64 * 2)               /* Random delay 
iterations */
+#define HRTIMER_TEST_CSECTION  (64)                   /* Critical section 
iterations */
+#define HRTIMER_TEST_THREAD_NR (CONFIG_SMP_NCPUS * 4) /* Test threads */
 
 /* Tolerable latency for timer expiration
  *
@@ -78,8 +78,8 @@ typedef struct hrtimer_test_s
   struct hrtimer_s  timer;     /* HRTimer instance */
   spinlock_t        lock;      /* Spinlock for thread-safe operations */
   volatile uint64_t timestamp; /* Previous timestamp in nanoseconds */
-  volatile uint64_t count;     /* Number of timer expirations */
   uint64_t          period;    /* Expected period between expirations */
+  volatile uint32_t count;     /* Number of timer expirations */
   volatile uint8_t  state;     /* Test state (used for synchronization tests) 
*/
 } hrtimer_test_t;
 
@@ -115,6 +115,7 @@ static uint64_t hrtimer_test_callback_oneshot(FAR const 
hrtimer_t *timer,
 
   /* Increment the callback count */
 
+  SMP_WMB();
   param->count++;
 
   return 0;
@@ -175,7 +176,7 @@ static void hrtimer_test_checkdelay(uint64_t timestamp, 
uint64_t expected)
 
 static void hrtimer_test_oneshot(FAR hrtimer_test_t *param, uint64_t delay)
 {
-  uint64_t       count;
+  uint32_t       count;
   uint64_t       now;
   FAR hrtimer_t *timer = &param->timer;
 
@@ -198,6 +199,8 @@ static void hrtimer_test_oneshot(FAR hrtimer_test_t *param, 
uint64_t delay)
       hrtimer_test_ndelay(delay);
     }
 
+  SMP_RMB();
+
   /* Verify the delay is within acceptable tolerance */
 
   hrtimer_test_checkdelay(param->timestamp, now + delay);
@@ -226,7 +229,7 @@ static void hrtimer_test_oneshot(FAR hrtimer_test_t *param, 
uint64_t delay)
 
 static void hrtimer_test_maximum(FAR hrtimer_test_t *param)
 {
-  uint64_t       count;
+  uint32_t       count;
   uint64_t       rest;
   FAR hrtimer_t *timer = &param->timer;
 
@@ -278,18 +281,17 @@ static void hrtimer_test_maximum(FAR hrtimer_test_t 
*param)
 
 static void hrtimer_test_rand(FAR hrtimer_test_t *param, uint64_t rand_ns)
 {
-  uint64_t       count;
+  uint32_t       count;
   uint64_t       now;
   unsigned int   idx;
   uint64_t       delay;
-  irqstate_t     flags;
   FAR hrtimer_t *timer = &param->timer;
 
   printf("hrtimer_test_rand: max delay = %" PRIu64 " ns\n", rand_ns);
 
   /* Perform multiple iterations with random delays */
 
-  for (idx = 0; idx < HRTIMER_TEST_RAND_ITER; idx++)
+  for (idx = 0u; idx < HRTIMER_TEST_RAND_ITER; idx++)
     {
       /* Generate a random delay within the specified range */
 
@@ -297,22 +299,11 @@ static void hrtimer_test_rand(FAR hrtimer_test_t *param, 
uint64_t rand_ns)
 
       ASSERT(timer->func == NULL);
 
-      /* Enter critical section if the callback count is odd */
-
       count = param->count;
 
-      if (count % 2u)
-        {
-          flags = up_irq_save();
-        }
-
       now = clock_systime_nsec();
       ASSERT(hrtimer_start(timer, hrtimer_test_callback_oneshot,
-                           delay, HRTIMER_MODE_REL) == 0);
-      if (count % 2u)
-        {
-          up_irq_restore(flags);
-        }
+                           delay + now, HRTIMER_MODE_ABS) == 0);
 
       /* Decide to wait for the callback or cancel the hrtimer */
 
@@ -325,19 +316,16 @@ static void hrtimer_test_rand(FAR hrtimer_test_t *param, 
uint64_t rand_ns)
               hrtimer_test_ndelay(delay);
             }
 
+          SMP_RMB();
+
           /* Check the delay if the callback count is odd */
 
-          if (count % 2u)
-            {
-              hrtimer_test_checkdelay(param->timestamp, now + delay);
-            }
+          hrtimer_test_checkdelay(param->timestamp, now + delay);
         }
 
       hrtimer_cancel_sync(timer);
       ASSERT(timer->func == NULL);
     }
-
-  hrtimer_cancel_sync(timer);
 }
 
 /****************************************************************************
@@ -369,14 +357,16 @@ static uint64_t hrtimer_test_cancel_callback(FAR const 
hrtimer_t *timer,
 
   delay = expired_ns % param->period;
 
-  /* Check if the expiration time matches (prevents duplicate processing) */
+  /* Check if the version matches (prevents duplicate processing) */
 
-  if (expired_ns == timer->expired)
+  if (timer->expired == expired_ns && param->state)
     {
+      param->state     = 0u;
       param->timestamp = clock_systime_nsec();
 
       /* Increment the callback count */
 
+      SMP_WMB();
       param->count++;
     }
 
@@ -409,7 +399,7 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t 
*param,
 {
   uint64_t       now;
   unsigned int   idx;
-  uint64_t     count;
+  uint32_t     count;
   uint64_t     delay;
   irqstate_t   flags;
   spinlock_t   *lock = &param->lock;
@@ -420,7 +410,7 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t 
*param,
 
   /* Perform multiple iterations with random delays */
 
-  for (idx = 0; idx < HRTIMER_TEST_RAND_ITER; idx++)
+  for (idx = 0u; idx < HRTIMER_TEST_RAND_ITER; idx++)
     {
       /* Generate a random delay within the specified range */
 
@@ -428,10 +418,11 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t 
*param,
 
       flags = spin_lock_irqsave(lock);
 
-      now   = clock_systime_nsec();
-      count = param->count;
+      count        = param->count;
+      now          = clock_systime_nsec();
+      param->state = 1u;
       ASSERT(hrtimer_start(&param->timer, hrtimer_test_cancel_callback,
-                           delay, HRTIMER_MODE_REL) == 0);
+                           now + delay, HRTIMER_MODE_ABS) == 0);
 
       spin_unlock_irqrestore(lock, flags);
 
@@ -441,11 +432,13 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t 
*param,
         {
           /* Wait for the callback to finish */
 
-          while (param->count != count + 1u)
+          while (count + 1u != param->count)
             {
               hrtimer_test_ndelay(delay);
             }
 
+          SMP_RMB();
+
           hrtimer_test_checkdelay(param->timestamp, now + delay);
         }
 
@@ -478,10 +471,10 @@ static uint64_t hrtimer_test_callback_period(FAR const 
hrtimer_t *timer,
   FAR hrtimer_test_t *param = (FAR hrtimer_test_t *)timer;
   uint64_t         interval = param->period;
 
-  param->count++;
+  param->count--;
   param->timestamp = clock_systime_nsec();
 
-  return interval;
+  return (int64_t)param->count > 0 ? interval : 0u;
 }
 
 /****************************************************************************
@@ -507,9 +500,10 @@ static void hrtimer_test_period(FAR hrtimer_test_t *param,
                                 unsigned int iters)
 {
   uint64_t   timestamp;
-  uint64_t       count = param->count;
   FAR hrtimer_t *timer = &param->timer;
 
+  param->count = iters;
+
   printf("hrtimer_test_period: period = %" PRIu64 " ns, iters = %u\n",
          delay_ns, iters);
 
@@ -530,13 +524,13 @@ static void hrtimer_test_period(FAR hrtimer_test_t *param,
 
   /* Report results */
 
-  printf("hrtimer_test_period: triggered %" PRIu64 " times, "
-         "elapsed nsec %" PRIu64 "\n", param->count - count,
+  printf("hrtimer_test_period: triggered %" PRIu32 " times, "
+         "elapsed nsec %" PRIu64 "\n", iters - param->count,
          param->timestamp - timestamp);
 
   /* Warn if fewer expirations than expected */
 
-  if (param->count - count < iters)
+  if (iters - param->count < iters)
     {
       printf("hrtimer_test_period: [WARNING] periodical hrtimer "
              "triggered times < %u\n", iters);
@@ -568,16 +562,16 @@ static uint64_t hrtimer_test_callback_crita(FAR const 
hrtimer_t *timer,
 
   /* Change status if in initial state */
 
-  if (param->state == 0)
+  if (param->state == 0u)
     {
-      param->state = 1;
+      param->state = 1u;
       param->count++;
     }
 
   /* Verify state wasn't changed by another critical section */
 
-  ASSERT(param->state == 1);
-  param->state = 0;
+  ASSERT(param->state == 1u);
+  param->state = 0u;
 
   return 0;
 }
@@ -606,16 +600,16 @@ static uint64_t hrtimer_test_callback_critb(FAR const 
hrtimer_t *timer,
 
   /* Change status if in expected state */
 
-  if (param->state == 1)
+  if (param->state == 1u)
     {
-      param->state = 0;
+      param->state = 0u;
       param->count++;
     }
 
   /* Verify state wasn't changed by another critical section */
 
-  ASSERT(param->state == 0);
-  param->state = 1;
+  ASSERT(param->state == 0u);
+  param->state = 1u;
 
   return 0;
 }
@@ -641,7 +635,7 @@ static uint64_t hrtimer_test_callback_critdelay(FAR const 
hrtimer_t *timer,
                                                 uint64_t expired_ns)
 {
   FAR hrtimer_test_t *param = (FAR hrtimer_test_t *)timer;
-  FAR spinlock_t *lock      = &param->lock;
+  FAR spinlock_t     *lock  = &param->lock;
   irqstate_t flags;
 
   /* Protect count increment with spinlock */
@@ -679,17 +673,17 @@ static void hrtimer_test_cancel_sync(FAR hrtimer_test_t 
*param)
 
   ASSERT(!param->timer.func);
 
-  param->count = 0;
+  param->count = 0u;
 
   printf("hrtimer_test_cancel_sync: synchronous cancellation test\n");
 
   for (idx = 0; idx < HRTIMER_TEST_CSECTION; idx++)
     {
-      param->state = 0;
+      param->state = 0u;
       hrtimer_start(&param->timer, hrtimer_test_callback_crita,
                     0, HRTIMER_MODE_REL);
       hrtimer_cancel_sync(&param->timer);
-      param->state = 1;
+      param->state = 1u;
       hrtimer_start(&param->timer, hrtimer_test_callback_critb,
                     0, HRTIMER_MODE_REL);
       hrtimer_cancel_sync(&param->timer);
@@ -712,13 +706,13 @@ static void hrtimer_test_cancel_sync(FAR hrtimer_test_t 
*param)
 
 static void hrtimer_test_cancel_periodic(FAR hrtimer_test_t *param)
 {
-  uint64_t       count;
-  unsigned int     idx = 0;
+  uint32_t       count;
+  unsigned int     idx = 0u;
   FAR spinlock_t *lock = &param->lock;
 
   ASSERT(!param->timer.func);
 
-  param->count = 0;
+  param->count = 0u;
 
   printf("hrtimer_test_cancel_periodic:periodic timer cancellation test\n");
 
@@ -817,9 +811,9 @@ static void *hrtimer_test_thread(void *arg)
 
   hrtimer_test_maximum(&param);
 
-  /* Test periodic timer with 1ms period */
+  /* Test periodic timer with 100ms period */
 
-  hrtimer_test_period(&param, 1000000u, 128u);
+  hrtimer_test_period(&param, 100 * NSEC_PER_MSEC, 8u);
 
   /* Test random delay and cancel scenarios */
 

Reply via email to