Add noisy yield test in nOS-V

Ensure we can call nosv_yield in a loop without generating a lot of
events when using the level 3 instrumentation level. Noisy events are
now moved to level 4, so they shouldn't appear on the trace.
Additionally, make sure that the noisy events appear on level 4.
This commit is contained in:
Rodrigo Arias 2025-03-20 13:13:01 +01:00
parent a8a8a0e763
commit c847ec19ad
4 changed files with 160 additions and 1 deletions

View File

@ -1,4 +1,4 @@
# Copyright (c) 2021-2024 Barcelona Supercomputing Center (BSC)
# Copyright (c) 2021-2025 Barcelona Supercomputing Center (BSC)
# SPDX-License-Identifier: GPL-3.0-or-later
find_package(Nosv)
@ -45,6 +45,8 @@ nosv_test(inline.c SORT)
nosv_test(mutex.c SORT LEVEL 3)
nosv_test(barrier.c SORT LEVEL 3)
nosv_test(cond.c SORT LEVEL 3)
nosv_test(yield-noisy.c NAME "yield-noisy-l3" DRIVER "yield-noisy-l3.driver.sh")
nosv_test(yield-noisy.c NAME "yield-noisy-l4" DRIVER "yield-noisy-l4.driver.sh")
# Test multiple instrumentation levels
nosv_test(several-tasks.c SORT NAME several-tasks-level-0 LEVEL 0)

View File

@ -0,0 +1,30 @@
target=$OVNI_TEST_BIN
# We will set our own
unset NOSV_CONFIG
unset NOSV_CONFIG_OVERRIDE
export NOSV_APPID=1
cat > nosv.toml << EOF
instrumentation.version = "ovni"
ovni.level = 3
EOF
$target
. ./vars.sh
# We need to sort the trace as it has unsorted regions
ovnisort ovni
# Ensure that we don't find any noisy events by using the limit of 5% of
# nosv_yield calls. It is fine if some events don't appear.
ovnitop ovni | awk -v n=$nyields \
'/^V(AY|Ay|Sh|Sf|S\[|S\]|SN|Sn|Pr|Pp)/ { \
if ($2 < 0.05 * n) { print $0, "OK" }
else { print $0, "BAD"; bad++ }
} END { if (bad != 0) { exit 1 } }'
# Perform the emulation with breakdown enabled
ovniemu -b ovni

View File

@ -0,0 +1,38 @@
target=$OVNI_TEST_BIN
# We will set our own
unset NOSV_CONFIG
unset NOSV_CONFIG_OVERRIDE
export NOSV_APPID=1
cat > nosv.toml << EOF
instrumentation.version = "ovni"
ovni.level = 4
EOF
$target
. ./vars.sh
# We need to sort the trace as it has unsorted regions
ovnisort ovni
# Ensure we get a lot of VA[yY] and VS[nN] events. We need to make sure that all
# events are matched.
ovnitop ovni | awk -v n=$nyields \
'/^VA[Yy]/ { \
/* Match the number or nosv_yield calls exactly */
if ($2 == n) { print $0, "OK"; ok++ }
else { print $0, "BAD" }
} \
/^VS[Nn]/ { \
/* Use 2% for the non-blocking scheduler events */
if ($2 > 0.02 * n) { print $0, "OK"; ok++ }
else { print $0, "BAD" }
} END {
/* Be sure we matched the 4 rules */
if (ok != 4) { exit 1 }
}'
# Avoid emulation as may be huge

View File

@ -0,0 +1,89 @@
/* Copyright (c) 2025 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include <nosv.h>
#include <nosv/alpi.h>
#include <stdatomic.h>
#include <unistd.h>
#include <stdlib.h>
#include "common.h"
#include "compat.h"
#define NITERS 1000L
atomic_int ncompleted = 0;
static void
busywait(long iter)
{
for (volatile long i = 0; i < iter; i++)
;
}
static void
task_body(nosv_task_t task)
{
UNUSED(task);
/* Yield a lot of times to try to generate several events */
for (long i = 0; i < NITERS; i++) {
nosv_yield(0);
busywait(10000L);
}
}
static void
task_done(nosv_task_t task)
{
UNUSED(task);
atomic_fetch_add(&ncompleted, 1);
}
int
main(void)
{
nosv_init();
uint64_t ncpus;
if (alpi_cpu_count(&ncpus))
die("alpi_cpu_count failed");
nosv_task_t *tasks = calloc((size_t) ncpus, sizeof(nosv_task_t));
if (tasks == NULL)
die("calloc failed:");
int ntasks = (int) ncpus;
info("ntasks = %d", ntasks);
FILE *f = fopen("vars.sh", "w");
if (f == NULL)
die("fopen failed:");
fprintf(f, "nyields=%ld\n", (long) ntasks * NITERS);
fclose(f);
nosv_task_type_t task_type;
nosv_type_init(&task_type, task_body, NULL, task_done, "task", NULL, NULL, 0);
for (int i = 0; i < ntasks; i++)
nosv_create(&tasks[i], task_type, 0, 0);
for (int i = 0; i < ntasks; i++)
nosv_submit(tasks[i], 0);
while (atomic_load(&ncompleted) != ntasks)
sleep_us(1000);
for (int i = 0; i < ntasks; i++)
nosv_destroy(tasks[i], 0);
nosv_type_destroy(task_type, 0);
free(tasks);
nosv_shutdown();
return 0;
}