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 = ¶m->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 = ¶m->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 = ¶m->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 = ¶m->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(¶m->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 = ¶m->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 = ¶m->lock; + FAR spinlock_t *lock = ¶m->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(¶m->timer, hrtimer_test_callback_crita, 0, HRTIMER_MODE_REL); hrtimer_cancel_sync(¶m->timer); - param->state = 1; + param->state = 1u; hrtimer_start(¶m->timer, hrtimer_test_callback_critb, 0, HRTIMER_MODE_REL); hrtimer_cancel_sync(¶m->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 = ¶m->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(¶m); - /* Test periodic timer with 1ms period */ + /* Test periodic timer with 100ms period */ - hrtimer_test_period(¶m, 1000000u, 128u); + hrtimer_test_period(¶m, 100 * NSEC_PER_MSEC, 8u); /* Test random delay and cancel scenarios */
