This is an automated email from the ASF dual-hosted git repository. linguini pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git
commit e4b84b29d47b98a666df524d6f2d38904c972de5 Author: ouyangxiangzhen <[email protected]> AuthorDate: Wed Feb 25 10:01:21 2026 +0800 ostest/hrtimer: Update the comments. This commit updated the comments. Signed-off-by: ouyangxiangzhen <[email protected]> --- testing/ostest/hrtimer.c | 388 +++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 322 insertions(+), 66 deletions(-) diff --git a/testing/ostest/hrtimer.c b/testing/ostest/hrtimer.c index 63040697c..3220ef2db 100644 --- a/testing/ostest/hrtimer.c +++ b/testing/ostest/hrtimer.c @@ -39,14 +39,13 @@ * Pre-processor Definitions ****************************************************************************/ -/* Timer constants */ +/* HRTimer test constants */ -#define HRTIMER_TEST_RAND_ITER (1024 * 2) -#define HRTIMER_TEST_CSECTION 1024 -#define HRTIMER_TEST_THREAD_NR (CONFIG_SMP_NCPUS * 8) +#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 */ -/* Set the tolerent latency to 10ms to allow hrtimer_test to pass - * in QEMU. +/* Tolerable latency for timer expiration * * QEMU is a virtual platform, vCPUs can be preempted by any * high priority thread. This can cause the timer to be triggered @@ -62,7 +61,9 @@ #define HRTIMER_TEST_TOLERENT_LATENCY (10 * NSEC_PER_MSEC) -#define hrtimer_test_ndelay(delay_ns) usleep(delay_ns / 1000 + 1) +/* Helper macro for nanosecond delay */ + +#define hrtimer_test_ndelay(delay_ns) usleep((delay_ns) / 1000 + 1) /**************************************************************************** * Private Types @@ -73,23 +74,40 @@ typedef struct hrtimer_test_s { struct hrtimer_s timer; /* HRTimer instance */ - spinlock_t lock; /* Spinlock */ + 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 uint8_t state; /* Test state */ + volatile uint8_t state; /* Test state (used for synchronization tests) */ } hrtimer_test_t; /**************************************************************************** * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: hrtimer_test_callback_oneshot + * + * Description: + * One-shot timer callback function. This callback is invoked when a + * one-shot HRTimer expires. It records the exact timestamp and increments + * the expiration counter. + * + * Input Parameters: + * timer - Pointer to the HRTimer instance + * expired_ns - Time when the timer expired (unused) + * + * Returned Value: + * 0 (oneshot hrtimer) + * + ****************************************************************************/ + static uint64_t hrtimer_test_callback_oneshot(FAR const hrtimer_t *timer, uint64_t expired_ns) { FAR hrtimer_test_t *param = (FAR hrtimer_test_t *)timer; - /* Save the timestamp when the callback was triggered */ + /* Record the exact timestamp when the callback was triggered */ param->timestamp = clock_systime_nsec(); @@ -100,6 +118,24 @@ static uint64_t hrtimer_test_callback_oneshot(FAR const hrtimer_t *timer, return 0; } +/**************************************************************************** + * Name: hrtimer_test_checkdelay + * + * Description: + * Check timer delay against tolerance threshold. This function verifies + * that the actual timer expiration time is within the acceptable + * tolerance. + * It warns if the delay exceeds the threshold. + * + * Input Parameters: + * timestamp - Actual expiration timestamp (nanoseconds) + * expected - Expected expiration timestamp (nanoseconds) + * + * Returned Value: + * None. + * + ****************************************************************************/ + static void hrtimer_test_checkdelay(uint64_t timestamp, uint64_t expected) { int64_t diff = timestamp - expected; @@ -113,76 +149,131 @@ static void hrtimer_test_checkdelay(uint64_t timestamp, uint64_t expected) if (diff > HRTIMER_TEST_TOLERENT_LATENCY) { printf("hrtimer_test: [WARNING] hrtimer latency %" PRId64 - " is too late!!! (> %u)\n", diff, + " ns is too late (> %u ns)\n", diff, (unsigned)HRTIMER_TEST_TOLERENT_LATENCY); } } +/**************************************************************************** + * Name: hrtimer_test_oneshot + * + * Description: + * Test one-shot HRTimer functionality. This function tests a one-shot + * HRTimer by starting it with a specified delay and verifying that it + * expires at the expected time. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * delay - Delay in nanoseconds for the one-shot timer + * + * Returned Value: + * None. + * + ****************************************************************************/ + static void hrtimer_test_oneshot(FAR hrtimer_test_t *param, uint64_t delay) { uint64_t count; uint64_t now; FAR hrtimer_t *timer = ¶m->timer; - printf("hrtimer_test_oneshot %" PRIu64 " ns\n", delay); + printf("hrtimer_test_oneshot: delay = %" PRIu64 " ns\n", delay); - /* Save the current callback count. */ + /* Save the current callback count and system time */ count = param->count; - - /* Save the current system time. */ - now = clock_systime_nsec(); + /* Start the one-shot timer */ + ASSERT(hrtimer_start(timer, hrtimer_test_callback_oneshot, delay + now, HRTIMER_MODE_ABS) == OK); - /* Wait until the callback is triggered exactly once. */ + /* Wait until the callback is triggered exactly once */ while (count + 1 != param->count) { hrtimer_test_ndelay(delay); } - /* Check if the delay is within the acceptable tolerance. */ + /* Verify the delay is within acceptable tolerance */ hrtimer_test_checkdelay(param->timestamp, now + delay); - /* Cancel the timer. */ + /* Cancel the timer to clean up */ hrtimer_cancel_sync(timer); } +/**************************************************************************** + * Name: hrtimer_test_maximum + * + * Description: + * Test HRTimer with maximum delay value. This function tests the behavior + * of HRTimer when started with the maximum possible delay (UINT64_MAX + * nanoseconds). The timer should not expire within a reasonable test + * period. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * + * Returned Value: + * None. + * + ****************************************************************************/ + static void hrtimer_test_maximum(FAR hrtimer_test_t *param) { uint64_t count; uint64_t rest; FAR hrtimer_t *timer = ¶m->timer; + printf("hrtimer_test_maximum: testing with UINT64_MAX delay\n"); + count = param->count; - /* Start the hrtimer with maximum */ + /* Start the hrtimer with maximum delay */ ASSERT(hrtimer_start(timer, hrtimer_test_callback_oneshot, UINT64_MAX, HRTIMER_MODE_REL) == OK); - /* Sleep for at least 1s */ + /* Sleep for at least 100ms to verify timer doesn't expire */ hrtimer_test_ndelay(USEC_PER_SEC / 100); - /* Ensure hrtimer is not alarmed */ + /* Ensure hrtimer has not expired (count should remain unchanged) */ ASSERT(count == param->count); + /* Get the remaining time until expiration */ + rest = hrtimer_gettime(timer); + /* Verify the remaining time is still large (less than UINT64_MAX) */ + ASSERT(rest < UINT64_MAX); + /* Cancel the timer */ + ASSERT(hrtimer_cancel_sync(timer) == OK); - printf("hrtimer_start with maximum delay, rest %" PRIu64 "\n", rest); + printf("hrtimer_test_maximum: remaining time = %" PRIu64 " ns\n", rest); } +/**************************************************************************** + * Name: hrtimer_test_rand + * + * Description: + * Test HRTimer with random delays. This function tests HRTimer behavior + * with random delay values within a specified range. It performs multiple + * iterations, testing both timer expiration and cancellation scenarios. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * rand_ns - Maximum random delay value in nanoseconds + * + ****************************************************************************/ + static void hrtimer_test_rand(FAR hrtimer_test_t *param, uint64_t rand_ns) { uint64_t count; @@ -192,19 +283,19 @@ static void hrtimer_test_rand(FAR hrtimer_test_t *param, uint64_t rand_ns) irqstate_t flags; FAR hrtimer_t *timer = ¶m->timer; - printf("hrtimer_test_rand %" PRIu64 " ns\n", rand_ns); + printf("hrtimer_test_rand: max delay = %" PRIu64 " ns\n", rand_ns); - /* Perform multiple iterations with random delays. */ + /* Perform multiple iterations with random delays */ for (idx = 0; idx < HRTIMER_TEST_RAND_ITER; idx++) { - /* Generate a random delay within the specified range. */ + /* Generate a random delay within the specified range */ delay = rand() % rand_ns; ASSERT(timer->func == NULL); - /* Enter critical section if the callback count is odd. */ + /* Enter critical section if the callback count is odd */ count = param->count; @@ -221,18 +312,18 @@ static void hrtimer_test_rand(FAR hrtimer_test_t *param, uint64_t rand_ns) up_irq_restore(flags); } - /* Decide to wait for the callback or cancel the hrtimer. */ + /* Decide to wait for the callback or cancel the hrtimer */ if (delay % 2u) { - /* Wait for the callback. */ + /* Wait for the callback */ while (count + 1u != param->count) { hrtimer_test_ndelay(delay); } - /* Check the delay if the callback count is odd. */ + /* Check the delay if the callback count is odd */ if (count % 2u) { @@ -247,6 +338,23 @@ static void hrtimer_test_rand(FAR hrtimer_test_t *param, uint64_t rand_ns) hrtimer_cancel_sync(timer); } +/**************************************************************************** + * Name: hrtimer_test_cancel_callback + * + * Description: + * Callback function for cancel test. This callback is used in the cancel + * test to simulate a long-running callback that can be interrupted by + * timer cancellation. + * + * Input Parameters: + * timer - Pointer to the HRTimer instance + * expired_ns - Time when the timer expired + * + * Returned Value: + * 0 (oneshot hrtimer) + * + ****************************************************************************/ + static uint64_t hrtimer_test_cancel_callback(FAR const hrtimer_t *timer, uint64_t expired_ns) { @@ -255,11 +363,11 @@ static uint64_t hrtimer_test_cancel_callback(FAR const hrtimer_t *timer, uint64_t delay = 0; irqstate_t flags = spin_lock_irqsave(lock); - /* Random sleep */ + /* Calculate random sleep delay based on period */ delay = expired_ns % param->period; - /* Check if the version is same. */ + /* Check if the expiration time matches (prevents duplicate processing) */ if (expired_ns == timer->expired) { @@ -272,11 +380,28 @@ static uint64_t hrtimer_test_cancel_callback(FAR const hrtimer_t *timer, spin_unlock_irqrestore(lock, flags); + /* Simulate work with random delay */ + up_ndelay(delay); return 0; } +/**************************************************************************** + * Name: hrtimer_test_rand_cancel + * + * Description: + * Test HRTimer cancellation with random delays. This function tests + * HRTimer cancellation behavior with random delay values. It verifies + * that timers can be properly cancelled and that callbacks behave + * correctly when cancellation occurs. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * rand_ns - Maximum random delay value in nanoseconds + * + ****************************************************************************/ + static void hrtimer_test_rand_cancel(FAR hrtimer_test_t *param, uint64_t rand_ns) { @@ -287,15 +412,15 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t *param, irqstate_t flags; spinlock_t *lock = ¶m->lock; - printf("hrtimer_test_rand cancel %" PRIu64 " ns\n", rand_ns); + printf("hrtimer_test_rand_cancel: max delay = %" PRIu64 " ns\n", rand_ns); param->period = rand_ns; - /* Perform multiple iterations with random delays. */ + /* Perform multiple iterations with random delays */ for (idx = 0; idx < HRTIMER_TEST_RAND_ITER; idx++) { - /* Generate a random delay within the specified range. */ + /* Generate a random delay within the specified range */ delay = rand() % rand_ns; @@ -308,11 +433,11 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t *param, spin_unlock_irqrestore(lock, flags); - /* Decide to wait for the callback or cancel the hrtimer. */ + /* Decide to wait for the callback or cancel the hrtimer */ if (delay % 2u) { - /* Wait for the callback finished. */ + /* Wait for the callback to finish */ while (param->count != count + 1u) { @@ -328,6 +453,23 @@ static void hrtimer_test_rand_cancel(FAR hrtimer_test_t *param, hrtimer_cancel_sync(¶m->timer); } +/**************************************************************************** + * Name: hrtimer_test_callback_period + * + * Description: + * Periodic timer callback function. This callback is invoked when a + * periodic HRTimer expires. It records the timestamp, increments the + * count, and returns the interval for the next expiration. + * + * Input Parameters: + * timer - Pointer to the HRTimer instance + * expired_ns - Time when the timer expired (unused) + * + * Returned Value: + * The interval in nanoseconds for the next expiration + * + ****************************************************************************/ + static uint64_t hrtimer_test_callback_period(FAR const hrtimer_t *timer, uint64_t expired_ns) { @@ -340,6 +482,24 @@ static uint64_t hrtimer_test_callback_period(FAR const hrtimer_t *timer, return interval; } +/**************************************************************************** + * Name: hrtimer_test_period + * + * Description: + * Test periodic HRTimer functionality. This function tests a periodic + * HRTimer by starting it with a specified interval and verifying that + * it triggers multiple times as expected. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * delay_ns - Period interval in nanoseconds + * iters - Expected number of timer expirations + * + * Returned Value: + * None. + * + ****************************************************************************/ + static void hrtimer_test_period(FAR hrtimer_test_t *param, uint64_t delay_ns, unsigned int iters) @@ -348,7 +508,8 @@ static void hrtimer_test_period(FAR hrtimer_test_t *param, uint64_t count = param->count; FAR hrtimer_t *timer = ¶m->timer; - printf("hrtimer_test_period %" PRIu64 " ns\n", delay_ns); + printf("hrtimer_test_period: period = %" PRIu64 " ns, iters = %u\n", + delay_ns, iters); param->period = delay_ns; ASSERT(param->period > 0); @@ -358,29 +519,52 @@ static void hrtimer_test_period(FAR hrtimer_test_t *param, ASSERT(hrtimer_start(timer, hrtimer_test_callback_period, delay_ns, HRTIMER_MODE_REL) == OK); + /* Wait for expected number of periods */ + hrtimer_test_ndelay(iters * delay_ns); hrtimer_cancel_sync(timer); ASSERT(timer->func == NULL); - printf("periodical hrtimer triggered %" PRIu64 " times, " + /* Report results */ + + printf("hrtimer_test_period: triggered %" PRIu64 " times, " "elapsed nsec %" PRIu64 "\n", param->count - count, param->timestamp - timestamp); + /* Warn if fewer expirations than expected */ + if (param->count - count < iters) { - printf("hrtimer_test: [WARNING] periodical hrtimer" + printf("hrtimer_test_period: [WARNING] periodical hrtimer " "triggered times < %u\n", iters); } } #ifdef CONFIG_SMP +/**************************************************************************** + * Name: hrtimer_test_callback_crita + * + * Description: + * Critical section test callback A. This callback is used to test + * critical section protection in SMP systems. It verifies that timer + * callbacks can safely access shared state. + * + * Input Parameters: + * timer - Pointer to the HRTimer instance + * expired_ns - Time when the timer expired (unused) + * + * Returned Value: + * 0 (oneshot hrtimer) + * + ****************************************************************************/ + static uint64_t hrtimer_test_callback_crita(FAR const hrtimer_t *timer, uint64_t expired_ns) { FAR hrtimer_test_t *param = (FAR hrtimer_test_t *)timer; - /* change status */ + /* Change status if in initial state */ if (param->state == 0) { @@ -388,7 +572,7 @@ static uint64_t hrtimer_test_callback_crita(FAR const hrtimer_t *timer, param->count++; } - /* check whether parameter be changed by another critical section */ + /* Verify state wasn't changed by another critical section */ ASSERT(param->state == 1); param->state = 0; @@ -396,12 +580,29 @@ static uint64_t hrtimer_test_callback_crita(FAR const hrtimer_t *timer, return 0; } +/**************************************************************************** + * Name: hrtimer_test_callback_critb + * + * Description: + * Critical section test callback B. This callback is used to test + * critical section protection in SMP systems. It verifies that timer + * callbacks can safely access shared state. + * + * Input Parameters: + * timer - Pointer to the HRTimer instance + * expired_ns - Time when the timer expired (unused) + * + * Returned Value: + * 0 (oneshot hrtimer) + * + ****************************************************************************/ + static uint64_t hrtimer_test_callback_critb(FAR const hrtimer_t *timer, uint64_t expired_ns) { FAR hrtimer_test_t *param = (FAR hrtimer_test_t *)timer; - /* change status */ + /* Change status if in expected state */ if (param->state == 1) { @@ -409,7 +610,7 @@ static uint64_t hrtimer_test_callback_critb(FAR const hrtimer_t *timer, param->count++; } - /* check whether parameter be changed by another critical section */ + /* Verify state wasn't changed by another critical section */ ASSERT(param->state == 0); param->state = 1; @@ -417,6 +618,23 @@ static uint64_t hrtimer_test_callback_critb(FAR const hrtimer_t *timer, return 0; } +/**************************************************************************** + * Name: hrtimer_test_callback_critdelay + * + * Description: + * Critical section delay test callback. This callback simulates a + * long-running timer callback with spinlock protection. It's used to + * test timer cancellation behavior with in-progress callbacks. + * + * Input Parameters: + * timer - Pointer to the HRTimer instance + * expired_ns - Time when the timer expired (unused) + * + * Returned Value: + * 300 microseconds (reschedules timer for periodic behavior) + * + ****************************************************************************/ + static uint64_t hrtimer_test_callback_critdelay(FAR const hrtimer_t *timer, uint64_t expired_ns) { @@ -424,15 +642,35 @@ static uint64_t hrtimer_test_callback_critdelay(FAR const hrtimer_t *timer, FAR spinlock_t *lock = ¶m->lock; irqstate_t flags; + /* Protect count increment with spinlock */ + flags = spin_lock_irqsave(lock); param->count++; spin_unlock_irqrestore(lock, flags); + /* Simulate work with 100 microsecond delay */ + up_ndelay(100 * NSEC_PER_USEC); + /* Return reschedule interval for periodic behavior */ + return 300 * NSEC_PER_USEC; } +/**************************************************************************** + * Name: hrtimer_test_cancel_sync + * + * Description: + * Test HRTimer cancel synchronization. This function tests that + * hrtimer_cancel_sync properly waits for callback completion before + * returning. It verifies that timer callbacks complete execution even + * when cancellation is requested. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * + ****************************************************************************/ + static void hrtimer_test_cancel_sync(FAR hrtimer_test_t *param) { unsigned int idx = 0; @@ -441,11 +679,6 @@ static void hrtimer_test_cancel_sync(FAR hrtimer_test_t *param) param->count = 0; - /* This test is to validate if the hrtimer can ensure the - * callback function be finished after the hrtimer_cancel_sync - * is called. - */ - for (idx = 0; idx < HRTIMER_TEST_CSECTION; ) { param->state = 0; @@ -459,13 +692,27 @@ static void hrtimer_test_cancel_sync(FAR hrtimer_test_t *param) if (++idx % (HRTIMER_TEST_CSECTION / 4) == 0) { - printf("hrtimer_test_cancel_sync passed %d times.\n", idx); + printf("hrtimer_test_cancel_sync: passed %u times\n", idx); } hrtimer_cancel_sync(¶m->timer); } } +/**************************************************************************** + * Name: hrtimer_test_cancel_periodic + * + * Description: + * Test periodic HRTimer cancellation. This function tests that periodic + * timers can be properly cancelled and that they don't restart after + * cancellation. It verifies that timer cancellation is effective and + * persistent. + * + * Input Parameters: + * param - Test context structure containing timer and state information + * + ****************************************************************************/ + static void hrtimer_test_cancel_periodic(FAR hrtimer_test_t *param) { uint64_t count; @@ -476,11 +723,6 @@ static void hrtimer_test_cancel_periodic(FAR hrtimer_test_t *param) param->count = 0; - /* This test to check if the hrtimer can ensure the perodical callback - * can not restart the timer again after the hrtimer_cancel_sync is - * called. - */ - for (idx = 0; idx < HRTIMER_TEST_CSECTION; idx++) { irqstate_t flags = spin_lock_irqsave(lock); @@ -503,7 +745,7 @@ static void hrtimer_test_cancel_periodic(FAR hrtimer_test_t *param) up_ndelay(10000); - /* The hrtimer should not be restarted again after the cancellation. */ + /* The hrtimer should not restart after cancellation */ ASSERT(!param->timer.func); @@ -516,7 +758,7 @@ static void hrtimer_test_cancel_periodic(FAR hrtimer_test_t *param) if (++idx % (HRTIMER_TEST_CSECTION / 4) == 0) { - printf("hrtimer_test_cancel_periodic passed %d times. count %" + printf("hrtimer_test_cancel_periodic: passed %u times, count = %" PRIu64 "\n", idx, param->count); } } @@ -529,11 +771,20 @@ static void hrtimer_test_cancel_periodic(FAR hrtimer_test_t *param) * Name: hrtimer_test_thread * * Description: - * Thread function to repeatedly test HRTimer start/cancel behavior. + * HRTimer test thread function. This function runs a comprehensive test + * suite for HRTimer functionality. It tests various scenarios including + * one-shot timers, periodic timers, random delays, maximum delays, and + * cancellation behavior. + * + * Input Parameters: + * arg - Thread argument (unused) + * + * Returned Value: + * NULL. * ****************************************************************************/ -static void * hrtimer_test_thread(void *arg) +static void *hrtimer_test_thread(void *arg) { hrtimer_test_t param = { @@ -542,6 +793,8 @@ static void * hrtimer_test_thread(void *arg) hrtimer_init(¶m.timer); + /* Test one-shot timers with various delays */ + /* Delay = 0 */ hrtimer_test_oneshot(¶m, 0u); @@ -561,24 +814,21 @@ static void * hrtimer_test_thread(void *arg) hrtimer_test_oneshot(¶m, 10000000u); #ifdef CONFIG_SMP - /* Test hrtimer_cancel_sync */ + /* Test SMP-specific cancellation behavior */ hrtimer_test_cancel_sync(¶m); - - /* Test hrtimer_cancel */ - hrtimer_test_cancel_periodic(¶m); #endif - /* Maximum hrtimer delay test. */ + /* Test maximum delay handling */ hrtimer_test_maximum(¶m); - /* Period hrtimer delay 100000ns */ + /* Test periodic timer with 1ms period */ hrtimer_test_period(¶m, 1000000u, 128u); - /* Random delay 12345ns and 67890ns */ + /* Test random delay and cancel scenarios */ hrtimer_test_rand(¶m, 12345u); hrtimer_test_rand_cancel(¶m, 67890u); @@ -617,11 +867,15 @@ void hrtimer_test(void) printf("hrtimer_test start...\n"); + /* Initialize thread attributes */ + ASSERT(pthread_attr_init(&attr) == 0); sparam.sched_priority = PTHREAD_DEFAULT_PRIORITY; ASSERT(pthread_attr_setschedparam(&attr, &sparam) == 0); + /* Create multiple test threads */ + for (thread_id = 0; thread_id < HRTIMER_TEST_THREAD_NR; thread_id++) { ASSERT(pthread_create(&pthreads[thread_id], &attr, @@ -635,6 +889,8 @@ void hrtimer_test(void) pthread_join(pthreads[thread_id], NULL); } + /* Clean up thread attributes */ + ASSERT(pthread_attr_destroy(&attr) == 0); printf("hrtimer_test end...\n");
