Add track module and port Nanos6 model

This commit is contained in:
Rodrigo Arias 2023-02-13 18:36:54 +01:00 committed by Rodrigo Arias Mallo
parent 09f58610ec
commit 259de4df43
11 changed files with 301 additions and 171 deletions

View File

@ -34,6 +34,7 @@ add_library(emu STATIC
recorder.c recorder.c
system.c system.c
task.c task.c
track.c
thread.c thread.c
extend.c extend.c
ovni/probe.c ovni/probe.c

View File

@ -285,3 +285,12 @@ cpu_migrate_thread(struct cpu *cpu, struct thread *thread, struct cpu *newcpu)
return 0; return 0;
} }
struct chan *
cpu_get_th_chan(struct cpu *cpu, enum track_th trackmode)
{
if (trackmode != TRACK_TH_RUN)
die("cpu tracking must be running");
return &cpu->chan[CPU_CHAN_THRUN];
}

View File

@ -8,6 +8,7 @@ struct cpu; /* Needed for thread */
#include "thread.h" #include "thread.h"
#include "chan.h" #include "chan.h"
#include "track.h"
#include "bay.h" #include "bay.h"
#include "uthash.h" #include "uthash.h"
#include "recorder.h" #include "recorder.h"
@ -74,4 +75,6 @@ int cpu_add_thread(struct cpu *cpu, struct thread *thread);
int cpu_remove_thread(struct cpu *cpu, struct thread *thread); int cpu_remove_thread(struct cpu *cpu, struct thread *thread);
int cpu_migrate_thread(struct cpu *cpu, struct thread *thread, struct cpu *newcpu); int cpu_migrate_thread(struct cpu *cpu, struct thread *thread, struct cpu *newcpu);
struct chan *cpu_get_th_chan(struct cpu *cpu, enum track_th mode);
#endif /* CPU_H */ #endif /* CPU_H */

View File

@ -1,121 +1,69 @@
#include "nanos6_priv.h" #include "nanos6_priv.h"
const enum nanos6_track nanos6_chan_track[CH_MAX][CT_MAX] = { const int nanos6_chan_track[CH_MAX][CT_MAX] = {
/* Thread CPU */ /* Thread CPU */
[CH_TASKID] = { RUN_TH, RUN_TH }, [CH_TASKID] = { TRACK_TH_RUN, TRACK_TH_RUN },
[CH_TYPE] = { RUN_TH, RUN_TH }, [CH_TYPE] = { TRACK_TH_RUN, TRACK_TH_RUN },
[CH_SUBSYSTEM] = { ACT_TH, RUN_TH }, [CH_SUBSYSTEM] = { TRACK_TH_ACT, TRACK_TH_RUN },
[CH_RANK] = { RUN_TH, RUN_TH }, [CH_RANK] = { TRACK_TH_RUN, TRACK_TH_RUN },
[CH_THREAD] = { NONE, RUN_TH }, [CH_THREAD] = { TRACK_TH_ANY, TRACK_TH_RUN },
}; };
static int static int
connect_thread_mux(struct emu *emu, struct thread *thread) connect_thread(struct thread *sth)
{ {
struct nanos6_thread *th = EXT(thread, '6'); struct nanos6_thread *th = EXT(sth, '6');
for (int i = 0; i < CH_MAX; i++) { for (int i = 0; i < CH_MAX; i++) {
struct track *track = &th->track[i];
/* TODO: Let the thread take the select channel if (track_thread(track, &sth->chan[TH_CHAN_STATE], &th->ch[i]) != 0) {
* and build the mux as a tracking mode */ err("track_thread failed");
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; return -1;
} }
if (mux_add_input(mux_run, value_int64(0), inp) != 0) { /* Select the default output to PRV */
err("mux_add_input failed"); track_set_default(track, nanos6_chan_track[i][CT_TH]);
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 nanos6_track track = nanos6_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; return 0;
} }
static int static int
add_inputs_cpu_mux(struct emu *emu, struct mux *mux, int i) connect_cpu(struct emu *emu, struct cpu *scpu)
{
for (struct thread *t = emu->system.threads; t; t = t->gnext) {
struct nanos6_thread *th = EXT(t, '6');
/* Choose input thread channel based on tracking mode */
struct chan *inp = NULL;
enum nanos6_track track = nanos6_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 nanos6_cpu *cpu = EXT(scpu, '6'); struct nanos6_cpu *cpu = EXT(scpu, '6');
for (int i = 0; i < CH_MAX; i++) { for (int i = 0; i < CH_MAX; i++) {
struct mux *mux = &cpu->mux[i]; struct track *cpu_track = &cpu->track[i];
struct chan *out = &cpu->ch[i];
/* Choose select CPU channel based on tracking mode */ /* Choose select CPU channel based on tracking mode (only
struct chan *sel = NULL; * TRACK_TH_RUN allowed, as active may cause collisions) */
enum nanos6_track track = nanos6_chan_track[i][CT_CPU]; int mode = nanos6_chan_track[i][CT_CPU];
if (track == RUN_TH) struct chan *sel = cpu_get_th_chan(scpu, mode);
sel = &scpu->chan[CPU_CHAN_THRUN]; if (track_set_select(cpu_track, mode, sel, NULL) != 0) {
else if (track == ACT_TH) err("track_select failed");
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; return -1;
} }
if (add_inputs_cpu_mux(emu, mux, i) != 0) { /* Add each thread as input */
err("add_inputs_cpu_mux failed"); for (struct thread *t = emu->system.threads; t; t = t->gnext) {
struct nanos6_thread *th = EXT(t, '6');
/* Choose input channel from the thread output channels
* based on CPU tracking mode */
struct value key = value_int64(t->gindex);
struct chan *inp = track_get_output(&th->track[i], mode);
if (track_add_input(cpu_track, mode, key, inp) != 0) {
err("track_add_input failed");
return -1; return -1;
} }
} }
/* Set the PRV output */
track_set_default(cpu_track, nanos6_chan_track[i][CT_CPU]);
}
return 0; return 0;
} }
@ -126,16 +74,16 @@ nanos6_connect(struct emu *emu)
/* threads */ /* threads */
for (struct thread *t = sys->threads; t; t = t->gnext) { for (struct thread *t = sys->threads; t; t = t->gnext) {
if (connect_thread_mux(emu, t) != 0) { if (connect_thread(t) != 0) {
err("connect_thread_mux failed"); err("connect_thread failed");
return -1; return -1;
} }
} }
/* cpus */ /* cpus */
for (struct cpu *c = sys->cpus; c; c = c->next) { for (struct cpu *c = sys->cpus; c; c = c->next) {
if (connect_cpu_mux(emu, c) != 0) { if (connect_cpu(emu, c) != 0) {
err("connect_cpu_mux failed"); err("connect_cpu failed");
return -1; return -1;
} }
} }

View File

@ -1,12 +1,5 @@
#include "nanos6_priv.h" #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_MAX] = { static const char *chan_name[CH_MAX] = {
[CH_TASKID] = "taskid", [CH_TASKID] = "taskid",
[CH_TYPE] = "task_type", [CH_TYPE] = "task_type",
@ -21,11 +14,11 @@ static const int chan_stack[CH_MAX] = {
}; };
static int static int
init_chans(struct bay *bay, struct chan *chans, const char *fmt, int64_t gindex, int filtered) init_chans(struct bay *bay, struct chan *chans, const char *fmt, int64_t gindex)
{ {
for (int i = 0; i < CH_MAX; i++) { for (int i = 0; i < CH_MAX; i++) {
struct chan *c = &chans[i]; struct chan *c = &chans[i];
int type = (chan_stack[i] && !filtered) ? CHAN_STACK : CHAN_SINGLE; int type = chan_stack[i] ? CHAN_STACK : CHAN_SINGLE;
chan_init(c, type, fmt, gindex, chan_name[i]); chan_init(c, type, fmt, gindex, chan_name[i]);
if (bay_register(bay, c) != 0) { if (bay_register(bay, c) != 0) {
@ -37,6 +30,21 @@ init_chans(struct bay *bay, struct chan *chans, const char *fmt, int64_t gindex,
return 0; return 0;
} }
static int
init_tracks(struct bay *bay, struct track *tracks, const char *fmt, int64_t gindex)
{
for (int i = 0; i < CH_MAX; i++) {
struct track *track = &tracks[i];
if (track_init(track, bay, TRACK_TYPE_TH, fmt, gindex, chan_name[i]) != 0) {
err("track_init failed");
return -1;
}
}
return 0;
}
static int static int
init_cpu(struct bay *bay, struct cpu *syscpu) init_cpu(struct bay *bay, struct cpu *syscpu)
{ {
@ -46,20 +54,15 @@ init_cpu(struct bay *bay, struct cpu *syscpu)
return -1; return -1;
} }
cpu->ch = calloc(CH_MAX, sizeof(struct chan)); cpu->track = calloc(CH_MAX, sizeof(struct track));
if (cpu->ch == NULL) { if (cpu->track == NULL) {
err("calloc failed:"); err("calloc failed:");
return -1; return -1;
} }
cpu->mux = calloc(CH_MAX, sizeof(struct mux)); char *fmt = "nanos6.cpu%ld.%s";
if (cpu->mux == NULL) { if (init_tracks(bay, cpu->track, fmt, syscpu->gindex) != 0) {
err("calloc failed:"); err("init_tracks failed");
return -1;
}
if (init_chans(bay, cpu->ch, chan_fmt_cpu_raw, syscpu->gindex, 1) != 0) {
err("init_chans failed");
return -1; return -1;
} }
@ -82,52 +85,23 @@ init_thread(struct bay *bay, struct thread *systh)
return -1; return -1;
} }
th->ch_run = calloc(CH_MAX, sizeof(struct chan)); th->track = calloc(CH_MAX, sizeof(struct track));
if (th->ch_run == NULL) { if (th->track == NULL) {
err("calloc failed:"); err("calloc failed:");
return -1; return -1;
} }
th->ch_act = calloc(CH_MAX, sizeof(struct chan)); char *fmt = "nanos6.thread%ld.%s";
if (th->ch_act == NULL) { if (init_chans(bay, th->ch, fmt, systh->gindex) != 0) {
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"); err("init_chans failed");
return -1; return -1;
} }
if (init_chans(bay, th->ch_run, chan_fmt_th_run, systh->gindex, 1) != 0) { if (init_tracks(bay, th->track, fmt, systh->gindex) != 0) {
err("init_chans failed"); err("init_tracks failed");
return -1; 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; th->task_stack.thread = systh;
extend_set(&systh->ext, '6', th); extend_set(&systh->ext, '6', th);

View File

@ -8,6 +8,7 @@
#include "chan.h" #include "chan.h"
#include "mux.h" #include "mux.h"
#include "task.h" #include "task.h"
#include "track.h"
/* Private enums */ /* Private enums */
@ -26,14 +27,7 @@ enum nanos6_chan {
CH_MAX, CH_MAX,
}; };
enum nanos6_track { extern const int nanos6_chan_track[CH_MAX][CT_MAX];
NONE = 0,
RUN_TH,
ACT_TH,
TRACK_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,
@ -76,18 +70,13 @@ enum nanos6_thread_type {
}; };
struct nanos6_thread { struct nanos6_thread {
struct chan *ch; /* Raw, modified by nanos6 */ struct chan *ch;
struct chan *ch_run; /* Tracking running thread */ struct track *track;
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 task_stack task_stack;
}; };
struct nanos6_cpu { struct nanos6_cpu {
struct chan *ch; struct track *track;
struct mux *mux;
}; };
struct nanos6_proc { struct nanos6_proc {

View File

@ -23,10 +23,10 @@ static const char *pcf_prefix[CH_MAX] = {
[CH_THREAD] = "Nanos6 thread type", [CH_THREAD] = "Nanos6 thread type",
}; };
static const char *pcf_suffix[TRACK_MAX] = { static const char *pcf_suffix[TRACK_TH_MAX] = {
[NONE] = "", [TRACK_TH_ANY] = "",
[RUN_TH] = "of the RUNNING thread", [TRACK_TH_RUN] = "of the RUNNING thread",
[ACT_TH] = "of the ACTIVE thread", [TRACK_TH_ACT] = "of the ACTIVE thread",
}; };
static const struct pcf_value_label nanos6_ss_values[] = { static const struct pcf_value_label nanos6_ss_values[] = {
@ -139,7 +139,7 @@ connect_thread_prv(struct emu *emu, struct thread *thread, struct prv *prv)
{ {
struct nanos6_thread *th = EXT(thread, '6'); struct nanos6_thread *th = EXT(thread, '6');
for (int i = 0; i < CH_MAX; i++) { for (int i = 0; i < CH_MAX; i++) {
struct chan *out = th->ch_out[i]; struct chan *out = track_get_default(&th->track[i]);
long type = pvt_type[i]; long type = pvt_type[i];
long row = thread->gindex; long row = thread->gindex;
if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) { if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) {
@ -156,7 +156,7 @@ connect_cpu_prv(struct emu *emu, struct cpu *scpu, struct prv *prv)
{ {
struct nanos6_cpu *cpu = EXT(scpu, '6'); struct nanos6_cpu *cpu = EXT(scpu, '6');
for (int i = 0; i < CH_MAX; i++) { for (int i = 0; i < CH_MAX; i++) {
struct chan *out = &cpu->ch[i]; struct chan *out = track_get_default(&cpu->track[i]);
long type = pvt_type[i]; long type = pvt_type[i];
long row = scpu->gindex; long row = scpu->gindex;
if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) { if (prv_register(prv, row, type, &emu->bay, out, PRV_DUP)) {

View File

@ -254,7 +254,30 @@ thread_select_running(struct mux *mux,
return 0; return 0;
} }
int
thread_select_any(struct mux *mux,
struct value value,
struct mux_input **input)
{
if (value.type == VALUE_NULL) {
*input = NULL;
return 0;
}
if (value.type != VALUE_INT64) {
err("expecting NULL or INT64 channel value");
return -1;
}
if (mux->ninputs != 1) {
err("mux doesn't have one input but %d", mux->ninputs);
return -1;
}
*input = mux->input;
return 0;
}
int int
thread_set_cpu(struct thread *th, struct cpu *cpu) thread_set_cpu(struct thread *th, struct cpu *cpu)

View File

@ -85,5 +85,6 @@ int thread_connect(struct thread *th, struct bay *bay, struct recorder *rec);
int thread_select_active(struct mux *mux, struct value value, struct mux_input **input); int thread_select_active(struct mux *mux, struct value value, struct mux_input **input);
int thread_select_running(struct mux *mux, struct value value, struct mux_input **input); int thread_select_running(struct mux *mux, struct value value, struct mux_input **input);
int thread_select_any(struct mux *mux, struct value value, struct mux_input **input);
#endif /* THREAD_H */ #endif /* THREAD_H */

140
src/emu/track.c Normal file
View File

@ -0,0 +1,140 @@
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#include "track.h"
#include "thread.h"
static const int track_nmodes[TRACK_TYPE_MAX] = {
[TRACK_TYPE_TH] = TRACK_TH_MAX,
};
static const char *th_suffix[TRACK_TH_MAX] = {
[TRACK_TH_ANY] = ".any",
[TRACK_TH_RUN] = ".run",
[TRACK_TH_ACT] = ".act",
};
static const char **track_suffix[TRACK_TYPE_MAX] = {
[TRACK_TYPE_TH] = th_suffix,
};
int
track_init(struct track *track, struct bay *bay, enum track_type type, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
int n = ARRAYLEN(track->name);
int ret = vsnprintf(track->name, n, fmt, ap);
if (ret >= n)
die("track name too long\n");
va_end(ap);
track->nmodes = track_nmodes[type];
track->type = type;
track->bay = bay;
/* Create one output channel per tracking mode */
track->out = calloc(track->nmodes, sizeof(struct chan));
if (track->out == NULL) {
err("calloc failed:");
return -1;
}
/* Set the channel name by appending the suffix */
for (int i = 0; i < track->nmodes; i++) {
struct chan *ch = &track->out[i];
chan_init(ch, CHAN_SINGLE, "%s%s", track->name, track_suffix[type][i]);
if (bay_register(bay, ch) != 0) {
err("bay_register failed");
return -1;
}
}
track->mux = calloc(track->nmodes, sizeof(struct mux));
if (track->mux == NULL) {
err("calloc failed:");
return -1;
}
return 0;
}
void
track_set_default(struct track *track, int mode)
{
track->def = &track->out[mode];
}
struct chan *
track_get_default(struct track *track)
{
return track->def;
}
int
track_set_select(struct track *track, int mode, struct chan *sel, mux_select_func_t fsel)
{
struct mux *mux = &track->mux[mode];
struct chan *out = &track->out[mode];
if (mux_init(mux, track->bay, sel, out, fsel) != 0) {
err("mux_init failed");
return -1;
}
return 0;
}
struct chan *
track_get_output(struct track *track, int mode)
{
return &track->out[mode];
}
int
track_add_input(struct track *track, int mode, struct value key, struct chan *inp)
{
struct mux *mux = &track->mux[mode];
if (mux_add_input(mux, key, inp) != 0) {
err("mux_add_input failed");
return -1;
}
return 0;
}
int
track_thread(struct track *track, struct chan *sel, struct chan *inp)
{
/* Create all thread tracking modes */
if (track_set_select(track, TRACK_TH_ANY, sel, thread_select_any) != 0) {
err("track_select failed");
return -1;
}
if (track_add_input(track, TRACK_TH_ANY, value_int64(0), inp) != 0) {
err("track_add_input failed");
return -1;
}
if (track_set_select(track, TRACK_TH_RUN, sel, thread_select_running) != 0) {
err("track_select failed");
return -1;
}
if (track_add_input(track, TRACK_TH_RUN, value_int64(0), inp) != 0) {
err("track_add_input failed");
return -1;
}
if (track_set_select(track, TRACK_TH_ACT, sel, thread_select_active) != 0) {
err("track_select failed");
return -1;
}
if (track_add_input(track, TRACK_TH_ACT, value_int64(0), inp) != 0) {
err("track_add_input failed");
return -1;
}
return 0;
}

42
src/emu/track.h Normal file
View File

@ -0,0 +1,42 @@
/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
#ifndef TRACK_H
#define TRACK_H
#include "mux.h"
enum track_type {
TRACK_TYPE_TH = 0,
TRACK_TYPE_MAX
};
enum track_th {
TRACK_TH_ANY = 0,
TRACK_TH_RUN,
TRACK_TH_ACT,
TRACK_TH_MAX,
};
struct track {
enum track_type type;
char name[MAX_CHAN_NAME];
int nmodes;
struct bay *bay;
struct chan *out;
struct chan *def;
struct mux *mux;
};
int track_init(struct track *track, struct bay *bay, enum track_type type, const char *fmt, ...);
int track_set_select(struct track *track, int mode, struct chan *sel, mux_select_func_t fsel);
int track_add_input(struct track *track, int mode, struct value key, struct chan *inp);
int track_output(struct track *track, int mode);
void track_set_default(struct track *track, int mode);
struct chan *track_get_default(struct track *track);
struct chan *track_get_output(struct track *track, int mode);
int track_thread(struct track *track, struct chan *sel, struct chan *inp);
#endif /* TRACK_H */