Compare commits

...

3 Commits

Author SHA1 Message Date
cc38bcfe91 Add support for progress events in OpenMP
Two new events are added (Ppp and Pps) which define the Progressing and
Stalled states respectively. A new pseudo-state Idle is shown in the
view when no thread is running.
2025-02-27 16:17:33 +01:00
8d78abd07f WIP: Allow breakdown for OpenMP without nOS-V 2024-12-10 08:28:48 +01:00
5ca0fcaed3 Implement simple OpenMP breakdown view 2024-12-10 08:28:48 +01:00
18 changed files with 512 additions and 22 deletions

View File

@ -0,0 +1,44 @@
#ParaverCFG
ConfigFile.Version: 3.4
ConfigFile.NumWindows: 1
################################################################################
< NEW DISPLAYING WINDOW CPU: OpenMP Runtime/Label breakdown >
################################################################################
window_name CPU: OpenMP Runtime/Label breakdown
window_type single
window_id 1
window_position_x 100
window_position_y 100
window_width 600
window_height 150
window_comm_lines_enabled false
window_flags_enabled false
window_noncolor_mode true
window_custom_color_enabled true
window_custom_color_palette {1.000000000000:0,70,0},{3.000000000000:99,131,0},{4.000000000000:53,121,221},{5.000000000000:223,108,0},{6.000000000000:75,127,82},{7.000000000000:242,110,162},{8.000000000000:255,190,0},{9.000000000000:153,114,0},{10.000000000000:156,12,231},{11.000000000000:177,25,229},{12.000000000000:255,72,50},{15.000000000000:0,171,255},{16.000000000000:124,213,228},{17.000000000000:242,239,141},{18.000000000000:80,80,80},{19.000000000000:94,0,0},{20.000000000000:128,165,214},{22.000000000000:222,101,128},{23.000000000000:110,148,255},{100.000000000000:0,100,0},{101.000000000000:100,100,177},{102.000000000000:150,150,0}
window_logical_filtered true
window_physical_filtered false
window_comm_fromto true
window_comm_tagsize true
window_comm_typeval true
window_units Microseconds
window_maximum_y 1000.0
window_minimum_y 1.0
window_compute_y_max true
window_level thread
window_scale_relative 1.000000000000
window_end_time_relative 1.000000000000
window_object appl { 1, { All } }
window_begin_time_relative 0.000000000000
window_open true
window_drawmode draw_randnotzero
window_drawmode_rows draw_randnotzero
window_pixel_size 1
window_labels_to_draw 1
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
window_filter_module evt_type 1 54
window_filter_module evt_type_label 1 "CPU: OpenMP Runtime/Label breakdown"

View File

@ -1,7 +1,7 @@
# Emulator events
This is a exhaustive list of the events recognized by the emulator.
Built on Nov 13 2024.
Built on Feb 5 2025.
## Model nanos6
@ -437,7 +437,7 @@ List of events for the model *ovni* with identifier **`O`** at version `1.1.0`:
## Model openmp
List of events for the model *openmp* with identifier **`P`** at version `1.2.0`:
List of events for the model *openmp* with identifier **`P`** at version `1.3.0`:
<dl>
<dt><a id="PBb" href="#PBb"><pre>PBb</pre></a></dt>
<dd>begins plain barrier</dd>
@ -575,6 +575,10 @@ List of events for the model *openmp* with identifier **`P`** at version `1.2.0`
<dd>begins worksharing with type %{typeid}</dd>
<dt><a id="PQe" href="#PQe"><pre>PQe(u32 typeid)</pre></a></dt>
<dd>ends worksharing with type %{typeid}</dd>
<dt><a id="Ppp" href="#Ppp"><pre>Ppp</pre></a></dt>
<dd>sets progress state to Progressing</dd>
<dt><a id="Pps" href="#Pps"><pre>Pps</pre></a></dt>
<dd>sets progress state to Stalled</dd>
</dl>
## Model tampi

View File

@ -177,6 +177,19 @@ currently running on each thread. The ID is a monotonically increasing
identifier assigned on task creation. Lower IDs correspond to tasks
created at an earlier point than higher IDs.
## Idle view
The idle view shows the progress state of the running threads:
*Progressing* and *Stalled*. The *Progressing* state is shown when they
are making useful progress and the *Stalled* state when they are waiting
for work. When workers start running, by definition, they begin in the
Progressing state and there are some situations that make them
transition to Stalled...
!!! Note
TODO: Complete description
## Limitations
As the compiler generates the code that perform the calls to the libompv

View File

@ -65,6 +65,7 @@ add_library(emu STATIC
kernel/event.c
openmp/setup.c
openmp/event.c
openmp/breakdown.c
)
target_link_libraries(emu ovni-static)

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 */
#ifndef EMU_PRV_H
@ -35,6 +35,8 @@ enum emu_prv_types {
PRV_OPENMP_SUBSYSTEM = 50,
PRV_OPENMP_LABEL = 51,
PRV_OPENMP_TASKID = 52,
PRV_OPENMP_IDLE = 53,
PRV_OPENMP_BREAKDOWN = 54,
PRV_OVNI_MARK = 100,
/* User marks [100, 200) */
PRV_RESERVED = 200,

View File

@ -313,7 +313,7 @@ model_nanos6_create(struct emu *emu)
extend_set(&emu->ext, model_id, e);
if (model_nanos6_breakdown_create(emu) != 0) {
err("model_nanos6_breakdown_connect failed");
err("model_nanos6_breakdown_create failed");
return -1;
}

View File

@ -80,6 +80,20 @@ model_nosv_breakdown_create(struct emu *emu)
struct nosv_emu *memu = EXT(emu, 'V');
struct nosv_breakdown_emu *bemu = &memu->breakdown;
/* Ensure all threads have breakdown enabled */
bemu->enabled = 1;
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
if (check_thread_metadata(th) != 0) {
err("bad nosv metadata in thread: %s", th->id);
bemu->enabled = 0;
}
}
if (!bemu->enabled) {
warn("cannot enable breakdown for nOS-V model");
return 0;
}
/* Count phy cpus */
struct system *sys = &emu->system;
int64_t nphycpus = (int64_t) (sys->ncpus - sys->nlooms);
@ -111,13 +125,6 @@ model_nosv_breakdown_create(struct emu *emu)
}
}
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
if (check_thread_metadata(th) != 0) {
err("bad nosv metadata in thread: %s", th->id);
return -1;
}
}
return 0;
}
@ -241,6 +248,10 @@ model_nosv_breakdown_connect(struct emu *emu)
struct nosv_emu *memu = EXT(emu, 'V');
struct nosv_breakdown_emu *bemu = &memu->breakdown;
if (!bemu->enabled)
return 0;
struct bay *bay = &emu->bay;
struct system *sys = &emu->system;
@ -290,6 +301,10 @@ model_nosv_breakdown_finish(struct emu *emu,
struct nosv_emu *memu = EXT(emu, 'V');
struct nosv_breakdown_emu *bemu = &memu->breakdown;
if (!bemu->enabled)
return 0;
struct pcf *pcf = pvt_get_pcf(bemu->pvt);
long typeid = PRV_NOSV_BREAKDOWN;
char label[] = "CPU: nOS-V Runtime/Idle/Task breakdown";

View File

@ -51,6 +51,7 @@ struct nosv_breakdown_emu {
int64_t nphycpus;
struct sort sort;
struct pvt *pvt;
int enabled;
};
#endif /* BREAKDOWN_H */

239
src/emu/openmp/breakdown.c Normal file
View File

@ -0,0 +1,239 @@
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "breakdown.h"
#include <stdint.h>
#include <stdio.h>
#include "bay.h"
#include "chan.h"
#include "common.h"
#include "cpu.h"
#include "emu.h"
#include "emu_args.h"
#include "emu_prv.h"
#include "extend.h"
#include "model_cpu.h"
#include "mux.h"
#include "openmp_priv.h"
#include "proc.h"
#include "pv/pcf.h"
#include "pv/prf.h"
#include "pv/prv.h"
#include "pv/pvt.h"
#include "recorder.h"
#include "sort.h"
#include "system.h"
#include "task.h"
#include "track.h"
#include "value.h"
static int
create_cpu(struct bay *bay, struct breakdown_cpu *bcpu, int64_t gindex)
{
enum chan_type t = CHAN_SINGLE;
chan_init(&bcpu->tri, t, "openmp.cpu%"PRIi64".breakdown.tri", gindex);
if (bay_register(bay, &bcpu->tri) != 0) {
err("bay_register tri failed");
return -1;
}
return 0;
}
int
model_openmp_breakdown_create(struct emu *emu)
{
if (emu->args.breakdown == 0)
return 0;
struct openmp_emu *memu = EXT(emu, 'P');
struct breakdown_emu *bemu = &memu->breakdown;
/* Count phy cpus */
struct system *sys = &emu->system;
int64_t nphycpus = (int64_t) (sys->ncpus - sys->nlooms);
bemu->nphycpus = nphycpus;
/* Create a new Paraver trace */
struct recorder *rec = &emu->recorder;
bemu->pvt = recorder_add_pvt(rec, "openmp-breakdown", (long) nphycpus);
if (bemu->pvt == NULL) {
err("recorder_add_pvt failed");
return -1;
}
if (sort_init(&bemu->sort, &emu->bay, nphycpus, "openmp.breakdown.sort") != 0) {
err("sort_init failed");
return -1;
}
for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
if (cpu->is_virtual)
continue;
struct openmp_cpu *mcpu = EXT(cpu, 'P');
struct breakdown_cpu *bcpu = &mcpu->breakdown;
if (create_cpu(&emu->bay, bcpu, cpu->gindex) != 0) {
err("create_cpu failed");
return -1;
}
}
return 0;
}
static int
select_label(struct mux *mux, struct value value, struct mux_input **input)
{
dbg("selecting tri output for value %s", value_str(value));
if (value.type != VALUE_NULL) {
dbg("selecting input 0 (label)");
*input = mux_get_input(mux, 0);
} else {
dbg("selecting input 1 (subsystem)");
*input = mux_get_input(mux, 1);
}
return 0;
}
static int
connect_cpu(struct bay *bay, struct openmp_cpu *mcpu)
{
struct breakdown_cpu *bcpu = &mcpu->breakdown;
/* Channel aliases */
struct chan *subsystem = &mcpu->m.track[CH_SUBSYSTEM].ch;
struct chan *label = &mcpu->m.track[CH_LABEL].ch;
struct chan *tri = &bcpu->tri;
/* Connect mux using label as select */
if (mux_init(&bcpu->mux, bay, label, tri, select_label, 2) != 0) {
err("mux_init failed");
return -1;
}
if (mux_set_input(&bcpu->mux, 0, label) != 0) {
err("mux_set_input label failed");
return -1;
}
if (mux_set_input(&bcpu->mux, 1, subsystem) != 0) {
err("mux_set_input subsystem failed");
return -1;
}
/* Emit unknown subsystem on NULL */
//mux_set_default(&bcpu->mux, value_int64(ST_UNKNOWN_SS));
return 0;
}
int
model_openmp_breakdown_connect(struct emu *emu)
{
if (emu->args.breakdown == 0)
return 0;
struct openmp_emu *memu = EXT(emu, 'P');
struct breakdown_emu *bemu = &memu->breakdown;
struct bay *bay = &emu->bay;
struct system *sys = &emu->system;
int64_t i = 0;
for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) {
if (cpu->is_virtual)
continue;
struct openmp_cpu *mcpu = EXT(cpu, 'P');
struct breakdown_cpu *bcpu = &mcpu->breakdown;
/* Connect tri channels and muxes */
if (connect_cpu(bay, mcpu) != 0) {
err("connect_cpu failed");
return -1;
}
/* Connect tri to sort */
if (sort_set_input(&bemu->sort, i, &bcpu->tri) != 0) {
err("sort_set_input failed");
return -1;
}
/* Connect out to PRV */
struct prv *prv = pvt_get_prv(bemu->pvt);
long type = PRV_OPENMP_BREAKDOWN;
long flags = PRV_SKIPDUP;
/* We may emit zero at the start, when an input changes and all
* the other sort output channels write a zero in the output,
* before the last value is set in prv.c. */
flags |= PRV_ZERO;
struct chan *out = sort_get_output(&bemu->sort, i);
if (prv_register(prv, (long) i, type, bay, out, flags)) {
err("prv_register failed");
return -1;
}
i++;
}
return 0;
}
int
model_openmp_breakdown_finish(struct emu *emu,
const struct pcf_value_label **labels)
{
if (emu->args.breakdown == 0)
return 0;
struct openmp_emu *memu = EXT(emu, 'P');
struct breakdown_emu *bemu = &memu->breakdown;
struct pcf *pcf = pvt_get_pcf(bemu->pvt);
long typeid = PRV_OPENMP_BREAKDOWN;
char label[] = "CPU: OpenMP Runtime/Label breakdown";
struct pcf_type *pcftype = pcf_add_type(pcf, (int) typeid, label);
const struct pcf_value_label *v = NULL;
/* Emit subsystem values */
for (v = labels[CH_SUBSYSTEM]; v->label; v++) {
if (pcf_add_value(pcftype, v->value, v->label) == NULL) {
err("pcf_add_value ss failed");
return -1;
}
}
/* Emit label values */
struct system *sys = &emu->system;
for (struct proc *p = sys->procs; p; p = p->gnext) {
struct openmp_proc *proc = EXT(p, 'P');
struct task_info *info = &proc->task_info;
if (task_create_pcf_types(pcftype, info->types) != 0) {
err("task_create_pcf_types failed");
return -1;
}
}
/* Also populate the row labels */
struct prf *prf = pvt_get_prf(bemu->pvt);
for (int64_t row = 0; row < bemu->nphycpus; row++) {
char name[128];
if (snprintf(name, 128, "~CPU %4" PRIi64, bemu->nphycpus - row) >= 128) {
err("label too long");
return -1;
}
if (prf_add(prf, (long) row, name) != 0) {
err("prf_add failed for %s", name);
return -1;
}
}
return 0;
}

View File

@ -0,0 +1,48 @@
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef BREAKDOWN_H
#define BREAKDOWN_H
/*
* The breakdown model is implemented on top of the CPU subsystem, task_type and
* idle channels. The first mux0 selects the task type when the subsystem
* matches "Task body" otherwise forwards the subsystem as-is to tr. The second
* mux1 selects tr only when the CPU is not Idle, otherwise sets the output tri
* as Idle.
*
* +--------+
* | |
* | v
* | +------+
* label -----+-->--| |
* | mux0 |
* subsystem ---->--| |-->-- tri
* +------+
* Then the sort module takes the output tri of each CPU and sorts the values
* which are propagated to the PRV directly.
*
* +------+ +-----+
* cpu0.tri --->---| |--->---| |
* ... | sort | ... | PRV |
* cpuN.tri --->---| |--->---| |
* +------+ +-----+
*/
#include <stdint.h>
#include "chan.h"
#include "mux.h"
#include "sort.h"
struct breakdown_cpu {
struct mux mux;
struct chan tri;
};
struct breakdown_emu {
int64_t nphycpus;
struct sort sort;
struct pvt *pvt;
};
#endif /* BREAKDOWN_H */

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
/* Copyright (c) 2023-2025 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "openmp_priv.h"
@ -14,7 +14,7 @@
#include "thread.h"
#include "value.h"
enum { PUSH = 1, POP = 2, IGN = 3 };
enum { PUSH = 1, POP, SET, IGN };
static const int fn_table[256][256][3] = {
['B'] = {
@ -95,6 +95,10 @@ static const int fn_table[256][256][3] = {
['f'] = { CH_SUBSYSTEM, PUSH, ST_RT_FORK_CALL },
['F'] = { CH_SUBSYSTEM, POP, ST_RT_FORK_CALL },
},
['p'] = {
['p'] = { CH_IDLE, SET, ST_PROGRESSING },
['s'] = { CH_IDLE, SET, ST_STALLED },
},
};
static int
@ -117,6 +121,8 @@ simple(struct emu *emu)
return chan_push(ch, value_int64(st));
} else if (action == POP) {
return chan_pop(ch, value_int64(st));
} else if (action == SET) {
return chan_set(ch, value_int64(st));
} else if (action == IGN) {
return 0; /* do nothing */
}
@ -369,6 +375,7 @@ process_ev(struct emu *emu)
case 'M':
case 'H':
case 'C':
case 'p':
return simple(emu);
case 'P':
return pre_task(emu);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
/* Copyright (c) 2023-2025 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef OPENMP_PRIV_H
@ -8,6 +8,7 @@
#include "task.h"
#include "model_cpu.h"
#include "model_thread.h"
#include "breakdown.h"
/* Private enums */
@ -15,6 +16,7 @@ enum openmp_chan {
CH_SUBSYSTEM = 0,
CH_LABEL,
CH_TASKID,
CH_IDLE,
CH_MAX,
};
@ -56,6 +58,14 @@ enum openmp_function_values {
ST_RT_WORKER_LOOP,
};
enum openmp_progress_values {
/* Can mix with subsystem values */
ST_PROGRESSING = 100,
ST_STALLED, /* Running thread doing nothing useful */
ST_IDLE, /* No running threads */
};
struct openmp_thread {
struct model_thread m;
struct task_stack task_stack;
@ -63,6 +73,7 @@ struct openmp_thread {
struct openmp_cpu {
struct model_cpu m;
struct breakdown_cpu breakdown;
};
struct openmp_proc {
@ -70,10 +81,19 @@ struct openmp_proc {
struct task_info task_info;
};
struct openmp_emu {
struct breakdown_emu breakdown;
};
int model_openmp_probe(struct emu *emu);
int model_openmp_create(struct emu *emu);
int model_openmp_connect(struct emu *emu);
int model_openmp_event(struct emu *emu);
int model_openmp_finish(struct emu *emu);
int model_openmp_breakdown_create(struct emu *emu);
int model_openmp_breakdown_connect(struct emu *emu);
int model_openmp_breakdown_finish(struct emu *emu,
const struct pcf_value_label **labels);
#endif /* OPENMP_PRIV_H */

View File

@ -1,10 +1,11 @@
/* Copyright (c) 2023-2024 Barcelona Supercomputing Center (BSC)
/* Copyright (c) 2023-2025 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "openmp_priv.h"
#include <stddef.h>
#include "chan.h"
#include "common.h"
#include "cpu.h"
#include "emu.h"
#include "emu_args.h"
#include "emu_prv.h"
@ -77,12 +78,15 @@ static struct ev_decl model_evlist[] = {
{ "PQx(u32 typeid)", "begins worksharing with type %{typeid}" },
{ "PQe(u32 typeid)", "ends worksharing with type %{typeid}" },
{ "Ppp", "sets progress state to Progressing" },
{ "Pps", "sets progress state to Stalled" },
{ NULL, NULL },
};
struct model_spec model_openmp = {
.name = model_name,
.version = "1.2.0",
.version = "1.3.0",
.evlist = model_evlist,
.model = model_id,
.create = model_openmp_create,
@ -98,6 +102,7 @@ static const char *chan_name[CH_MAX] = {
[CH_SUBSYSTEM] = "subsystem",
[CH_LABEL] = "label",
[CH_TASKID] = "task ID",
[CH_IDLE] = "idle",
};
static const int chan_stack[CH_MAX] = {
@ -118,12 +123,14 @@ static const int pvt_type[CH_MAX] = {
[CH_SUBSYSTEM] = PRV_OPENMP_SUBSYSTEM,
[CH_LABEL] = PRV_OPENMP_LABEL,
[CH_TASKID] = PRV_OPENMP_TASKID,
[CH_IDLE] = PRV_OPENMP_IDLE,
};
static const char *pcf_prefix[CH_MAX] = {
[CH_SUBSYSTEM] = "OpenMP subsystem",
[CH_LABEL] = "OpenMP label",
[CH_TASKID] = "OpenMP task ID",
[CH_IDLE] = "OpenMP idle",
};
static const struct pcf_value_label openmp_subsystem_values[] = {
@ -166,14 +173,23 @@ static const struct pcf_value_label openmp_subsystem_values[] = {
{ -1, NULL },
};
static const struct pcf_value_label openmp_progress_values[] = {
{ ST_PROGRESSING, "Progressing" },
{ ST_STALLED, "Stalled" },
{ ST_IDLE, "Idle" },
{ -1, NULL },
};
static const struct pcf_value_label *pcf_labels[CH_MAX] = {
[CH_SUBSYSTEM] = openmp_subsystem_values,
[CH_IDLE] = openmp_progress_values,
};
static const long prv_flags[CH_MAX] = {
[CH_SUBSYSTEM] = PRV_SKIPDUPNULL,
[CH_LABEL] = PRV_SKIPDUPNULL,
[CH_TASKID] = PRV_SKIPDUPNULL,
[CH_IDLE] = PRV_SKIPDUPNULL,
};
static const struct model_pvt_spec pvt_spec = {
@ -189,12 +205,14 @@ static const int th_track[CH_MAX] = {
[CH_SUBSYSTEM] = TRACK_TH_ACT,
[CH_LABEL] = TRACK_TH_ACT,
[CH_TASKID] = TRACK_TH_ACT,
[CH_IDLE] = TRACK_TH_ACT,
};
static const int cpu_track[CH_MAX] = {
[CH_SUBSYSTEM] = TRACK_TH_RUN,
[CH_LABEL] = TRACK_TH_RUN,
[CH_TASKID] = TRACK_TH_RUN,
[CH_IDLE] = TRACK_TH_RUN,
};
/* ----------------- chan_spec ------------------ */
@ -278,6 +296,19 @@ model_openmp_create(struct emu *emu)
}
}
struct openmp_emu *e = calloc(1, sizeof(struct openmp_emu));
if (e == NULL) {
err("calloc failed:");
return -1;
}
extend_set(&emu->ext, model_id, e);
if (model_openmp_breakdown_create(emu) != 0) {
err("model_openmp_breakdown_create failed");
return -1;
}
return 0;
}
@ -294,6 +325,28 @@ model_openmp_connect(struct emu *emu)
return -1;
}
if (model_openmp_breakdown_connect(emu) != 0) {
err("model_openmp_breakdown_connect failed");
return -1;
}
for (struct thread *th = emu->system.threads; th; th = th->gnext) {
struct openmp_thread *mth = EXT(th, model_id);
struct chan *idle = &mth->m.ch[CH_IDLE];
/* By default set all threads as Progressing */
if (chan_set(idle, value_int64(ST_PROGRESSING)) != 0) {
err("chan_push idle failed");
return -1;
}
}
for (struct cpu *cpu = emu->system.cpus; cpu; cpu = cpu->next) {
struct openmp_cpu *mcpu = EXT(cpu, model_id);
struct mux *mux = &mcpu->m.track[CH_IDLE].mux;
/* Emit Idle when a CPU has no running threads */
mux_set_default(mux, value_int64(ST_IDLE));
}
return 0;
}
@ -379,6 +432,11 @@ model_openmp_finish(struct emu *emu)
return -1;
}
if (model_openmp_breakdown_finish(emu, pcf_labels) != 0) {
err("model_openmp_breakdown_finish failed");
return -1;
}
/* When running in linter mode perform additional checks */
if (emu->args.linter_mode && end_lint(emu) != 0) {
err("end_lint failed");

View File

@ -1,6 +1,7 @@
# Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
# Copyright (c) 2024-2025 Barcelona Supercomputing Center (BSC)
# SPDX-License-Identifier: GPL-3.0-or-later
test_emu(nested-ws.c)
test_emu(nested-task.c)
test_emu(mix-task-ws.c)
test_emu(idle.c)

34
test/emu/openmp/idle.c Normal file
View File

@ -0,0 +1,34 @@
/* Copyright (c) 2025 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include <stdlib.h>
#include "compat.h"
#include "instr.h"
#include "instr_openmp.h"
int
main(void)
{
instr_start(0, 1);
instr_openmp_init();
instr_openmp_type_create(1, "task");
instr_openmp_task_create(1, 1);
instr_openmp_stalled();
sleep_us(100);
instr_openmp_progressing();
sleep_us(100);
/* Pause the thread to create Idle state */
instr_thread_pause();
sleep_us(100);
instr_thread_resume();
sleep_us(100);
instr_openmp_task_execute(1);
sleep_us(100);
instr_openmp_task_end(1);
instr_end();
return 0;
}

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2024 Barcelona Supercomputing Center (BSC)
/* Copyright (c) 2024-2025 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef INSTR_OPENMP_H
@ -44,4 +44,7 @@ INSTR_1ARG(instr_openmp_task_end, "PPe", uint32_t, taskid)
INSTR_1ARG(instr_openmp_ws_enter, "PQx", uint32_t, typeid)
INSTR_1ARG(instr_openmp_ws_exit, "PQe", uint32_t, typeid)
INSTR_0ARG(instr_openmp_progressing, "Ppp")
INSTR_0ARG(instr_openmp_stalled, "Pps")
#endif /* INSTR_OPENMP_H */

View File

@ -26,7 +26,7 @@ if(NOT NOSV_FOUND)
endif()
function(openmp_rt_test)
ovni_test(${ARGN})
ovni_test(${ARGN} SORT)
target_compile_options("${OVNI_TEST_NAME}" PUBLIC "-fopenmp=libompv"
"-no-pedantic")
target_link_options("${OVNI_TEST_NAME}" PUBLIC "-fopenmp=libompv")
@ -34,7 +34,7 @@ function(openmp_rt_test)
set_property(TEST "${OVNI_TEST_NAME}" APPEND PROPERTY
ENVIRONMENT "OMP_OVNI=1")
set_property(TEST "${OVNI_TEST_NAME}" APPEND PROPERTY
ENVIRONMENT "NOSV_CONFIG_OVERRIDE=instrumentation.version=ovni")
ENVIRONMENT "NOSV_CONFIG_OVERRIDE=instrumentation.version=ovni,ovni.level=3")
endfunction()
openmp_rt_test(barrier-explicit.c)
@ -53,7 +53,7 @@ openmp_rt_test(taskloop.c)
openmp_rt_test(taskwait.c)
openmp_rt_test(team-distribute.c)
openmp_rt_test(worksharing-and-tasks.c)
openmp_rt_test(worksharing-mix.c)
openmp_rt_test(worksharing-mix.c BREAKDOWN)
openmp_rt_test(worksharing-task.c)
openmp_rt_test(worksharing.c)
openmp_rt_test(worksharing01.c)

View File

@ -34,7 +34,7 @@ int main(void)
#pragma omp single
for (int i = 0; i < 100; i++)
{
#pragma omp task
#pragma omp task label("mini-task")
sleep_us(10);
}
}