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 <justin@dynam.ac>
This commit is contained in:
Justin Hammond 2026-08-15 17:31:49 +08:00 committed by Alan C. Assis
parent f45a02c938
commit f4d71b6074

View file

@ -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)