Split nanos6 model into separate files

This commit is contained in:
Rodrigo Arias 2023-02-01 11:38:39 +01:00 committed by Rodrigo Arias Mallo
parent 0e8b23c918
commit cc5582c493
24 changed files with 1129 additions and 1198 deletions

View File

@ -15,6 +15,7 @@ void vdie(const char *func, const char *errstr, ...);
/* clang-format off */
#define rerr(...) fprintf(stderr, __VA_ARGS__);
#define err(...) verr(__func__, __VA_ARGS__);
#define die(...) vdie(__func__, __VA_ARGS__);

View File

@ -8,9 +8,6 @@ include_directories(
"${CMAKE_SOURCE_DIR}/include"
)
#add_library(trace STATIC trace.c)
#target_link_libraries(trace parson ovni-static)
add_library(emu STATIC
../common.c
bay.c
@ -26,7 +23,6 @@ add_library(emu STATIC
emu_trace.c
loom.c
metadata.c
model_nanos6.c
model_ust.c
mux.c
path.c
@ -38,26 +34,15 @@ add_library(emu STATIC
task.c
thread.c
extend.c
nanos6/probe.c
nanos6/connect.c
nanos6/create.c
nanos6/event.c
)
#add_library(emu STATIC
# chan.c
# emu.c
# nosv.c
# openmp.c
# ovni.c
# tampi.c
# nodes.c
# kernel.c
# nanos6.c
# task.c
# pcf.c
# prv.c
#)
#
#add_executable(ovniemu ovniemu.c)
#target_link_libraries(ovniemu emu trace)
#
add_executable(ovniemu ovniemu.c)
target_link_libraries(ovniemu emu parson-static ovni-static)
#add_executable(ovnidump ovnidump.c)
#target_link_libraries(ovnidump emu trace)
#

View File

@ -1,4 +1,4 @@
#define ENABLE_DEBUG
//#define ENABLE_DEBUG
#include "bay.h"

View File

@ -1,7 +1,7 @@
/* Copyright (c) 2021-2022 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#define ENABLE_DEBUG
//#define ENABLE_DEBUG
#include "chan.h"
#include "common.h"

View File

@ -37,7 +37,7 @@ cpu_init_begin(struct cpu *cpu, int phyid)
cpu->phyid = phyid;
err("cpu init %d", phyid);
dbg("cpu init %d", phyid);
}
int

View File

@ -3,13 +3,13 @@
#define _POSIX_C_SOURCE 2
#define ENABLE_DEBUG
//#define ENABLE_DEBUG
#include "emu.h"
#include <unistd.h>
#include "model_ust.h"
#include "model_nanos6.h"
#include "models.h"
int
emu_init(struct emu *emu, int argc, char *argv[])
@ -54,8 +54,6 @@ emu_init(struct emu *emu, int argc, char *argv[])
// /* Register all the models */
// emu_model_register(&emu->model, &ovni_model_spec, emu);
//
if (model_ust.create && model_ust.create(emu) != 0) {
err("model ust create failed");

View File

@ -14,16 +14,16 @@ static char progname[] = "ovniemu";
static void
usage(void)
{
err("Usage: %s [-c offsetfile] tracedir\n", progname);
err("\n");
err("Options:\n");
err(" -c offsetfile Use the given offset file to correct\n");
err(" the clocks among nodes. It can be\n");
err(" generated by the ovnisync program\n");
err("\n");
err(" tracedir The output trace dir generated by ovni.\n");
err("\n");
err("The output PRV files are placed in the tracedir directory.\n");
rerr("Usage: %s [-c offsetfile] tracedir\n", progname);
rerr("\n");
rerr("Options:\n");
rerr(" -c offsetfile Use the given offset file to correct\n");
rerr(" the clocks among nodes. It can be\n");
rerr(" generated by the ovnisync program\n");
rerr("\n");
rerr(" tracedir The output trace dir generated by ovni.\n");
rerr("\n");
rerr("The output PRV files are placed in the tracedir directory.\n");
exit(EXIT_FAILURE);
}
@ -34,7 +34,7 @@ emu_args_init(struct emu_args *args, int argc, char *argv[])
memset(args, 0, sizeof(struct emu_args));
int opt;
while ((opt = getopt(argc, argv, "c:l")) != -1) {
while ((opt = getopt(argc, argv, "c:lh")) != -1) {
switch (opt) {
case 'c':
args->clock_offset_file = optarg;
@ -42,6 +42,7 @@ emu_args_init(struct emu_args *args, int argc, char *argv[])
case 'l':
args->linter_mode = 1;
break;
case 'h':
default: /* '?' */
usage();
}

View File

@ -84,7 +84,7 @@ emu_stream_load(struct emu_stream *stream, const char *tracedir, const char *rel
return -1;
}
err("emu_stream_load: loading %s\n", stream->relpath);
dbg("emu_stream_load: loading %s\n", stream->relpath);
if ((fd = open(stream->path, O_RDWR)) == -1) {
err("emu_stream_load: open failed: %s\n", stream->path);

View File

@ -95,13 +95,13 @@ emu_trace_load(struct emu_trace *trace, const char *tracedir)
cur_trace = trace;
if (snprintf(trace->tracedir, PATH_MAX, "%s", tracedir) >= PATH_MAX) {
err("emu_trace_load: path too long: %s\n", tracedir);
err("path too long: %s", tracedir);
return -1;
}
/* Search recursively all streams in the trace directory */
if (nftw(tracedir, cb_nftw, 50, 0) != 0) {
err("emu_trace_load: nftw failed\n");
err("nftw failed");
return -1;
}
@ -110,7 +110,7 @@ emu_trace_load(struct emu_trace *trace, const char *tracedir)
/* Sort the streams */
DL_SORT(trace->streams, cmp_streams);
err("emu_trace_load: loaded %ld streams\n", trace->nstreams);
err("loaded %ld streams", trace->nstreams);
return 0;
}

View File

@ -66,7 +66,7 @@ loom_init_begin(struct loom *loom, const char *name)
cpu_init_begin(&loom->vcpu, -1);
err("creating new loom %s", loom->id);
dbg("creating new loom %s", loom->id);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,34 +0,0 @@
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef MODEL_NANOS6_H
#define MODEL_NANOS6_H
#include "emu_model.h"
extern struct model_spec model_nanos6;
#include "chan.h"
#include "mux.h"
#include "task.h"
struct nanos6_thread {
struct chan *ch; /* Raw, modified by nanos6 */
struct chan *ch_run; /* Tracking running thread */
struct chan *ch_act; /* Tracking active thread */
struct chan **ch_out; /* Output to PRV */
struct mux *mux_run;
struct mux *mux_act;
struct task_stack task_stack;
};
struct nanos6_cpu {
struct chan *ch;
struct mux *mux;
};
struct nanos6_proc {
struct task_info task_info;
};
#endif /* MODEL_NANOS6_H */

12
src/emu/models.h Normal file
View File

@ -0,0 +1,12 @@
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef MODELS_H
#define MODELS_H
#include "emu_model.h"
extern struct model_spec model_ust;
extern struct model_spec model_nanos6;
#endif /* MODELS_H */

View File

@ -1,4 +1,4 @@
#define ENABLE_DEBUG
//#define ENABLE_DEBUG
#include "mux.h"
@ -57,6 +57,7 @@ cb_select(struct chan *sel_chan, void *ptr)
}
char buf[128];
UNUSED(buf);
dbg("select channel got value %s\n",
value_str(sel_value, buf));

253
src/emu/nanos6/connect.c Normal file
View File

@ -0,0 +1,253 @@
#include "nanos6_priv.h"
static const char *th_track[] = {
[CH_TASKID] = "running",
[CH_TYPE] = "running",
[CH_SUBSYSTEM] = "active",
[CH_RANK] = "running",
[CH_THREAD] = "none",
};
static const char *cpu_track[] = {
[CH_TASKID] = "running",
[CH_TYPE] = "running",
[CH_SUBSYSTEM] = "running",
[CH_RANK] = "running",
[CH_THREAD] = "running",
};
static const int th_type[] = {
[CH_TASKID] = 35,
[CH_TYPE] = 36,
[CH_SUBSYSTEM] = 37,
[CH_RANK] = 38,
[CH_THREAD] = 39,
};
static const int *cpu_type = th_type;
static int
connect_thread_mux(struct emu *emu, struct thread *thread)
{
struct nanos6_thread *th = extend_get(&thread->ext, '6');
for (int i = 0; i < CH_MAX; i++) {
/* TODO: Let the thread take the select channel
* and build the mux as a tracking mode */
struct chan *inp = &th->ch[i];
struct chan *sel = &thread->chan[TH_CHAN_STATE];
struct mux *mux_run = &th->mux_run[i];
mux_select_func_t selrun = thread_select_running;
if (mux_init(mux_run, &emu->bay, sel, &th->ch_run[i], selrun) != 0) {
err("mux_init failed");
return -1;
}
if (mux_add_input(mux_run, value_int64(0), inp) != 0) {
err("mux_add_input failed");
return -1;
}
struct mux *mux_act = &th->mux_act[i];
mux_select_func_t selact = thread_select_active;
if (mux_init(mux_act, &emu->bay, sel, &th->ch_act[i], selact) != 0) {
err("mux_init failed");
return -1;
}
if (mux_add_input(mux_act, value_int64(0), inp) != 0) {
err("mux_add_input failed");
return -1;
}
if (mux_act->ninputs != 1)
die("expecting one input only");
/* The tracking only sets the ch_out, but we keep both tracking
* updated as the CPU tracking channels may use them. */
const char *tracking = th_track[i];
if (strcmp(tracking, "running") == 0) {
th->ch_out[i] = &th->ch_run[i];
} else if (strcmp(tracking, "active") == 0) {
th->ch_out[i] = &th->ch_act[i];
} else {
th->ch_out[i] = &th->ch[i];
}
}
return 0;
}
static int
connect_thread_prv(struct emu *emu, struct thread *thread, struct prv *prv)
{
struct nanos6_thread *th = extend_get(&thread->ext, '6');
for (int i = 0; i < CH_MAX; i++) {
struct chan *out = th->ch_out[i];
long type = th_type[i];
long row = thread->gindex;
if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) {
err("prv_register failed");
return -1;
}
}
return 0;
}
static int
add_inputs_cpu_mux(struct emu *emu, struct mux *mux, int i)
{
for (struct thread *t = emu->system.threads; t; t = t->gnext) {
struct nanos6_thread *th = extend_get(&t->ext, '6');
/* Choose input thread channel based on tracking mode */
const char *tracking = cpu_track[i];
struct chan *inp;
if (strcmp(tracking, "running") == 0) {
inp = &th->ch_run[i];
} else if (strcmp(tracking, "active") == 0) {
inp = &th->ch_act[i];
} else {
die("cpu tracking must be 'running' or 'active'");
}
if (mux_add_input(mux, value_int64(t->gindex), inp) != 0) {
err("mux_add_input failed");
return -1;
}
}
return 0;
}
static int
connect_cpu_mux(struct emu *emu, struct cpu *scpu)
{
struct nanos6_cpu *cpu = extend_get(&scpu->ext, '6');
for (int i = 0; i < CH_MAX; i++) {
struct mux *mux = &cpu->mux[i];
struct chan *out = &cpu->ch[i];
const char *tracking = cpu_track[i];
/* Choose select CPU channel based on tracking mode */
struct chan *sel;
if (strcmp(tracking, "running") == 0) {
sel = &scpu->chan[CPU_CHAN_THRUN];
} else if (strcmp(tracking, "active") == 0) {
sel = &scpu->chan[CPU_CHAN_THACT];
} else {
die("cpu tracking must be 'running' or 'active'");
}
if (mux_init(mux, &emu->bay, sel, out, NULL) != 0) {
err("mux_init failed");
return -1;
}
if (add_inputs_cpu_mux(emu, mux, i) != 0) {
err("add_inputs_cpu_mux failed");
return -1;
}
}
return 0;
}
static int
connect_threads(struct emu *emu)
{
struct system *sys = &emu->system;
/* threads */
for (struct thread *t = sys->threads; t; t = t->gnext) {
if (connect_thread_mux(emu, t) != 0) {
err("connect_thread_mux failed");
return -1;
}
}
/* Get thread PRV */
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread");
if (pvt == NULL) {
err("cannot find thread pvt");
return -1;
}
struct prv *prv = pvt_get_prv(pvt);
for (struct thread *t = sys->threads; t; t = t->gnext) {
if (connect_thread_prv(emu, t, prv) != 0) {
err("connect_thread_prv failed");
return -1;
}
}
return 0;
}
static int
connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv)
{
struct nanos6_cpu *cpu = extend_get(&scpu->ext, '6');
for (int i = 0; i < CH_MAX; i++) {
struct chan *out = &cpu->ch[i];
long type = cpu_type[i];
long row = scpu->gindex;
if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) {
err("prv_register failed");
return -1;
}
}
return 0;
}
static int
connect_cpus(struct emu *emu)
{
struct system *sys = &emu->system;
/* cpus */
for (struct cpu *c = sys->cpus; c; c = c->next) {
if (connect_cpu_mux(emu, c) != 0) {
err("connect_cpu_mux failed");
return -1;
}
}
/* Get cpu PRV */
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "cpu");
if (pvt == NULL) {
err("cannot find cpu pvt");
return -1;
}
struct prv *prv = pvt_get_prv(pvt);
for (struct cpu *c = sys->cpus; c; c = c->next) {
if (connect_cpu_prv(emu, c, prv) != 0) {
err("connect_cpu_prv failed");
return -1;
}
}
return 0;
}
int
nanos6_connect(struct emu *emu)
{
if (connect_threads(emu) != 0) {
err("connect_threads failed");
return -1;
}
if (connect_cpus(emu) != 0) {
err("connect_cpus failed");
return -1;
}
return 0;
}

180
src/emu/nanos6/create.c Normal file
View File

@ -0,0 +1,180 @@
#include "nanos6_priv.h"
static const char chan_fmt_cpu_raw[] = "nanos6.cpu%ld.%s";
//static const char chan_fmt_cpu_run[] = "nanos6.cpu%ld.%s.run";
//static const char chan_fmt_cpu_act[] = "nanos6.cpu%ld.%s.act";
static const char chan_fmt_th_raw[] = "nanos6.thread%ld.%s.raw";
static const char chan_fmt_th_run[] = "nanos6.thread%ld.%s.run";
static const char chan_fmt_th_act[] = "nanos6.thread%ld.%s.act";
static const char *chan_name[] = {
[CH_TASKID] = "taskid",
[CH_TYPE] = "task_type",
[CH_SUBSYSTEM] = "subsystem",
[CH_RANK] = "rank",
[CH_THREAD] = "thread_type",
};
static const int chan_stack[] = {
[CH_SUBSYSTEM] = 1,
[CH_THREAD] = 1,
};
static int
init_chans(struct bay *bay, struct chan *chans, const char *fmt, int64_t gindex, int filtered)
{
for (int i = 0; i < CH_MAX; i++) {
struct chan *c = &chans[i];
int type = (chan_stack[i] && !filtered) ? CHAN_STACK : CHAN_SINGLE;
chan_init(c, type, fmt, gindex, chan_name[i]);
if (bay_register(bay, c) != 0) {
err("bay_register failed");
return -1;
}
}
return 0;
}
static int
init_cpu(struct bay *bay, struct cpu *syscpu)
{
struct nanos6_cpu *cpu = calloc(1, sizeof(struct nanos6_cpu));
if (cpu == NULL) {
err("calloc failed:");
return -1;
}
cpu->ch = calloc(CH_MAX, sizeof(struct chan));
if (cpu->ch == NULL) {
err("calloc failed:");
return -1;
}
cpu->mux = calloc(CH_MAX, sizeof(struct mux));
if (cpu->mux == NULL) {
err("calloc failed:");
return -1;
}
if (init_chans(bay, cpu->ch, chan_fmt_cpu_raw, syscpu->gindex, 1) != 0) {
err("init_chans failed");
return -1;
}
extend_set(&syscpu->ext, '6', cpu);
return 0;
}
static int
init_thread(struct bay *bay, struct thread *systh)
{
struct nanos6_thread *th = calloc(1, sizeof(struct nanos6_thread));
if (th == NULL) {
err("calloc failed:");
return -1;
}
th->ch = calloc(CH_MAX, sizeof(struct chan));
if (th->ch == NULL) {
err("calloc failed:");
return -1;
}
th->ch_run = calloc(CH_MAX, sizeof(struct chan));
if (th->ch_run == NULL) {
err("calloc failed:");
return -1;
}
th->ch_act = calloc(CH_MAX, sizeof(struct chan));
if (th->ch_act == NULL) {
err("calloc failed:");
return -1;
}
th->ch_out = calloc(CH_MAX, sizeof(struct chan *));
if (th->ch_out == NULL) {
err("calloc failed:");
return -1;
}
th->mux_run = calloc(CH_MAX, sizeof(struct mux));
if (th->mux_run == NULL) {
err("calloc failed:");
return -1;
}
th->mux_act = calloc(CH_MAX, sizeof(struct mux));
if (th->mux_act == NULL) {
err("calloc failed:");
return -1;
}
if (init_chans(bay, th->ch, chan_fmt_th_raw, systh->gindex, 0) != 0) {
err("init_chans failed");
return -1;
}
if (init_chans(bay, th->ch_run, chan_fmt_th_run, systh->gindex, 1) != 0) {
err("init_chans failed");
return -1;
}
if (init_chans(bay, th->ch_act, chan_fmt_th_act, systh->gindex, 1) != 0) {
err("init_chans failed");
return -1;
}
th->task_stack.thread = systh;
extend_set(&systh->ext, '6', th);
return 0;
}
static int
init_proc(struct proc *sysproc)
{
struct nanos6_proc *proc = calloc(1, sizeof(struct nanos6_proc));
if (proc == NULL) {
err("calloc failed:");
return -1;
}
extend_set(&sysproc->ext, '6', proc);
return 0;
}
int
nanos6_create(struct emu *emu)
{
struct system *sys = &emu->system;
struct bay *bay = &emu->bay;
for (struct cpu *c = sys->cpus; c; c = c->next) {
if (init_cpu(bay, c) != 0) {
err("init_cpu failed");
return -1;
}
}
for (struct thread *t = sys->threads; t; t = t->gnext) {
if (init_thread(bay, t) != 0) {
err("init_thread failed");
return -1;
}
}
for (struct proc *p = sys->procs; p; p = p->gnext) {
if (init_proc(p) != 0) {
err("init_proc failed");
return -1;
}
}
return 0;
}

525
src/emu/nanos6/event.c Normal file
View File

@ -0,0 +1,525 @@
#include "nanos6_priv.h"
enum { PUSH = 1, POP = 2, IGN = 3 };
#define CHSS CH_SUBSYSTEM
#define CHTH CH_THREAD
static const int ss_table[256][256][3] = {
['W'] = {
['['] = { CHSS, PUSH, ST_WORKER_LOOP },
[']'] = { CHSS, POP, ST_WORKER_LOOP },
['t'] = { CHSS, PUSH, ST_HANDLING_TASK },
['T'] = { CHSS, POP, ST_HANDLING_TASK },
['w'] = { CHSS, PUSH, ST_SWITCH_TO },
['W'] = { CHSS, POP, ST_SWITCH_TO },
['m'] = { CHSS, PUSH, ST_MIGRATE },
['M'] = { CHSS, POP, ST_MIGRATE },
['s'] = { CHSS, PUSH, ST_SUSPEND },
['S'] = { CHSS, POP, ST_SUSPEND },
['r'] = { CHSS, PUSH, ST_RESUME },
['R'] = { CHSS, POP, ST_RESUME },
['*'] = { CHSS, IGN, -1 },
},
['C'] = {
['['] = { CHSS, PUSH, ST_TASK_CREATING },
[']'] = { CHSS, POP, ST_TASK_CREATING },
},
['U'] = {
['['] = { CHSS, PUSH, ST_TASK_SUBMIT },
[']'] = { CHSS, POP, ST_TASK_SUBMIT },
},
['F'] = {
['['] = { CHSS, PUSH, ST_TASK_SPAWNING },
[']'] = { CHSS, POP, ST_TASK_SPAWNING },
},
['O'] = {
['['] = { CHSS, PUSH, ST_TASK_FOR },
[']'] = { CHSS, POP, ST_TASK_FOR },
},
['t'] = {
['['] = { CHSS, PUSH, ST_TASK_BODY },
[']'] = { CHSS, POP, ST_TASK_BODY },
},
['M'] = {
['a'] = { CHSS, PUSH, ST_ALLOCATING },
['A'] = { CHSS, POP, ST_ALLOCATING },
['f'] = { CHSS, PUSH, ST_FREEING },
['F'] = { CHSS, POP, ST_FREEING },
},
['D'] = {
['r'] = { CHSS, PUSH, ST_DEP_REG },
['R'] = { CHSS, POP, ST_DEP_REG },
['u'] = { CHSS, PUSH, ST_DEP_UNREG },
['U'] = { CHSS, POP, ST_DEP_UNREG },
},
['S'] = {
['['] = { CHSS, PUSH, ST_SCHED_SERVING },
[']'] = { CHSS, POP, ST_SCHED_SERVING },
['a'] = { CHSS, PUSH, ST_SCHED_ADDING },
['A'] = { CHSS, POP, ST_SCHED_ADDING },
['p'] = { CHSS, PUSH, ST_SCHED_PROCESSING },
['P'] = { CHSS, POP, ST_SCHED_PROCESSING },
['@'] = { CHSS, IGN, -1 },
['r'] = { CHSS, IGN, -1 },
['s'] = { CHSS, IGN, -1 },
},
['B'] = {
['b'] = { CHSS, PUSH, ST_BLK_BLOCKING },
['B'] = { CHSS, POP, ST_BLK_BLOCKING },
['u'] = { CHSS, PUSH, ST_BLK_UNBLOCKING },
['U'] = { CHSS, POP, ST_BLK_UNBLOCKING },
['w'] = { CHSS, PUSH, ST_BLK_TASKWAIT },
['W'] = { CHSS, POP, ST_BLK_TASKWAIT },
['f'] = { CHSS, PUSH, ST_BLK_WAITFOR },
['F'] = { CHSS, POP, ST_BLK_WAITFOR },
},
['H'] = {
['e'] = { CHTH, PUSH, ST_TH_EXTERNAL },
['E'] = { CHTH, POP, ST_TH_EXTERNAL },
['w'] = { CHTH, PUSH, ST_TH_WORKER },
['W'] = { CHTH, POP, ST_TH_WORKER },
['l'] = { CHTH, PUSH, ST_TH_LEADER },
['L'] = { CHTH, POP, ST_TH_LEADER },
['m'] = { CHTH, PUSH, ST_TH_MAIN },
['M'] = { CHTH, POP, ST_TH_MAIN },
},
};
static int
simple(struct emu *emu)
{
const int *entry = ss_table[emu->ev->c][emu->ev->v];
int chind = entry[0];
int action = entry[1];
int st = entry[2];
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
struct chan *ch = &th->ch[chind];
if (action == PUSH) {
return chan_push(ch, value_int64(st));
} else if (action == POP) {
return chan_pop(ch, value_int64(st));
} else if (action == IGN) {
return 0; /* do nothing */
} else {
err("unknown Nanos6 subsystem event");
return -1;
}
return 0;
}
static int
chan_task_stopped(struct emu *emu)
{
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
struct value null = value_null();
if (chan_set(&th->ch[CH_TASKID], null) != 0) {
err("chan_set taskid failed");
return -1;
}
if (chan_set(&th->ch[CH_TYPE], null) != 0) {
err("chan_set type failed");
return -1;
}
struct proc *proc = emu->proc;
if (proc->rank >= 0) {
if (chan_set(&th->ch[CH_RANK], null) != 0) {
err("chan_set rank failed");
return -1;
}
}
return 0;
}
static int
chan_task_running(struct emu *emu, struct task *task)
{
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
struct proc *proc = emu->proc;
if (task->id == 0) {
err("task id cannot be 0");
return -1;
}
if (task->type->gid == 0) {
err("task type gid cannot be 0");
return -1;
}
if (chan_set(&th->ch[CH_TASKID], value_int64(task->id)) != 0) {
err("chan_set taskid failed");
return -1;
}
if (chan_set(&th->ch[CH_TYPE], value_int64(task->type->gid)) != 0) {
err("chan_set type failed");
return -1;
}
if (proc->rank >= 0) {
struct value vrank = value_int64(proc->rank + 1);
if (chan_set(&th->ch[CH_RANK], vrank) != 0) {
err("chan_set rank failed");
return -1;
}
}
return 0;
}
static int
chan_task_switch(struct emu *emu,
struct task *prev, struct task *next)
{
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
if (!prev || !next) {
err("cannot switch to or from a NULL task");
return -1;
}
if (prev == next) {
err("cannot switch to the same task");
return -1;
}
if (next->id == 0) {
err("next task id cannot be 0");
return -1;
}
if (next->type->gid == 0) {
err("next task type id cannot be 0");
return -1;
}
if (prev->thread != next->thread) {
err("cannot switch to a task of another thread");
return -1;
}
/* No need to change the rank as we will switch to tasks from
* same thread */
if (chan_set(&th->ch[CH_TASKID], value_int64(next->id)) != 0) {
err("chan_set taskid failed");
return -1;
}
/* TODO: test when switching to another task with the same type. We
* should emit the same type state value as previous task. */
if (chan_set(&th->ch[CH_TYPE], value_int64(next->type->gid)) != 0) {
err("chan_set type failed");
return -1;
}
return 0;
}
static int
update_task_state(struct emu *emu)
{
if (emu->ev->payload_size < 4) {
err("missing task id in payload");
return -1;
}
uint32_t task_id = emu->ev->payload->u32[0];
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
struct nanos6_proc *proc = extend_get(&emu->proc->ext, '6');
struct task_info *info = &proc->task_info;
struct task_stack *stack = &th->task_stack;
struct task *task = task_find(info->tasks, task_id);
if (task == NULL) {
err("cannot find task with id %u", task_id);
return -1;
}
int ret = 0;
switch (emu->ev->v) {
case 'x':
ret = task_execute(stack, task);
break;
case 'e':
ret = task_end(stack, task);
break;
case 'p':
ret = task_pause(stack, task);
break;
case 'r':
ret = task_resume(stack, task);
break;
default:
err("unexpected Nanos6 task event");
return -1;
}
if (ret != 0) {
err("cannot change task state");
return -1;
}
return 0;
}
static int
expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr_p)
{
char tr = emu->ev->v;
/* Ensure we don't clobber the value */
if (tr == 'X' || tr == 'E') {
err("unexpected event value %c", tr);
return -1;
}
/* Modify the event value to detect nested transitions */
if (tr == 'x' && was_running)
tr = 'X'; /* Execute a new nested task */
else if (tr == 'e' && runs_now)
tr = 'E'; /* End a nested task */
*tr_p = tr;
return 0;
}
static int
update_task_channels(struct emu *emu,
char tr, struct task *prev, struct task *next)
{
int ret = 0;
switch (tr) {
case 'x':
case 'r':
ret = chan_task_running(emu, next);
break;
case 'e':
case 'p':
ret = chan_task_stopped(emu);
break;
/* Additional nested transitions */
case 'X':
case 'E':
ret = chan_task_switch(emu, prev, next);
break;
default:
err("unexpected transition value %c", tr);
return -1;
}
if (ret != 0) {
err("cannot update task channels");
return -1;
}
return 0;
}
static int
enforce_task_rules(struct emu *emu, char tr, struct task *next)
{
if (tr != 'x' && tr != 'X')
return 0;
/* If a task has just entered the running state, it must show
* the running task body subsystem */
if (next->state != TASK_ST_RUNNING) {
err("task not in running state on begin");
return -1;
}
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
struct value ss;
if (chan_read(&th->ch[CH_SUBSYSTEM], &ss) != 0) {
err("chan_read failed");
return -1;
}
if (ss.type == VALUE_INT64 && ss.i != ST_TASK_BODY) {
err("wrong subsystem state on task begin");
//return -1;
return 0; // FIXME
}
return 0;
}
static int
update_task(struct emu *emu)
{
struct nanos6_thread *th = extend_get(&emu->thread->ext, '6');
struct task_stack *stack = &th->task_stack;
struct task *prev = task_get_running(stack);
/* Update the emulator state, but don't modify the channels */
if (update_task_state(emu) != 0) {
err("update_task_state failed");
return -1;
}
struct task *next = task_get_running(stack);
int was_running = (prev != NULL);
int runs_now = (next != NULL);
char tr;
if (expand_transition_value(emu, was_running, runs_now, &tr) != 0) {
err("expand_transition_value failed");
return -1;
}
/* Update the task related channels now */
update_task_channels(emu, tr, prev, next);
if (enforce_task_rules(emu, tr, next) != 0) {
err("enforce_task_rules failed");
return -1;
}
return 0;
}
static int
create_task(struct emu *emu)
{
if (emu->ev->payload_size != 8) {
err("unexpected payload size");
return -1;
}
uint32_t task_id = emu->ev->payload->u32[0];
uint32_t type_id = emu->ev->payload->u32[1];
struct nanos6_proc *proc = extend_get(&emu->proc->ext, '6');
struct task_info *info = &proc->task_info;
if (task_create(info, type_id, task_id) != 0) {
err("task_create failed");
return -1;
}
return 0;
}
static int
pre_task(struct emu *emu)
{
int ret = 0;
switch (emu->ev->v) {
case 'C':
err("warning: got old 6TC event, ignoring");
break;
case 'c':
ret = create_task(emu);
break;
case 'x':
case 'e':
case 'r':
case 'p':
ret = update_task(emu);
break;
default:
err("unexpected Nanos6 task event value");
return -1;
}
if (ret != 0) {
err("cannot update task state");
return -1;
}
return 0;
}
static int
pre_type(struct emu *emu)
{
uint8_t value = emu->ev->v;
if (value != 'c') {
err("unexpected event value %c", value);
return -1;
}
if (!emu->ev->is_jumbo) {
err("expecting a jumbo event");
return -1;
}
const uint8_t *data = &emu->ev->payload->jumbo.data[0];
uint32_t typeid = *(uint32_t *) data;
data += 4;
const char *label = (const char *) data;
struct nanos6_proc *proc = extend_get(&emu->proc->ext, '6');
struct task_info *info = &proc->task_info;
if (task_type_create(info, typeid, label) != 0) {
err("task_type_create failed");
return -1;
}
return 0;
}
static int
process_ev(struct emu *emu)
{
if (!emu->thread->is_active) {
err("current thread %d not active", emu->thread->tid);
return -1;
}
switch (emu->ev->c) {
case 'C':
case 'S':
case 'U':
case 'F':
case 'O':
case 't':
case 'H':
case 'D':
case 'B':
case 'W':
return simple(emu);
case 'T':
return pre_task(emu);
case 'Y':
return pre_type(emu);
default:
err("unknown Nanos6 event category");
return -1;
}
/* Not reached */
return 0;
}
int
nanos6_event(struct emu *emu)
{
if (emu->ev->m != '6') {
err("unexpected event model %c\n", emu->ev->m);
return -1;
}
dbg("got nanos6 event %s", emu->ev->mcv);
if (process_ev(emu) != 0) {
err("error processing Nanos6 event");
return -1;
}
//check_affinity(emu);
return 0;
}

View File

@ -1,69 +0,0 @@
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef OVNI_MODEL_H
#define OVNI_MODEL_H
#include "ovni/ovni_model.h"
#include "chan.h"
/* The values of nanos6_ss_state are synced to the previous
* CTF implementation. */
enum nanos6_ss_state {
ST_NANOS6_TASK_BODY = 1,
ST_NANOS6_TASK_CREATING,
ST_NANOS6_TASK_SUBMIT,
ST_NANOS6_TASK_SPAWNING,
ST_NANOS6_TASK_FOR,
ST_NANOS6_SCHED_ADDING,
ST_NANOS6_SCHED_PROCESSING,
ST_NANOS6_SCHED_SERVING,
ST_NANOS6_DEP_REG,
ST_NANOS6_DEP_UNREG,
ST_NANOS6_BLK_TASKWAIT,
ST_NANOS6_BLK_WAITFOR,
ST_NANOS6_BLK_BLOCKING,
ST_NANOS6_BLK_UNBLOCKING,
ST_NANOS6_ALLOCATING,
ST_NANOS6_FREEING,
ST_NANOS6_HANDLING_TASK,
ST_NANOS6_WORKER_LOOP,
ST_NANOS6_SWITCH_TO,
ST_NANOS6_MIGRATE,
ST_NANOS6_SUSPEND,
ST_NANOS6_RESUME,
/* Value 51 is broken in old Paraver */
EV_NANOS6_SCHED_RECV = 60,
EV_NANOS6_SCHED_SEND,
EV_NANOS6_SCHED_SELF,
EV_NANOS6_CPU_IDLE,
EV_NANOS6_CPU_ACTIVE,
EV_NANOS6_SIGNAL,
};
enum nanos6_thread_type {
ST_NANOS6_TH_LEADER = 1,
ST_NANOS6_TH_MAIN = 2,
ST_NANOS6_TH_WORKER = 3,
ST_NANOS6_TH_EXTERNAL = 4,
};
struct nanos6_thread {
struct task_stack nanos6_task_stack;
};
struct nanos6_proc {
struct task_info nanos6_task_info;
};
struct nanos6_emu {
struct ovni_emu *ovni;
};
int nanos6_model_probe(struct emu *emu);
int nanos6_model_create(struct emu *emu);
int nanos6_model_connect(struct emu *emu);
int nanos6_model_event(struct emu *emu);
#endif /* OVNI_MODEL_H */

View File

@ -0,0 +1,86 @@
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef NANOS6_PRIV_H
#define NANOS6_PRIV_H
#include "emu.h"
#include "chan.h"
#include "mux.h"
#include "task.h"
/* Private enums */
enum nanos6_chan_type {
CH_TASKID = 0,
CH_TYPE,
CH_SUBSYSTEM,
CH_RANK,
CH_THREAD,
CH_MAX,
};
enum nanos6_ss_state {
ST_TASK_BODY = 1,
ST_TASK_CREATING,
ST_TASK_SUBMIT,
ST_TASK_SPAWNING,
ST_TASK_FOR,
ST_SCHED_ADDING,
ST_SCHED_PROCESSING,
ST_SCHED_SERVING,
ST_DEP_REG,
ST_DEP_UNREG,
ST_BLK_TASKWAIT,
ST_BLK_WAITFOR,
ST_BLK_BLOCKING,
ST_BLK_UNBLOCKING,
ST_ALLOCATING,
ST_FREEING,
ST_HANDLING_TASK,
ST_WORKER_LOOP,
ST_SWITCH_TO,
ST_MIGRATE,
ST_SUSPEND,
ST_RESUME,
/* Value 51 is broken in old Paraver */
EV_SCHED_RECV = 60,
EV_SCHED_SEND,
EV_SCHED_SELF,
EV_CPU_IDLE,
EV_CPU_ACTIVE,
EV_SIGNAL,
};
enum nanos6_thread_type {
ST_TH_LEADER = 1,
ST_TH_MAIN = 2,
ST_TH_WORKER = 3,
ST_TH_EXTERNAL = 4,
};
struct nanos6_thread {
struct chan *ch; /* Raw, modified by nanos6 */
struct chan *ch_run; /* Tracking running thread */
struct chan *ch_act; /* Tracking active thread */
struct chan **ch_out; /* Output to PRV */
struct mux *mux_run;
struct mux *mux_act;
struct task_stack task_stack;
};
struct nanos6_cpu {
struct chan *ch;
struct mux *mux;
};
struct nanos6_proc {
struct task_info task_info;
};
int nanos6_probe(struct emu *emu);
int nanos6_create(struct emu *emu);
int nanos6_connect(struct emu *emu);
int nanos6_event(struct emu *emu);
#endif /* NANOS6_PRIV_H */

19
src/emu/nanos6/probe.c Normal file
View File

@ -0,0 +1,19 @@
#include "nanos6_priv.h"
struct model_spec model_nanos6 = {
.name = "nanos6",
.model = '6',
.create = nanos6_create,
.connect = nanos6_connect,
.event = nanos6_event,
.probe = nanos6_probe,
};
int
nanos6_probe(struct emu *emu)
{
if (emu->system.nthreads == 0)
return -1;
return 0;
}

View File

@ -1,23 +1,35 @@
#include "emu.h"
#include <stdlib.h>
#include "common.h"
int
main(int argc, char *argv[])
{
struct ovni_emu *emu = malloc(sizeof(struct ovni_emu));
progname_set("ovniemu");
struct emu *emu = calloc(1, sizeof(struct emu));
if (emu == NULL) {
perror("malloc");
err("malloc failed:");
return 1;
}
emu_init(emu, argc, argv);
if (emu_init(emu, argc, argv) != 0)
die("emu_init failed\n");
if (emu_connect(emu) != 0)
die("emu_connect failed\n");
err("emulation starts\n");
emu_run(emu);
emu_post(emu);
emu_destroy(emu);
int ret = 0;
while ((ret = emu_step(emu)) == 0);
if (ret < 0)
die("emu_step failed\n");
err("emulation ends\n");
free(emu);
return 0;

View File

@ -84,7 +84,7 @@ proc_init_begin(struct proc *proc, const char *relpath)
return -1;
}
err("created proc %s", proc->id);
dbg("created proc %s", proc->id);
return 0;
}

View File

@ -1,7 +1,7 @@
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#define ENABLE_DEBUG
//#define ENABLE_DEBUG
#include "prv.h"
#include <stdio.h>

View File

@ -515,6 +515,7 @@ system_init(struct system *sys, struct emu_args *args, struct emu_trace *trace)
}
/* Finaly dump the system */
if (0)
print_system(sys);
return 0;