diff --git a/test/rt/nosv/CMakeLists.txt b/test/rt/nosv/CMakeLists.txt index 5e785be..00d3b80 100644 --- a/test/rt/nosv/CMakeLists.txt +++ b/test/rt/nosv/CMakeLists.txt @@ -44,6 +44,7 @@ nosv_test(parallel-tasks.c SORT) nosv_test(inline.c SORT) nosv_test(mutex.c SORT LEVEL 3) nosv_test(barrier.c SORT LEVEL 3) +nosv_test(overflow-kernel-ring.c SORT LEVEL 3) # Test multiple instrumentation levels nosv_test(several-tasks.c SORT NAME several-tasks-level-0 LEVEL 0) diff --git a/test/rt/nosv/overflow-kernel-ring.c b/test/rt/nosv/overflow-kernel-ring.c new file mode 100644 index 0000000..03a070f --- /dev/null +++ b/test/rt/nosv/overflow-kernel-ring.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include +#include +#include +#include + +#include "common.h" +#include "compat.h" + +int done = 0; + +/* https://gitlab.bsc.es/nos-v/nos-v/-/blob/master/src/include/instr.h?ref_type=heads#L542 */ +#define NOSV_INSTR_KBUFLEN (4UL * 1024UL * 1024UL) // 4 MB + +static void +task_run(nosv_task_t task) +{ + UNUSED(task); + + /* Cause enough context switches for the kernel ring to be full, + * which wouldn't fail if nosv_waitfor() flushes the kernel + * events. */ + + unsigned long fill = 3 * NOSV_INSTR_KBUFLEN / 4; + unsigned long n = fill / 16; + + struct timespec one_ns = { .tv_sec = 0, .tv_nsec = 1 }; + + for (unsigned long run = 0; run < 3; run++) { + info("starting run %lu", run); + for (unsigned long i = 0; i < n; i++) + nanosleep(&one_ns, NULL); + + info("starting waitfor"); + + if (nosv_waitfor(1, NULL) != 0) + die("nosv_waitfor failed"); + + info("end run %lu", run); + } + + done = 1; +} + +int main(void) +{ + if (nosv_init()) + die("nosv_init failed"); + + nosv_task_type_t task_type; + if (nosv_type_init(&task_type, task_run, NULL, NULL, "task", NULL, NULL, NOSV_TYPE_INIT_NONE)) + die("nosv_type_init failed"); + + nosv_task_t task; + if (nosv_create(&task, task_type, 0, NOSV_CREATE_NONE)) + die("nosv_create failed"); + + if (nosv_submit(task, NOSV_SUBMIT_IMMEDIATE)) + die("nosv_submit failed"); + + /* Wait for the task to finish */ + while (!done) + sleep_us(10000); + + if (nosv_destroy(task, NOSV_DESTROY_NONE)) + die("nosv_destroy failed"); + + if (nosv_type_destroy(task_type, NOSV_TYPE_DESTROY_NONE)) + die("nosv_type_destroy failed"); + + if (nosv_shutdown()) + die("nosv_shutdown failed"); + + return 0; +}