diff --git a/test/emu/nosv/CMakeLists.txt b/test/emu/nosv/CMakeLists.txt index a86d482..832159b 100644 --- a/test/emu/nosv/CMakeLists.txt +++ b/test/emu/nosv/CMakeLists.txt @@ -22,6 +22,7 @@ test_emu(parallel-tasks.c) test_emu(nest-to-parallel.c) test_emu(mutex.c) test_emu(barrier.c) +test_emu(cond.c) test_emu(bad-nest-same-task.c SHOULD_FAIL REGEX "body_execute: refusing to run body(id=1,taskid=1) in Paused state, needs to resume intead") diff --git a/test/emu/nosv/cond.c b/test/emu/nosv/cond.c new file mode 100644 index 0000000..b041a88 --- /dev/null +++ b/test/emu/nosv/cond.c @@ -0,0 +1,32 @@ +/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#include "compat.h" +#include "instr.h" +#include "instr_nosv.h" + +/* Test the nosv_cond_wait(), nosv_cond_broadcast() and nosv_cond_signal() API + * events, introduced in the nOS-V model 2.4.0 */ + +int +main(void) +{ + instr_start(0, 1); + instr_nosv_init(); + + instr_nosv_cond_wait_enter(); + sleep_us(100); + instr_nosv_cond_wait_exit(); + + instr_nosv_cond_broadcast_enter(); + sleep_us(100); + instr_nosv_cond_broadcast_exit(); + + instr_nosv_cond_signal_enter(); + sleep_us(100); + instr_nosv_cond_signal_exit(); + + instr_end(); + + return 0; +} diff --git a/test/emu/nosv/instr_nosv.h b/test/emu/nosv/instr_nosv.h index 17c222b..9311214 100644 --- a/test/emu/nosv/instr_nosv.h +++ b/test/emu/nosv/instr_nosv.h @@ -59,6 +59,12 @@ INSTR_0ARG(instr_nosv_mutex_trylock_enter, "VAt") INSTR_0ARG(instr_nosv_mutex_trylock_exit, "VAT") INSTR_0ARG(instr_nosv_mutex_unlock_enter, "VAu") INSTR_0ARG(instr_nosv_mutex_unlock_exit, "VAU") +INSTR_0ARG(instr_nosv_cond_wait_enter, "VAo") +INSTR_0ARG(instr_nosv_cond_wait_exit, "VAO") +INSTR_0ARG(instr_nosv_cond_signal_enter, "VAg") +INSTR_0ARG(instr_nosv_cond_signal_exit, "VAG") +INSTR_0ARG(instr_nosv_cond_broadcast_enter, "VAk") +INSTR_0ARG(instr_nosv_cond_broadcast_exit, "VAK") INSTR_0ARG(instr_nosv_attached, "VHa") /* deprecated */ INSTR_0ARG(instr_nosv_detached, "VHA") /* deprecated */ diff --git a/test/rt/nosv/CMakeLists.txt b/test/rt/nosv/CMakeLists.txt index 575deca..47c95e2 100644 --- a/test/rt/nosv/CMakeLists.txt +++ b/test/rt/nosv/CMakeLists.txt @@ -12,9 +12,9 @@ if(NOT NOSV_FOUND) return() endif() -# Needed for breakdown and kernel fix -if("${NOSV_VERSION}" VERSION_LESS "2.3.1") - message(FATAL_ERROR "nOS-V version ${NOSV_VERSION} too old, required at least 2.3.1") +# Needed for nosv_cond +if("${NOSV_VERSION}" VERSION_LESS "3.1.0") + message(FATAL_ERROR "nOS-V version ${NOSV_VERSION} too old, required at least 3.1.0") endif() message(STATUS "Enabling nOS-V RT tests") @@ -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(cond.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/cond.c b/test/rt/nosv/cond.c new file mode 100644 index 0000000..6691134 --- /dev/null +++ b/test/rt/nosv/cond.c @@ -0,0 +1,123 @@ +/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#define _DEFAULT_SOURCE + +#include +#include +#include +#include + +#include "common.h" +#include "compat.h" + +#define NTASKS 200 +atomic_int nstarted = 0; +atomic_int ncompleted = 0; +atomic_int ready = 0; + +nosv_task_t tasks[NTASKS]; +nosv_cond_t cond; +nosv_mutex_t mutex; + +static void +task_body(nosv_task_t task) +{ + UNUSED(task); + atomic_fetch_add(&nstarted, 1); + if (nosv_mutex_lock(mutex) != 0) + die("nosv_mutex_lock failed"); + + while (!ready) { + if (nosv_cond_wait(cond, mutex) != 0) + die("nosv_cond_wait failed"); + } + + if (nosv_mutex_unlock(mutex) != 0) + die("nosv_mutex_unlock failed"); +} + +static void +task_done(nosv_task_t task) +{ + UNUSED(task); + atomic_fetch_add(&ncompleted, 1); +} + +static void +task_broadcast_run(nosv_task_t task) +{ + UNUSED(task); + if (nosv_mutex_lock(mutex) != 0) + die("nosv_mutex_lock failed"); + + atomic_store(&ready, 1); + if (nosv_cond_broadcast(cond) != 0) + die("nosv_cond_broadcast failed"); + + if (nosv_mutex_unlock(mutex) != 0) + die("nosv_mutex_unlock failed"); + + if (nosv_mutex_lock(mutex) != 0) + die("nosv_mutex_lock failed"); + + if (nosv_cond_signal(cond) != 0) + die("nosv_cond_signal failed"); + + if (nosv_mutex_unlock(mutex) != 0) + die("nosv_mutex_unlock failed"); +} + +int +main(void) +{ + nosv_init(); + + nosv_task_type_t task_type; + nosv_type_init(&task_type, task_body, NULL, task_done, "task", NULL, NULL, NOSV_TYPE_INIT_NONE); + + nosv_task_t task_broadcast; + nosv_task_type_t task_type_broadcast; + nosv_type_init(&task_type_broadcast, task_broadcast_run, NULL, NULL, "task_broadcast", NULL, NULL, NOSV_TYPE_INIT_NONE); + + if (nosv_cond_init(&cond, NOSV_COND_NONE) != 0) + die("nosv_cond_init failed"); + + if (nosv_mutex_init(&mutex, NOSV_MUTEX_NONE) != 0) + die("nosv_mutex_init failed"); + + for (int i = 0; i < NTASKS; i++) + nosv_create(&tasks[i], task_type, 0, NOSV_CREATE_NONE); + + nosv_create(&task_broadcast, task_type_broadcast, 0, NOSV_CREATE_NONE); + + for (int i = 0; i < NTASKS; i++) + nosv_submit(tasks[i], NOSV_SUBMIT_NONE); + + while (atomic_load(&nstarted) != NTASKS) + nosv_yield(NOSV_YIELD_NONE); + + nosv_submit(task_broadcast, NOSV_SUBMIT_NONE); + + while (atomic_load(&ncompleted) != NTASKS) + sleep_us(1000); + + for (int i = 0; i < NTASKS; i++) + nosv_destroy(tasks[i], NOSV_DESTROY_NONE); + + nosv_destroy(task_broadcast, NOSV_DESTROY_NONE); + + if (nosv_cond_destroy(cond) != 0) + die("nosv_cond_destroy failed"); + + if (nosv_mutex_destroy(mutex) != 0) + die("nosv_mutex_destroy failed"); + + nosv_type_destroy(task_type, NOSV_TYPE_DESTROY_NONE); + nosv_type_destroy(task_type_broadcast, NOSV_TYPE_DESTROY_NONE); + + nosv_shutdown(); + + return 0; +} +