Add support for nOS-V
Most of the model is taken from nanos6, we should refactor them.
This commit is contained in:
parent
55a5be7d13
commit
a818795d88
@ -45,6 +45,12 @@ add_library(emu STATIC
|
|||||||
nanos6/event.c
|
nanos6/event.c
|
||||||
nanos6/pvt.c
|
nanos6/pvt.c
|
||||||
nanos6/finish.c
|
nanos6/finish.c
|
||||||
|
nosv/probe.c
|
||||||
|
nosv/connect.c
|
||||||
|
nosv/create.c
|
||||||
|
nosv/event.c
|
||||||
|
nosv/pvt.c
|
||||||
|
nosv/finish.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(ovniemu ovniemu.c)
|
add_executable(ovniemu ovniemu.c)
|
||||||
|
@ -30,11 +30,12 @@ static int chan_type[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
cpu_init_begin(struct cpu *cpu, int phyid)
|
cpu_init_begin(struct cpu *cpu, int phyid, int is_virtual)
|
||||||
{
|
{
|
||||||
memset(cpu, 0, sizeof(struct cpu));
|
memset(cpu, 0, sizeof(struct cpu));
|
||||||
|
|
||||||
cpu->phyid = phyid;
|
cpu->phyid = phyid;
|
||||||
|
cpu->is_virtual = is_virtual;
|
||||||
|
|
||||||
dbg("cpu init %d", phyid);
|
dbg("cpu init %d", phyid);
|
||||||
}
|
}
|
||||||
@ -166,6 +167,13 @@ cpu_update(struct cpu *cpu)
|
|||||||
cpu->nth_running = running;
|
cpu->nth_running = running;
|
||||||
cpu->nth_active = active;
|
cpu->nth_active = active;
|
||||||
|
|
||||||
|
/* Only virtual cpus can be oversubscribed */
|
||||||
|
if (cpu->nth_running > 1 && !cpu->is_virtual) {
|
||||||
|
err("physical cpu %s has %d thread running at the same time",
|
||||||
|
cpu->name, cpu->nth_running);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
struct value tid_running;
|
struct value tid_running;
|
||||||
struct value pid_running;
|
struct value pid_running;
|
||||||
struct value gid_running;
|
struct value gid_running;
|
||||||
|
@ -61,7 +61,7 @@ struct cpu {
|
|||||||
UT_hash_handle hh; /* CPUs in the loom */
|
UT_hash_handle hh; /* CPUs in the loom */
|
||||||
};
|
};
|
||||||
|
|
||||||
void cpu_init_begin(struct cpu *cpu, int phyid);
|
void cpu_init_begin(struct cpu *cpu, int phyid, int is_virtual);
|
||||||
int cpu_get_phyid(struct cpu *cpu);
|
int cpu_get_phyid(struct cpu *cpu);
|
||||||
//int cpu_get_index(struct cpu *cpu);
|
//int cpu_get_index(struct cpu *cpu);
|
||||||
void cpu_set_gindex(struct cpu *cpu, int64_t gindex);
|
void cpu_set_gindex(struct cpu *cpu, int64_t gindex);
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define _POSIX_C_SOURCE 2
|
#define _POSIX_C_SOURCE 2
|
||||||
|
|
||||||
//#define ENABLE_DEBUG
|
#define ENABLE_DEBUG
|
||||||
|
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ loom_init_begin(struct loom *loom, const char *name)
|
|||||||
set_hostname(loom->hostname, loom->name);
|
set_hostname(loom->hostname, loom->name);
|
||||||
loom->id = loom->name;
|
loom->id = loom->name;
|
||||||
|
|
||||||
cpu_init_begin(&loom->vcpu, -1);
|
cpu_init_begin(&loom->vcpu, -1, 1);
|
||||||
|
|
||||||
dbg("creating new loom %s", loom->id);
|
dbg("creating new loom %s", loom->id);
|
||||||
|
|
||||||
|
@ -105,7 +105,7 @@ load_cpus(struct loom *loom, JSON_Object *meta)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
cpu_init_begin(cpu, phyid);
|
cpu_init_begin(cpu, phyid, 0);
|
||||||
|
|
||||||
if (loom_add_cpu(loom, cpu) != 0) {
|
if (loom_add_cpu(loom, cpu) != 0) {
|
||||||
err("loom_add_cpu() failed");
|
err("loom_add_cpu() failed");
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later */
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG
|
||||||
|
|
||||||
#include "model.h"
|
#include "model.h"
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
@ -18,6 +20,8 @@ model_register(struct model *model, struct model_spec *spec)
|
|||||||
int i = spec->model;
|
int i = spec->model;
|
||||||
model->spec[i] = spec;
|
model->spec[i] = spec;
|
||||||
model->registered[i] = 1;
|
model->registered[i] = 1;
|
||||||
|
|
||||||
|
dbg("registered model %c", (char) i);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -37,8 +41,12 @@ model_probe(struct model *model, struct emu *emu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == 0)
|
if (ret == 0) {
|
||||||
model->enabled[i] = 1;
|
model->enabled[i] = 1;
|
||||||
|
dbg("model %c enabled", (char) i);
|
||||||
|
} else {
|
||||||
|
dbg("model %c disabled", (char) i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -77,6 +85,8 @@ model_connect(struct model *model, struct emu *emu)
|
|||||||
err("connect failed for model '%c'", (char) i);
|
err("connect failed for model '%c'", (char) i);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dbg("connect for model %c ok", (char) i);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -7,10 +7,12 @@
|
|||||||
|
|
||||||
extern struct model_spec model_ovni;
|
extern struct model_spec model_ovni;
|
||||||
extern struct model_spec model_nanos6;
|
extern struct model_spec model_nanos6;
|
||||||
|
extern struct model_spec model_nosv;
|
||||||
|
|
||||||
static struct model_spec *models[] = {
|
static struct model_spec *models[] = {
|
||||||
&model_ovni,
|
&model_ovni,
|
||||||
&model_nanos6,
|
&model_nanos6,
|
||||||
|
&model_nosv,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "nanos6_priv.h"
|
#include "nanos6_priv.h"
|
||||||
|
|
||||||
const enum nanos6_track chan_track[CH_MAX][CT_MAX] = {
|
const enum nanos6_track nanos6_chan_track[CH_MAX][CT_MAX] = {
|
||||||
/* Thread CPU */
|
/* Thread CPU */
|
||||||
[CH_TASKID] = { RUN_TH, RUN_TH },
|
[CH_TASKID] = { RUN_TH, RUN_TH },
|
||||||
[CH_TYPE] = { RUN_TH, RUN_TH },
|
[CH_TYPE] = { RUN_TH, RUN_TH },
|
||||||
@ -49,7 +49,7 @@ connect_thread_mux(struct emu *emu, struct thread *thread)
|
|||||||
|
|
||||||
/* The tracking only sets the ch_out, but we keep both tracking
|
/* The tracking only sets the ch_out, but we keep both tracking
|
||||||
* updated as the CPU tracking channels may use them. */
|
* updated as the CPU tracking channels may use them. */
|
||||||
enum nanos6_track track = chan_track[i][CT_TH];
|
enum nanos6_track track = nanos6_chan_track[i][CT_TH];
|
||||||
if (track == RUN_TH)
|
if (track == RUN_TH)
|
||||||
th->ch_out[i] = &th->ch_run[i];
|
th->ch_out[i] = &th->ch_run[i];
|
||||||
else if (track == ACT_TH)
|
else if (track == ACT_TH)
|
||||||
@ -70,7 +70,7 @@ add_inputs_cpu_mux(struct emu *emu, struct mux *mux, int i)
|
|||||||
|
|
||||||
/* Choose input thread channel based on tracking mode */
|
/* Choose input thread channel based on tracking mode */
|
||||||
struct chan *inp = NULL;
|
struct chan *inp = NULL;
|
||||||
enum nanos6_track track = chan_track[i][CT_CPU];
|
enum nanos6_track track = nanos6_chan_track[i][CT_CPU];
|
||||||
if (track == RUN_TH)
|
if (track == RUN_TH)
|
||||||
inp = &th->ch_run[i];
|
inp = &th->ch_run[i];
|
||||||
else if (track == ACT_TH)
|
else if (track == ACT_TH)
|
||||||
@ -97,7 +97,7 @@ connect_cpu_mux(struct emu *emu, struct cpu *scpu)
|
|||||||
|
|
||||||
/* Choose select CPU channel based on tracking mode */
|
/* Choose select CPU channel based on tracking mode */
|
||||||
struct chan *sel = NULL;
|
struct chan *sel = NULL;
|
||||||
enum nanos6_track track = chan_track[i][CT_CPU];
|
enum nanos6_track track = nanos6_chan_track[i][CT_CPU];
|
||||||
if (track == RUN_TH)
|
if (track == RUN_TH)
|
||||||
sel = &scpu->chan[CPU_CHAN_THRUN];
|
sel = &scpu->chan[CPU_CHAN_THRUN];
|
||||||
else if (track == ACT_TH)
|
else if (track == ACT_TH)
|
||||||
@ -140,7 +140,7 @@ nanos6_connect(struct emu *emu)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (init_pvt(emu) != 0) {
|
if (nanos6_init_pvt(emu) != 0) {
|
||||||
err("init_pvt failed");
|
err("init_pvt failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ 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_run[] = "nanos6.thread%ld.%s.run";
|
||||||
static const char chan_fmt_th_act[] = "nanos6.thread%ld.%s.act";
|
static const char chan_fmt_th_act[] = "nanos6.thread%ld.%s.act";
|
||||||
|
|
||||||
static const char *chan_name[] = {
|
static const char *chan_name[CH_MAX] = {
|
||||||
[CH_TASKID] = "taskid",
|
[CH_TASKID] = "taskid",
|
||||||
[CH_TYPE] = "task_type",
|
[CH_TYPE] = "task_type",
|
||||||
[CH_SUBSYSTEM] = "subsystem",
|
[CH_SUBSYSTEM] = "subsystem",
|
||||||
@ -15,7 +15,7 @@ static const char *chan_name[] = {
|
|||||||
[CH_THREAD] = "thread_type",
|
[CH_THREAD] = "thread_type",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int chan_stack[] = {
|
static const int chan_stack[CH_MAX] = {
|
||||||
[CH_SUBSYSTEM] = 1,
|
[CH_SUBSYSTEM] = 1,
|
||||||
[CH_THREAD] = 1,
|
[CH_THREAD] = 1,
|
||||||
};
|
};
|
||||||
|
@ -520,7 +520,5 @@ nanos6_event(struct emu *emu)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check_affinity(emu);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ end_lint(struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
err("thread %d ended with %d stacked nanos6 subsystems, top=\"%s\"\n",
|
err("thread %d ended with %d stacked nanos6 subsystems, top=\"%s\"\n",
|
||||||
t->tid, stacked, ss_name(top.i));
|
t->tid, stacked, nanos6_ss_name(top.i));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -29,7 +29,7 @@ end_lint(struct emu *emu)
|
|||||||
int
|
int
|
||||||
nanos6_finish(struct emu *emu)
|
nanos6_finish(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (finish_pvt(emu) != 0) {
|
if (nanos6_finish_pvt(emu) != 0) {
|
||||||
err("finish_pvt failed");
|
err("finish_pvt failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ enum nanos6_track {
|
|||||||
TRACK_MAX,
|
TRACK_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
extern const enum nanos6_track chan_track[CH_MAX][CT_MAX];
|
extern const enum nanos6_track nanos6_chan_track[CH_MAX][CT_MAX];
|
||||||
|
|
||||||
enum nanos6_ss_state {
|
enum nanos6_ss_state {
|
||||||
ST_TASK_BODY = 1,
|
ST_TASK_BODY = 1,
|
||||||
@ -100,8 +100,8 @@ int nanos6_connect(struct emu *emu);
|
|||||||
int nanos6_event(struct emu *emu);
|
int nanos6_event(struct emu *emu);
|
||||||
int nanos6_finish(struct emu *emu);
|
int nanos6_finish(struct emu *emu);
|
||||||
|
|
||||||
int init_pvt(struct emu *emu);
|
int nanos6_init_pvt(struct emu *emu);
|
||||||
int finish_pvt(struct emu *emu);
|
int nanos6_finish_pvt(struct emu *emu);
|
||||||
const char *ss_name(int ss);
|
const char *nanos6_ss_name(int ss);
|
||||||
|
|
||||||
#endif /* NANOS6_PRIV_H */
|
#endif /* NANOS6_PRIV_H */
|
||||||
|
@ -101,7 +101,7 @@ create_type(struct pcf *pcf, enum nanos6_chan c, enum nanos6_chan_type ct)
|
|||||||
|
|
||||||
/* Compute the label by joining the two parts */
|
/* Compute the label by joining the two parts */
|
||||||
const char *prefix = pcf_prefix[c];
|
const char *prefix = pcf_prefix[c];
|
||||||
int track_mode = chan_track[c][ct];
|
int track_mode = nanos6_chan_track[c][ct];
|
||||||
const char *suffix = pcf_suffix[track_mode];
|
const char *suffix = pcf_suffix[track_mode];
|
||||||
|
|
||||||
char label[MAX_PCF_LABEL];
|
char label[MAX_PCF_LABEL];
|
||||||
@ -232,7 +232,7 @@ connect_cpus(struct emu *emu)
|
|||||||
|
|
||||||
/* Connect all outputs to the paraver trace and setup PCF types */
|
/* Connect all outputs to the paraver trace and setup PCF types */
|
||||||
int
|
int
|
||||||
init_pvt(struct emu *emu)
|
nanos6_init_pvt(struct emu *emu)
|
||||||
{
|
{
|
||||||
if (connect_threads(emu) != 0) {
|
if (connect_threads(emu) != 0) {
|
||||||
err("connect_threads failed");
|
err("connect_threads failed");
|
||||||
@ -248,7 +248,7 @@ init_pvt(struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
finish_pvt(struct emu *emu)
|
nanos6_finish_pvt(struct emu *emu)
|
||||||
{
|
{
|
||||||
struct system *sys = &emu->system;
|
struct system *sys = &emu->system;
|
||||||
|
|
||||||
@ -277,7 +277,7 @@ finish_pvt(struct emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
ss_name(int ss)
|
nanos6_ss_name(int ss)
|
||||||
{
|
{
|
||||||
static const char *unknown = "(unknown)";
|
static const char *unknown = "(unknown)";
|
||||||
const char *name = unknown;
|
const char *name = unknown;
|
||||||
|
150
src/emu/nosv/connect.c
Normal file
150
src/emu/nosv/connect.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include "nosv_priv.h"
|
||||||
|
|
||||||
|
const enum nosv_track nosv_chan_track[CH_MAX][CT_MAX] = {
|
||||||
|
/* Thread CPU */
|
||||||
|
[CH_TASKID] = { RUN_TH, RUN_TH },
|
||||||
|
[CH_TYPE] = { RUN_TH, RUN_TH },
|
||||||
|
[CH_APPID] = { RUN_TH, RUN_TH },
|
||||||
|
[CH_SUBSYSTEM] = { ACT_TH, RUN_TH },
|
||||||
|
[CH_RANK] = { RUN_TH, RUN_TH },
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
connect_thread_mux(struct emu *emu, struct thread *thread)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = EXT(thread, 'V');
|
||||||
|
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. */
|
||||||
|
enum nosv_track track = nosv_chan_track[i][CT_TH];
|
||||||
|
if (track == RUN_TH)
|
||||||
|
th->ch_out[i] = &th->ch_run[i];
|
||||||
|
else if (track == ACT_TH)
|
||||||
|
th->ch_out[i] = &th->ch_act[i];
|
||||||
|
else
|
||||||
|
th->ch_out[i] = &th->ch[i];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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 nosv_thread *th = EXT(t, 'V');
|
||||||
|
|
||||||
|
/* Choose input thread channel based on tracking mode */
|
||||||
|
struct chan *inp = NULL;
|
||||||
|
enum nosv_track track = nosv_chan_track[i][CT_CPU];
|
||||||
|
if (track == RUN_TH)
|
||||||
|
inp = &th->ch_run[i];
|
||||||
|
else if (track == ACT_TH)
|
||||||
|
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 nosv_cpu *cpu = EXT(scpu, 'V');
|
||||||
|
for (int i = 0; i < CH_MAX; i++) {
|
||||||
|
struct mux *mux = &cpu->mux[i];
|
||||||
|
struct chan *out = &cpu->ch[i];
|
||||||
|
|
||||||
|
/* Choose select CPU channel based on tracking mode */
|
||||||
|
struct chan *sel = NULL;
|
||||||
|
enum nosv_track track = nosv_chan_track[i][CT_CPU];
|
||||||
|
if (track == RUN_TH)
|
||||||
|
sel = &scpu->chan[CPU_CHAN_THRUN];
|
||||||
|
else if (track == ACT_TH)
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nosv_connect(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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nosv_init_pvt(emu) != 0) {
|
||||||
|
err("init_pvt failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
179
src/emu/nosv/create.c
Normal file
179
src/emu/nosv/create.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#include "nosv_priv.h"
|
||||||
|
|
||||||
|
static const char chan_fmt_cpu_raw[] = "nosv.cpu%ld.%s";
|
||||||
|
//static const char chan_fmt_cpu_run[] = "nosv.cpu%ld.%s.run";
|
||||||
|
//static const char chan_fmt_cpu_act[] = "nosv.cpu%ld.%s.act";
|
||||||
|
static const char chan_fmt_th_raw[] = "nosv.thread%ld.%s.raw";
|
||||||
|
static const char chan_fmt_th_run[] = "nosv.thread%ld.%s.run";
|
||||||
|
static const char chan_fmt_th_act[] = "nosv.thread%ld.%s.act";
|
||||||
|
|
||||||
|
static const char *chan_name[CH_MAX] = {
|
||||||
|
[CH_TASKID] = "taskid",
|
||||||
|
[CH_TYPE] = "task_type",
|
||||||
|
[CH_APPID] = "appid",
|
||||||
|
[CH_SUBSYSTEM] = "subsystem",
|
||||||
|
[CH_RANK] = "rank",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int chan_stack[CH_MAX] = {
|
||||||
|
[CH_SUBSYSTEM] = 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 nosv_cpu *cpu = calloc(1, sizeof(struct nosv_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, 'V', cpu);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_thread(struct bay *bay, struct thread *systh)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = calloc(1, sizeof(struct nosv_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, 'V', th);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_proc(struct proc *sysproc)
|
||||||
|
{
|
||||||
|
struct nosv_proc *proc = calloc(1, sizeof(struct nosv_proc));
|
||||||
|
if (proc == NULL) {
|
||||||
|
err("calloc failed:");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend_set(&sysproc->ext, 'V', proc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nosv_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;
|
||||||
|
}
|
501
src/emu/nosv/event.c
Normal file
501
src/emu/nosv/event.c
Normal file
@ -0,0 +1,501 @@
|
|||||||
|
#include "nosv_priv.h"
|
||||||
|
|
||||||
|
enum { PUSH = 1, POP = 2, IGN = 3 };
|
||||||
|
|
||||||
|
#define CHSS CH_SUBSYSTEM
|
||||||
|
|
||||||
|
static const int ss_table[256][256][3] = {
|
||||||
|
['S'] = {
|
||||||
|
['h'] = { CHSS, PUSH, ST_SCHED_HUNGRY },
|
||||||
|
['f'] = { CHSS, POP, ST_SCHED_HUNGRY },
|
||||||
|
['['] = { CHSS, PUSH, ST_SCHED_SERVING },
|
||||||
|
[']'] = { CHSS, POP, ST_SCHED_SERVING },
|
||||||
|
['@'] = { CHSS, IGN, -1 },
|
||||||
|
['r'] = { CHSS, IGN, -1 },
|
||||||
|
['s'] = { CHSS, IGN, -1 },
|
||||||
|
},
|
||||||
|
['U'] = {
|
||||||
|
['['] = { CHSS, PUSH, ST_SCHED_SUBMITTING },
|
||||||
|
[']'] = { CHSS, POP, ST_SCHED_SUBMITTING },
|
||||||
|
},
|
||||||
|
['M'] = {
|
||||||
|
['a'] = { CHSS, PUSH, ST_MEM_ALLOCATING },
|
||||||
|
['A'] = { CHSS, POP, ST_MEM_ALLOCATING },
|
||||||
|
['f'] = { CHSS, PUSH, ST_MEM_FREEING },
|
||||||
|
['F'] = { CHSS, POP, ST_MEM_FREEING },
|
||||||
|
},
|
||||||
|
['A'] = {
|
||||||
|
['s'] = { CHSS, PUSH, ST_API_SUBMIT },
|
||||||
|
['S'] = { CHSS, POP, ST_API_SUBMIT },
|
||||||
|
['p'] = { CHSS, PUSH, ST_API_PAUSE },
|
||||||
|
['P'] = { CHSS, POP, ST_API_PAUSE },
|
||||||
|
['y'] = { CHSS, PUSH, ST_API_YIELD },
|
||||||
|
['Y'] = { CHSS, POP, ST_API_YIELD },
|
||||||
|
['w'] = { CHSS, PUSH, ST_API_WAITFOR },
|
||||||
|
['W'] = { CHSS, POP, ST_API_WAITFOR },
|
||||||
|
['c'] = { CHSS, PUSH, ST_API_SCHEDPOINT },
|
||||||
|
['C'] = { CHSS, POP, ST_API_SCHEDPOINT },
|
||||||
|
},
|
||||||
|
/* FIXME: Move thread type to another channel, like nanos6 */
|
||||||
|
['H'] = {
|
||||||
|
['a'] = { CHSS, PUSH, ST_ATTACH },
|
||||||
|
['A'] = { CHSS, POP, ST_ATTACH },
|
||||||
|
['w'] = { CHSS, PUSH, ST_WORKER },
|
||||||
|
['W'] = { CHSS, POP, ST_WORKER },
|
||||||
|
['d'] = { CHSS, PUSH, ST_DELEGATE },
|
||||||
|
['D'] = { CHSS, POP, ST_DELEGATE },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
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 nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
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 nOS-V subsystem event");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
chan_task_stopped(struct emu *emu)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (chan_set(&th->ch[CH_APPID], null) != 0) {
|
||||||
|
err("chan_set appid 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Do we need this transition? */
|
||||||
|
if (chan_pop(&th->ch[CH_SUBSYSTEM], value_int64(ST_TASK_RUNNING)) != 0) {
|
||||||
|
err("chan_pop subsystem failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
chan_task_running(struct emu *emu, struct task *task)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
struct proc *proc = emu->proc;
|
||||||
|
struct chan *ch = th->ch;
|
||||||
|
|
||||||
|
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 (proc->appid <= 0) {
|
||||||
|
err("app id must be positive");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chan_set(&ch[CH_TASKID], value_int64(task->id)) != 0) {
|
||||||
|
err("chan_set taskid failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (chan_set(&ch[CH_TYPE], value_int64(task->type->gid)) != 0) {
|
||||||
|
err("chan_set type failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (chan_set(&ch[CH_APPID], value_int64(proc->appid)) != 0) {
|
||||||
|
err("chan_set appid failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (proc->rank >= 0) {
|
||||||
|
struct value vrank = value_int64(proc->rank + 1);
|
||||||
|
if (chan_set(&ch[CH_RANK], vrank) != 0) {
|
||||||
|
err("chan_set rank failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan_push(&ch[CH_SUBSYSTEM], value_int64(ST_TASK_RUNNING)) != 0) {
|
||||||
|
err("chan_push subsystem failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
chan_task_switch(struct emu *emu,
|
||||||
|
struct task *prev, struct task *next)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
|
||||||
|
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 or app ID 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 nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
struct nosv_proc *proc = EXT(emu->proc, 'V');
|
||||||
|
|
||||||
|
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 nOS-V 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 nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
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_RUNNING) {
|
||||||
|
err("wrong subsystem state on task begin");
|
||||||
|
//return -1;
|
||||||
|
return 0; // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
update_task(struct emu *emu)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = EXT(emu->thread, 'V');
|
||||||
|
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 nosv_proc *proc = EXT(emu->proc, 'V');
|
||||||
|
struct task_info *info = &proc->task_info;
|
||||||
|
|
||||||
|
if (task_create(info, type_id, task_id) != 0) {
|
||||||
|
err("task_create failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("task created with taskid %u", task_id);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pre_task(struct emu *emu)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
switch (emu->ev->v) {
|
||||||
|
case 'c':
|
||||||
|
ret = create_task(emu);
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
case 'e':
|
||||||
|
case 'r':
|
||||||
|
case 'p':
|
||||||
|
ret = update_task(emu);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
err("unexpected nOS-V 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 nosv_proc *proc = EXT(emu->proc, 'V');
|
||||||
|
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 'S':
|
||||||
|
case 'U':
|
||||||
|
case 'M':
|
||||||
|
case 'H':
|
||||||
|
case 'A':
|
||||||
|
return simple(emu);
|
||||||
|
case 'T':
|
||||||
|
return pre_task(emu);
|
||||||
|
case 'Y':
|
||||||
|
return pre_type(emu);
|
||||||
|
default:
|
||||||
|
err("unknown nOS-V event category");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Not reached */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nosv_event(struct emu *emu)
|
||||||
|
{
|
||||||
|
dbg("in nosv_event");
|
||||||
|
if (emu->ev->m != 'V') {
|
||||||
|
err("unexpected event model %c\n", emu->ev->m);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
dbg("got nosv event %s", emu->ev->mcv);
|
||||||
|
if (process_ev(emu) != 0) {
|
||||||
|
err("error processing nOS-V event");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
44
src/emu/nosv/finish.c
Normal file
44
src/emu/nosv/finish.c
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#include "nosv_priv.h"
|
||||||
|
|
||||||
|
static int
|
||||||
|
end_lint(struct emu *emu)
|
||||||
|
{
|
||||||
|
struct system *sys = &emu->system;
|
||||||
|
|
||||||
|
/* Ensure we run out of subsystem states */
|
||||||
|
for (struct thread *t = sys->threads; t; t = t->gnext) {
|
||||||
|
struct nosv_thread *th = EXT(t, 'V');
|
||||||
|
struct chan *ch = &th->ch[CH_SUBSYSTEM];
|
||||||
|
int stacked = ch->data.stack.n;
|
||||||
|
if (stacked > 0) {
|
||||||
|
struct value top;
|
||||||
|
if (chan_read(ch, &top) != 0) {
|
||||||
|
err("chan_read failed for subsystem");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
err("thread %d ended with %d stacked nosv subsystems, top=\"%s\"\n",
|
||||||
|
t->tid, stacked, nosv_ss_name(top.i));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nosv_finish(struct emu *emu)
|
||||||
|
{
|
||||||
|
if (nosv_finish_pvt(emu) != 0) {
|
||||||
|
err("finish_pvt failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* When running in linter mode perform additional checks */
|
||||||
|
if (emu->args.linter_mode && end_lint(emu) != 0) {
|
||||||
|
err("end_lint failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
88
src/emu/nosv/nosv_priv.h
Normal file
88
src/emu/nosv/nosv_priv.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/* Copyright (c) 2023 Barcelona Supercomputing Center (BSC)
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later */
|
||||||
|
|
||||||
|
#ifndef NOSV_PRIV_H
|
||||||
|
#define NOSV_PRIV_H
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "chan.h"
|
||||||
|
#include "mux.h"
|
||||||
|
#include "task.h"
|
||||||
|
|
||||||
|
/* Private enums */
|
||||||
|
|
||||||
|
enum nosv_chan_type {
|
||||||
|
CT_TH = 0,
|
||||||
|
CT_CPU,
|
||||||
|
CT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nosv_chan {
|
||||||
|
CH_TASKID = 0,
|
||||||
|
CH_TYPE,
|
||||||
|
CH_APPID,
|
||||||
|
CH_SUBSYSTEM,
|
||||||
|
CH_RANK,
|
||||||
|
CH_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum nosv_track {
|
||||||
|
NONE = 0,
|
||||||
|
RUN_TH,
|
||||||
|
ACT_TH,
|
||||||
|
TRACK_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
extern const enum nosv_track nosv_chan_track[CH_MAX][CT_MAX];
|
||||||
|
|
||||||
|
enum nosv_ss_values {
|
||||||
|
ST_SCHED_HUNGRY = 6,
|
||||||
|
ST_SCHED_SERVING,
|
||||||
|
ST_SCHED_SUBMITTING,
|
||||||
|
ST_MEM_ALLOCATING,
|
||||||
|
ST_MEM_FREEING,
|
||||||
|
ST_TASK_RUNNING,
|
||||||
|
ST_API_SUBMIT,
|
||||||
|
ST_API_PAUSE,
|
||||||
|
ST_API_YIELD,
|
||||||
|
ST_API_WAITFOR,
|
||||||
|
ST_API_SCHEDPOINT,
|
||||||
|
ST_ATTACH,
|
||||||
|
ST_WORKER,
|
||||||
|
ST_DELEGATE,
|
||||||
|
|
||||||
|
EV_SCHED_RECV,
|
||||||
|
EV_SCHED_SEND,
|
||||||
|
EV_SCHED_SELF,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nosv_thread {
|
||||||
|
struct chan *ch; /* Raw, modified by nosv */
|
||||||
|
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 nosv_cpu {
|
||||||
|
struct chan *ch;
|
||||||
|
struct mux *mux;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct nosv_proc {
|
||||||
|
struct task_info task_info;
|
||||||
|
};
|
||||||
|
|
||||||
|
int nosv_probe(struct emu *emu);
|
||||||
|
int nosv_create(struct emu *emu);
|
||||||
|
int nosv_connect(struct emu *emu);
|
||||||
|
int nosv_event(struct emu *emu);
|
||||||
|
int nosv_finish(struct emu *emu);
|
||||||
|
|
||||||
|
int nosv_init_pvt(struct emu *emu);
|
||||||
|
int nosv_finish_pvt(struct emu *emu);
|
||||||
|
const char *nosv_ss_name(int ss);
|
||||||
|
|
||||||
|
#endif /* NOSV_PRIV_H */
|
20
src/emu/nosv/probe.c
Normal file
20
src/emu/nosv/probe.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include "nosv_priv.h"
|
||||||
|
|
||||||
|
struct model_spec model_nosv = {
|
||||||
|
.name = "nosv",
|
||||||
|
.model = 'V',
|
||||||
|
.create = nosv_create,
|
||||||
|
.connect = nosv_connect,
|
||||||
|
.event = nosv_event,
|
||||||
|
.probe = nosv_probe,
|
||||||
|
.finish = nosv_finish,
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
nosv_probe(struct emu *emu)
|
||||||
|
{
|
||||||
|
if (emu->system.nthreads == 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
273
src/emu/nosv/pvt.c
Normal file
273
src/emu/nosv/pvt.c
Normal file
@ -0,0 +1,273 @@
|
|||||||
|
#include "nosv_priv.h"
|
||||||
|
|
||||||
|
/* TODO: Assign types on runtime and generate configs */
|
||||||
|
|
||||||
|
static const char *pvt_name[CT_MAX] = {
|
||||||
|
[CT_TH] = "thread",
|
||||||
|
[CT_CPU] = "cpu",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const int pvt_type[] = {
|
||||||
|
[CH_TASKID] = 10,
|
||||||
|
[CH_TYPE] = 11,
|
||||||
|
[CH_APPID] = 12,
|
||||||
|
[CH_SUBSYSTEM] = 13,
|
||||||
|
[CH_RANK] = 14,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *pcf_prefix[CH_MAX] = {
|
||||||
|
[CH_TASKID] = "nOS-V task ID",
|
||||||
|
[CH_TYPE] = "nOS-V task type",
|
||||||
|
[CH_APPID] = "nOS-V task AppID",
|
||||||
|
[CH_SUBSYSTEM] = "nOS-V subsystem",
|
||||||
|
[CH_RANK] = "nOS-V task MPI rank",
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static const char *pcf_suffix[TRACK_MAX] = {
|
||||||
|
[NONE] = "",
|
||||||
|
[RUN_TH] = "of the RUNNING thread",
|
||||||
|
[ACT_TH] = "of the ACTIVE thread",
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pcf_value_label nosv_ss_values[] = {
|
||||||
|
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" },
|
||||||
|
{ ST_SCHED_SERVING, "Scheduler: Serving" },
|
||||||
|
{ ST_SCHED_SUBMITTING, "Scheduler: Submitting" },
|
||||||
|
{ ST_MEM_ALLOCATING, "Memory: Allocating" },
|
||||||
|
{ ST_MEM_FREEING, "Memory: Freeing" },
|
||||||
|
{ ST_TASK_RUNNING, "Task: Running" },
|
||||||
|
{ ST_API_SUBMIT, "API: Submit" },
|
||||||
|
{ ST_API_PAUSE, "API: Pause" },
|
||||||
|
{ ST_API_YIELD, "API: Yield" },
|
||||||
|
{ ST_API_WAITFOR, "API: Waitfor" },
|
||||||
|
{ ST_API_SCHEDPOINT, "API: Scheduling point" },
|
||||||
|
{ ST_ATTACH, "Thread: Attached" },
|
||||||
|
{ ST_WORKER, "Thread: Worker" },
|
||||||
|
{ ST_DELEGATE, "Thread: Delegate" },
|
||||||
|
{ EV_SCHED_SEND, "EV Scheduler: Send task" },
|
||||||
|
{ EV_SCHED_RECV, "EV Scheduler: Recv task" },
|
||||||
|
{ EV_SCHED_SELF, "EV Scheduler: Self-assign task" },
|
||||||
|
{ -1, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct pcf_value_label (*pcf_chan_value_labels[CH_MAX])[] = {
|
||||||
|
[CH_SUBSYSTEM] = &nosv_ss_values,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* ------------------------------ pcf ------------------------------ */
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_values(struct pcf_type *t, int c)
|
||||||
|
{
|
||||||
|
const struct pcf_value_label(*q)[] = pcf_chan_value_labels[c];
|
||||||
|
|
||||||
|
if (q == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (const struct pcf_value_label *p = *q; p->label != NULL; p++)
|
||||||
|
pcf_add_value(t, p->value, p->label);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
create_type(struct pcf *pcf, enum nosv_chan c, enum nosv_chan_type ct)
|
||||||
|
{
|
||||||
|
long type = pvt_type[c];
|
||||||
|
|
||||||
|
if (type == -1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Compute the label by joining the two parts */
|
||||||
|
const char *prefix = pcf_prefix[c];
|
||||||
|
int track_mode = nosv_chan_track[c][ct];
|
||||||
|
const char *suffix = pcf_suffix[track_mode];
|
||||||
|
|
||||||
|
char label[MAX_PCF_LABEL];
|
||||||
|
int ret = snprintf(label, MAX_PCF_LABEL, "%s %s",
|
||||||
|
prefix, suffix);
|
||||||
|
|
||||||
|
if (ret >= MAX_PCF_LABEL) {
|
||||||
|
err("computed type label too long");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct pcf_type *pcftype = pcf_add_type(pcf, type, label);
|
||||||
|
|
||||||
|
return create_values(pcftype, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
init_pcf(struct pcf *pcf, enum nosv_chan_type ct)
|
||||||
|
{
|
||||||
|
/* Create default types and values */
|
||||||
|
for (enum nosv_chan c = 0; c < CH_MAX; c++) {
|
||||||
|
if (create_type(pcf, c, ct) != 0) {
|
||||||
|
err("create_type failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------ prv ------------------------------ */
|
||||||
|
|
||||||
|
static int
|
||||||
|
connect_thread_prv(struct emu *emu, struct thread *thread, struct prv *prv)
|
||||||
|
{
|
||||||
|
struct nosv_thread *th = EXT(thread, 'V');
|
||||||
|
for (int i = 0; i < CH_MAX; i++) {
|
||||||
|
struct chan *out = th->ch_out[i];
|
||||||
|
long type = pvt_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
|
||||||
|
connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv)
|
||||||
|
{
|
||||||
|
struct nosv_cpu *cpu = EXT(scpu, 'V');
|
||||||
|
for (int i = 0; i < CH_MAX; i++) {
|
||||||
|
struct chan *out = &cpu->ch[i];
|
||||||
|
long type = pvt_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_threads(struct emu *emu)
|
||||||
|
{
|
||||||
|
struct system *sys = &emu->system;
|
||||||
|
|
||||||
|
/* Get thread PRV */
|
||||||
|
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "thread");
|
||||||
|
if (pvt == NULL) {
|
||||||
|
err("cannot find thread pvt");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect thread channels to PRV */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init thread PCF */
|
||||||
|
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||||
|
if (init_pcf(pcf, CT_TH) != 0) {
|
||||||
|
err("init_pcf failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
connect_cpus(struct emu *emu)
|
||||||
|
{
|
||||||
|
struct system *sys = &emu->system;
|
||||||
|
|
||||||
|
/* Get cpu PRV */
|
||||||
|
struct pvt *pvt = recorder_find_pvt(&emu->recorder, "cpu");
|
||||||
|
if (pvt == NULL) {
|
||||||
|
err("cannot find cpu pvt");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect CPU channels to PRV */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Init CPU PCF */
|
||||||
|
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||||
|
if (init_pcf(pcf, CT_CPU) != 0) {
|
||||||
|
err("init_pcf failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Connect all outputs to the paraver trace and setup PCF types */
|
||||||
|
int
|
||||||
|
nosv_init_pvt(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
nosv_finish_pvt(struct emu *emu)
|
||||||
|
{
|
||||||
|
struct system *sys = &emu->system;
|
||||||
|
|
||||||
|
/* Emit task types for all channel types and processes */
|
||||||
|
for (enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++) {
|
||||||
|
struct pvt *pvt = recorder_find_pvt(&emu->recorder, pvt_name[ct]);
|
||||||
|
if (pvt == NULL) {
|
||||||
|
err("cannot find pvt with name '%s'", pvt_name[ct]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
struct pcf *pcf = pvt_get_pcf(pvt);
|
||||||
|
long typeid = pvt_type[CH_TYPE];
|
||||||
|
struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
|
||||||
|
|
||||||
|
for (struct proc *p = sys->procs; p; p = p->gnext) {
|
||||||
|
struct nosv_proc *nosvproc = EXT(p, 'V');
|
||||||
|
struct task_info *info = &nosvproc->task_info;
|
||||||
|
if (task_create_pcf_types(pcftype, info->types) != 0) {
|
||||||
|
err("task_create_pcf_types failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
nosv_ss_name(int ss)
|
||||||
|
{
|
||||||
|
static const char *unknown = "(unknown)";
|
||||||
|
const char *name = unknown;
|
||||||
|
const struct pcf_value_label *pv;
|
||||||
|
for (pv = &nosv_ss_values[0]; pv->label; pv++) {
|
||||||
|
if (pv->value == ss) {
|
||||||
|
name = pv->label;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return name;
|
||||||
|
}
|
@ -307,6 +307,22 @@ pre_affinity(struct emu *emu)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
pre_cpu(struct emu *emu)
|
||||||
|
{
|
||||||
|
switch (emu->ev->v) {
|
||||||
|
case 'n':
|
||||||
|
err("ignoring old event OCn");
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
err("unknown cpu event value %c\n",
|
||||||
|
emu->ev->v);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
compare_int64(const void *a, const void *b)
|
compare_int64(const void *a, const void *b)
|
||||||
{
|
{
|
||||||
@ -402,8 +418,9 @@ process_ev(struct emu *emu)
|
|||||||
case 'A':
|
case 'A':
|
||||||
return pre_affinity(emu);
|
return pre_affinity(emu);
|
||||||
case 'B':
|
case 'B':
|
||||||
pre_burst(emu);
|
return pre_burst(emu);
|
||||||
break;
|
case 'C':
|
||||||
|
return pre_cpu(emu);
|
||||||
case 'F':
|
case 'F':
|
||||||
return pre_flush(emu);
|
return pre_flush(emu);
|
||||||
default:
|
default:
|
||||||
|
@ -92,32 +92,6 @@ const int pcf_palette_len = ARRAY_LEN(pcf_def_palette);
|
|||||||
// { -1, NULL },
|
// { -1, NULL },
|
||||||
//};
|
//};
|
||||||
//
|
//
|
||||||
//struct pcf_value_label nosv_ss_values[] = {
|
|
||||||
// /* Errors */
|
|
||||||
// { ST_BAD, "Unknown: bad happened (report bug)" },
|
|
||||||
// { ST_TOO_MANY_TH, "Unknown: multiple threads running" },
|
|
||||||
// /* Good values */
|
|
||||||
// { ST_NULL, "No subsystem" },
|
|
||||||
// { ST_NOSV_SCHED_HUNGRY, "Scheduler: Hungry" },
|
|
||||||
// { ST_NOSV_SCHED_SERVING, "Scheduler: Serving" },
|
|
||||||
// { ST_NOSV_SCHED_SUBMITTING, "Scheduler: Submitting" },
|
|
||||||
// { ST_NOSV_MEM_ALLOCATING, "Memory: Allocating" },
|
|
||||||
// { ST_NOSV_MEM_FREEING, "Memory: Freeing" },
|
|
||||||
// { ST_NOSV_TASK_RUNNING, "Task: Running" },
|
|
||||||
// { ST_NOSV_API_SUBMIT, "API: Submit" },
|
|
||||||
// { ST_NOSV_API_PAUSE, "API: Pause" },
|
|
||||||
// { ST_NOSV_API_YIELD, "API: Yield" },
|
|
||||||
// { ST_NOSV_API_WAITFOR, "API: Waitfor" },
|
|
||||||
// { ST_NOSV_API_SCHEDPOINT, "API: Scheduling point" },
|
|
||||||
// { ST_NOSV_ATTACH, "Thread: Attached" },
|
|
||||||
// { ST_NOSV_WORKER, "Thread: Worker" },
|
|
||||||
// { ST_NOSV_DELEGATE, "Thread: Delegate" },
|
|
||||||
// { EV_NOSV_SCHED_SEND, "EV Scheduler: Send task" },
|
|
||||||
// { EV_NOSV_SCHED_RECV, "EV Scheduler: Recv task" },
|
|
||||||
// { EV_NOSV_SCHED_SELF, "EV Scheduler: Self-assign task" },
|
|
||||||
// { -1, NULL },
|
|
||||||
//};
|
|
||||||
//
|
|
||||||
//struct pcf_value_label nodes_mode_values[] = {
|
//struct pcf_value_label nodes_mode_values[] = {
|
||||||
// { ST_NULL, "NULL" },
|
// { ST_NULL, "NULL" },
|
||||||
// { ST_TOO_MANY_TH, "NODES: Multiple threads running" },
|
// { ST_TOO_MANY_TH, "NODES: Multiple threads running" },
|
||||||
|
@ -2,5 +2,5 @@
|
|||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
add_subdirectory(ovni)
|
add_subdirectory(ovni)
|
||||||
#add_subdirectory(nosv)
|
add_subdirectory(nosv)
|
||||||
add_subdirectory(nanos6)
|
add_subdirectory(nanos6)
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
ovni_test(nested-tasks.c)
|
ovni_test(nested-tasks.c)
|
||||||
ovni_test(nested-tasks-bad.c SHOULD_FAIL
|
ovni_test(nested-tasks-bad.c SHOULD_FAIL
|
||||||
REGEX "fatal: cannot execute task 1: state is not created")
|
REGEX "cannot execute task 1: state is not created")
|
||||||
ovni_test(task-types.c MP)
|
ovni_test(task-types.c MP)
|
||||||
ovni_test(pause.c MP)
|
ovni_test(pause.c MP)
|
||||||
ovni_test(mp-rank.c MP)
|
ovni_test(mp-rank.c MP)
|
||||||
|
@ -3,4 +3,4 @@
|
|||||||
|
|
||||||
add_subdirectory(nanos6)
|
add_subdirectory(nanos6)
|
||||||
#add_subdirectory(nodes)
|
#add_subdirectory(nodes)
|
||||||
#add_subdirectory(nosv)
|
add_subdirectory(nosv)
|
||||||
|
@ -23,6 +23,6 @@ function(nosv_test)
|
|||||||
ENVIRONMENT "NOSV_CONFIG=${OVNI_TEST_SOURCE_DIR}/rt/nosv/nosv.toml")
|
ENVIRONMENT "NOSV_CONFIG=${OVNI_TEST_SOURCE_DIR}/rt/nosv/nosv.toml")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
nosv_test(attach.c SORT)
|
nosv_test(attach.c)
|
||||||
nosv_test(waitfor.c SORT)
|
nosv_test(waitfor.c)
|
||||||
nosv_test(several-tasks.c SORT)
|
nosv_test(several-tasks.c)
|
||||||
|
@ -41,7 +41,7 @@ test_negative_cpu(struct loom *loom)
|
|||||||
die("loom_init_begin failed");
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
struct cpu cpu;
|
struct cpu cpu;
|
||||||
cpu_init_begin(&cpu, -1);
|
cpu_init_begin(&cpu, -1, 0);
|
||||||
|
|
||||||
if (loom_add_cpu(loom, &cpu) == 0)
|
if (loom_add_cpu(loom, &cpu) == 0)
|
||||||
die("loom_add_cpu didn't fail");
|
die("loom_add_cpu didn't fail");
|
||||||
@ -56,7 +56,7 @@ test_duplicate_cpus(struct loom *loom)
|
|||||||
die("loom_init_begin failed");
|
die("loom_init_begin failed");
|
||||||
|
|
||||||
struct cpu cpu;
|
struct cpu cpu;
|
||||||
cpu_init_begin(&cpu, 123);
|
cpu_init_begin(&cpu, 123, 0);
|
||||||
if (loom_add_cpu(loom, &cpu) != 0)
|
if (loom_add_cpu(loom, &cpu) != 0)
|
||||||
die("loom_add_cpu failed");
|
die("loom_add_cpu failed");
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user