From f4d71b6074ba5cd0cf042c72066ae4a87d649347 Mon Sep 17 00:00:00 2001 From: Justin Hammond Date: Sat, 15 Aug 2026 17:31:49 +0800 Subject: [PATCH] testing/libc/arch_libc: Time against a clock that runs. Every measurement repeats until a stated interval has passed, so a clock that reads the same value twice does not slow the benchmark down, it stops it returning at all. CLOCK_MONOTONIC does not advance on every target. On qemu-intel64 it reports success and stays at zero, while CLOCK_REALTIME advances normally, and the benchmark spins in its first measurement with no output after the heading. Sample each candidate twice around a busy wait and take the first one whose reading changes. Where none does, say so and skip the timing rather than hang. Assisted-by: Claude:claude-opus-5 Signed-off-by: Justin Hammond --- testing/libc/arch_libc/arch_libc_bench.c | 56 +++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/testing/libc/arch_libc/arch_libc_bench.c b/testing/libc/arch_libc/arch_libc_bench.c index af5bb4dd9..c24118e1a 100644 --- a/testing/libc/arch_libc/arch_libc_bench.c +++ b/testing/libc/arch_libc/arch_libc_bench.c @@ -116,6 +116,7 @@ struct bench_op_s static FAR char *g_src; static FAR char *g_dst; static volatile unsigned long g_sink; +static clockid_t g_clock = CLOCK_MONOTONIC; static const struct bench_op_s g_ops[] = { @@ -182,10 +183,57 @@ static double bench_now(void) { struct timespec t; - clock_gettime(CLOCK_MONOTONIC, &t); + clock_gettime(g_clock, &t); return t.tv_sec + t.tv_nsec / 1e9; } +/**************************************************************************** + * Name: bench_pick_clock + * + * Description: + * Settle on a clock that runs. Every measurement below repeats until a + * stated interval has passed, so a clock that reads the same value twice + * would spin forever rather than report anything. CLOCK_MONOTONIC is + * preferred and does not advance on every target. + * + ****************************************************************************/ + +static bool bench_pick_clock(void) +{ + static const clockid_t tries[] = + { + CLOCK_MONOTONIC, CLOCK_REALTIME + }; + + struct timespec a; + struct timespec b; + volatile int i; + size_t k; + + for (k = 0; k < sizeof(tries) / sizeof(tries[0]); k++) + { + if (clock_gettime(tries[k], &a) < 0) + { + continue; + } + + for (i = 0; i < 1000000; i++); + + if (clock_gettime(tries[k], &b) < 0) + { + continue; + } + + if (b.tv_sec != a.tv_sec || b.tv_nsec != a.tv_nsec) + { + g_clock = tries[k]; + return true; + } + } + + return false; +} + /**************************************************************************** * Name: bench_seen_src * @@ -385,6 +433,12 @@ int arch_libc_bench(void) size_t si; size_t ai; + if (!bench_pick_clock()) + { + printf("arch_libc bench: no clock advances, cannot time anything\n"); + return 1; + } + g_src = malloc(BENCH_BUF); g_dst = malloc(BENCH_BUF); if (g_src == NULL || g_dst == NULL)