Use a hash of the type label to derive the gid
This avoids different processes running tasks with the same type label to have different colors.
This commit is contained in:
parent
fa9196fd63
commit
b0f693360c
22
emu.h
22
emu.h
@ -107,9 +107,16 @@ enum kernel_cs_state {
|
||||
struct ovni_ethread;
|
||||
struct ovni_eproc;
|
||||
|
||||
struct nosv_task_type {
|
||||
uint32_t id; /* Per-process identifier, same as nOS-V */
|
||||
uint32_t gid; /* Global identifier computed from the label */
|
||||
char label[MAX_PCF_LABEL];
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
struct nosv_task {
|
||||
int id;
|
||||
int type_id;
|
||||
uint32_t id;
|
||||
struct nosv_task_type *type;
|
||||
struct ovni_ethread *thread;
|
||||
enum nosv_task_state state;
|
||||
UT_hash_handle hh;
|
||||
@ -119,13 +126,6 @@ struct nosv_task {
|
||||
struct nosv_task *prev;
|
||||
};
|
||||
|
||||
struct nosv_task_type {
|
||||
int gid; /* Global identifier */
|
||||
int id; /* Per-process identifier */
|
||||
char label[MAX_PCF_LABEL];
|
||||
UT_hash_handle hh;
|
||||
};
|
||||
|
||||
#define MAX_CHAN_STACK 128
|
||||
|
||||
enum chan_track {
|
||||
@ -151,7 +151,7 @@ enum chan {
|
||||
CHAN_OVNI_FLUSH,
|
||||
|
||||
CHAN_NOSV_TASKID,
|
||||
CHAN_NOSV_TYPEID,
|
||||
CHAN_NOSV_TYPE,
|
||||
CHAN_NOSV_APPID,
|
||||
CHAN_NOSV_SUBSYSTEM,
|
||||
CHAN_NOSV_RANK,
|
||||
@ -192,7 +192,7 @@ static const int chan_to_prvtype[CHAN_MAX][CHAN_MAXTYPE] = {
|
||||
[CHAN_OVNI_CPU] = { 15, -1 },
|
||||
[CHAN_OVNI_FLUSH] = { 16, 66 },
|
||||
[CHAN_NOSV_TASKID] = { 20, 70 },
|
||||
[CHAN_NOSV_TYPEID] = { 21, 71 },
|
||||
[CHAN_NOSV_TYPE] = { 21, 71 },
|
||||
[CHAN_NOSV_APPID] = { 22, 72 },
|
||||
[CHAN_NOSV_SUBSYSTEM] = { 23, 73 },
|
||||
[CHAN_NOSV_RANK] = { 24, 74 },
|
||||
|
139
emu_nosv.c
139
emu_nosv.c
@ -49,7 +49,7 @@ hook_init_nosv(struct ovni_emu *emu)
|
||||
uth = &emu->th_chan;
|
||||
|
||||
chan_th_init(th, uth, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
|
||||
@ -68,7 +68,7 @@ hook_init_nosv(struct ovni_emu *emu)
|
||||
ucpu = &emu->cpu_chan;
|
||||
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
@ -80,30 +80,33 @@ hook_init_nosv(struct ovni_emu *emu)
|
||||
static void
|
||||
pre_task_create(struct ovni_emu *emu)
|
||||
{
|
||||
struct nosv_task *task, *p = NULL;
|
||||
uint32_t task_id = emu->cur_ev->payload.u32[0];
|
||||
uint32_t type_id = emu->cur_ev->payload.u32[1];
|
||||
|
||||
/* Ensure the task id is new */
|
||||
struct nosv_task *task = NULL;
|
||||
HASH_FIND_INT(emu->cur_proc->tasks, &task_id, task);
|
||||
|
||||
if(task != NULL)
|
||||
die("a task with id %u already exists\n", task_id);
|
||||
|
||||
/* Ensure the type exists */
|
||||
struct nosv_task_type *type = NULL;
|
||||
HASH_FIND_INT(emu->cur_proc->types, &type_id, type);
|
||||
|
||||
if(type == NULL)
|
||||
die("unknown task type id %u\n", type_id);
|
||||
|
||||
task = calloc(1, sizeof(*task));
|
||||
|
||||
if(task == NULL)
|
||||
{
|
||||
perror("calloc");
|
||||
abort();
|
||||
}
|
||||
die("calloc failed\n");
|
||||
|
||||
task->id = emu->cur_ev->payload.i32[0];
|
||||
task->type_id = emu->cur_ev->payload.i32[1];
|
||||
task->id = task_id;
|
||||
task->type = type;
|
||||
task->state = TASK_ST_CREATED;
|
||||
task->thread = NULL;
|
||||
|
||||
/* Ensure the task id is new */
|
||||
HASH_FIND_INT(emu->cur_proc->tasks, &task->id, p);
|
||||
|
||||
if(p != NULL)
|
||||
{
|
||||
err("A task with id %d already exists\n", p->id);
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Add the new task to the hash table */
|
||||
HASH_ADD_INT(emu->cur_proc->tasks, id, task);
|
||||
|
||||
@ -113,16 +116,14 @@ pre_task_create(struct ovni_emu *emu)
|
||||
static void
|
||||
pre_task_execute(struct ovni_emu *emu)
|
||||
{
|
||||
struct nosv_task *task, *top;
|
||||
int taskid;
|
||||
|
||||
top = emu->cur_thread->task_stack;
|
||||
taskid = emu->cur_ev->payload.i32[0];
|
||||
struct nosv_task *top = emu->cur_thread->task_stack;
|
||||
uint32_t taskid = emu->cur_ev->payload.u32[0];
|
||||
|
||||
struct nosv_task *task = NULL;
|
||||
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %d\n", taskid);
|
||||
die("cannot find task with id %u\n", taskid);
|
||||
|
||||
if(task->state != TASK_ST_CREATED)
|
||||
die("task state is not created\n");
|
||||
@ -134,7 +135,7 @@ pre_task_execute(struct ovni_emu *emu)
|
||||
die("thread state is not running\n");
|
||||
|
||||
if(top == task)
|
||||
die("thread already has assigned task %d\n", taskid);
|
||||
die("thread already has assigned task %u\n", taskid);
|
||||
|
||||
if(top && top->state != TASK_ST_RUNNING)
|
||||
die("cannot execute a nested task from a non-running task\n");
|
||||
@ -144,22 +145,20 @@ pre_task_execute(struct ovni_emu *emu)
|
||||
|
||||
DL_PREPEND(emu->cur_thread->task_stack, task);
|
||||
|
||||
dbg("task id=%d runs now\n", task->id);
|
||||
dbg("task id=%u runs now\n", task->id);
|
||||
}
|
||||
|
||||
static void
|
||||
pre_task_pause(struct ovni_emu *emu)
|
||||
{
|
||||
struct nosv_task *task, *top;
|
||||
int taskid;
|
||||
|
||||
top = emu->cur_thread->task_stack;
|
||||
taskid = emu->cur_ev->payload.i32[0];
|
||||
struct nosv_task *top = emu->cur_thread->task_stack;
|
||||
uint32_t taskid = emu->cur_ev->payload.u32[0];
|
||||
|
||||
struct nosv_task *task = NULL;
|
||||
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %d\n", taskid);
|
||||
die("cannot find task with id %u\n", taskid);
|
||||
|
||||
if(task->state != TASK_ST_RUNNING)
|
||||
die("task state is not running\n");
|
||||
@ -181,16 +180,14 @@ pre_task_pause(struct ovni_emu *emu)
|
||||
static void
|
||||
pre_task_resume(struct ovni_emu *emu)
|
||||
{
|
||||
struct nosv_task *task, *top;
|
||||
int taskid;
|
||||
|
||||
top = emu->cur_thread->task_stack;
|
||||
taskid = emu->cur_ev->payload.i32[0];
|
||||
struct nosv_task *top = emu->cur_thread->task_stack;
|
||||
uint32_t taskid = emu->cur_ev->payload.u32[0];
|
||||
|
||||
struct nosv_task *task = NULL;
|
||||
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %d\n", taskid);
|
||||
die("cannot find task with id %u\n", taskid);
|
||||
|
||||
if(task->state != TASK_ST_PAUSED)
|
||||
die("task state is not paused\n");
|
||||
@ -212,16 +209,14 @@ pre_task_resume(struct ovni_emu *emu)
|
||||
static void
|
||||
pre_task_end(struct ovni_emu *emu)
|
||||
{
|
||||
struct nosv_task *task, *top;
|
||||
int taskid;
|
||||
|
||||
top = emu->cur_thread->task_stack;
|
||||
taskid = emu->cur_ev->payload.i32[0];
|
||||
struct nosv_task *top = emu->cur_thread->task_stack;
|
||||
uint32_t taskid = emu->cur_ev->payload.u32[0];
|
||||
|
||||
struct nosv_task *task = NULL;
|
||||
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %d\n", taskid);
|
||||
die("cannot find task with id %u\n", taskid);
|
||||
|
||||
if(task->state != TASK_ST_RUNNING)
|
||||
die("task state is not running\n");
|
||||
@ -250,7 +245,7 @@ pre_task_not_running(struct ovni_emu *emu)
|
||||
th = emu->cur_thread;
|
||||
|
||||
chan_set(&th->chan[CHAN_NOSV_TASKID], 0);
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPEID], 0);
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPE], 0);
|
||||
chan_set(&th->chan[CHAN_NOSV_APPID], 0);
|
||||
|
||||
if(emu->cur_loom->rank_enabled)
|
||||
@ -271,14 +266,14 @@ pre_task_running(struct ovni_emu *emu, struct nosv_task *task)
|
||||
if(task->id <= 0)
|
||||
die("task id must be positive\n");
|
||||
|
||||
if(task->type_id <= 0)
|
||||
die("task type id must be positive\n");
|
||||
if(task->type->gid <= 0)
|
||||
die("task type gid must be positive\n");
|
||||
|
||||
if(proc->appid <= 0)
|
||||
die("app id must be positive\n");
|
||||
|
||||
chan_set(&th->chan[CHAN_NOSV_TASKID], task->id);
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPEID], task->type_id);
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPE], task->type->gid);
|
||||
chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid);
|
||||
|
||||
if(emu->cur_loom->rank_enabled)
|
||||
@ -304,7 +299,7 @@ pre_task_switch(struct ovni_emu *emu, struct nosv_task *prev_task,
|
||||
if(next_task->id <= 0)
|
||||
die("next task id must be positive\n");
|
||||
|
||||
if(next_task->type_id <= 0)
|
||||
if(next_task->type->gid <= 0)
|
||||
die("next task type id must be positive\n");
|
||||
|
||||
chan_set(&th->chan[CHAN_NOSV_TASKID], next_task->id);
|
||||
@ -312,9 +307,12 @@ pre_task_switch(struct ovni_emu *emu, struct nosv_task *prev_task,
|
||||
/* No need to change the rank, as we can only switch to tasks of
|
||||
* the same loom (with same rank) */
|
||||
|
||||
/* Only emit the new type if necessary */
|
||||
if(prev_task->type_id != next_task->type_id)
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPEID], next_task->type_id);
|
||||
/* FIXME: We should emit a PRV event even if we are switching to
|
||||
* the same type event, to mark the end of the current task. For
|
||||
* now we only emit a new type if we switch to a type with a
|
||||
* different gid. */
|
||||
if(prev_task->type->gid != next_task->type->gid)
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPE], next_task->type->gid);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -350,13 +348,17 @@ pre_task(struct ovni_emu *emu)
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
get_task_type_gid(struct ovni_emu *emu, struct ovni_eproc *proc, uint32_t id)
|
||||
get_task_type_gid(const char *label)
|
||||
{
|
||||
/* Don't use emu->cur_proc, so we can use it at any point */
|
||||
uint32_t gid = id * emu->total_nprocs + proc->gindex;
|
||||
uint32_t gid;
|
||||
|
||||
HASH_VALUE(label, strlen(label), gid);
|
||||
|
||||
/* Use non-negative values */
|
||||
gid &= 0x7FFFFFFF;
|
||||
|
||||
if (gid == 0)
|
||||
die("invalid global task type id %d\n", gid);
|
||||
gid++;
|
||||
|
||||
return gid;
|
||||
}
|
||||
@ -402,7 +404,7 @@ pre_type_create(struct ovni_emu *emu)
|
||||
if(type->id == 0)
|
||||
die("invalid task type id %d\n", type->id);
|
||||
|
||||
type->gid = get_task_type_gid(emu, emu->cur_proc, type->id);
|
||||
type->gid = get_task_type_gid(label);
|
||||
int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label);
|
||||
if(n >= MAX_PCF_LABEL)
|
||||
die("task label too long: %s\n", label);
|
||||
@ -604,21 +606,22 @@ hook_pre_nosv(struct ovni_emu *emu)
|
||||
static void
|
||||
create_pcf_task_types(struct ovni_eproc *proc, struct pcf_type *pcftype)
|
||||
{
|
||||
char buf[MAX_PCF_LABEL];
|
||||
|
||||
/* Emit types for all task types */
|
||||
struct nosv_task_type *tt;
|
||||
for(tt = proc->types; tt != NULL; tt=tt->hh.next)
|
||||
{
|
||||
/* Use a unique identifier for the task types */
|
||||
int value = tt->gid;
|
||||
int n = snprintf(buf, MAX_PCF_LABEL, "%s (%d)",
|
||||
tt->label, tt->id);
|
||||
struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid);
|
||||
if(pcfvalue != NULL)
|
||||
{
|
||||
/* Ensure the label is the same, so we know that
|
||||
* no collision occurred */
|
||||
if(strcmp(pcfvalue->label, tt->label) != 0)
|
||||
die("collision occurred in task type labels\n");
|
||||
else
|
||||
continue;
|
||||
}
|
||||
|
||||
if(n >= MAX_PCF_LABEL)
|
||||
die("generated label too long: %s\n", buf);
|
||||
|
||||
pcf_add_value(pcftype, value, buf);
|
||||
pcf_add_value(pcftype, tt->gid, tt->label);
|
||||
}
|
||||
}
|
||||
|
||||
@ -629,7 +632,7 @@ hook_end_nosv(struct ovni_emu *emu)
|
||||
for(enum chan_type ct = 0; ct < CHAN_MAXTYPE; ct++)
|
||||
{
|
||||
struct pcf_file *pcf = &emu->pcf[ct];
|
||||
int typeid = chan_to_prvtype[CHAN_NOSV_TYPEID][ct];
|
||||
int typeid = chan_to_prvtype[CHAN_NOSV_TYPE][ct];
|
||||
struct pcf_type *pcftype = pcf_find_type(pcf, typeid);
|
||||
|
||||
for(size_t i = 0; i < emu->trace.nlooms; i++)
|
||||
|
66
pcf.c
66
pcf.c
@ -188,7 +188,7 @@ struct pcf_value_label (*pcf_chan_value_labels[CHAN_MAX])[] = {
|
||||
[CHAN_OVNI_FLUSH] = &ovni_flush_values,
|
||||
|
||||
[CHAN_NOSV_TASKID] = &default_values,
|
||||
[CHAN_NOSV_TYPEID] = &default_values,
|
||||
[CHAN_NOSV_TYPE] = &default_values,
|
||||
[CHAN_NOSV_APPID] = &default_values,
|
||||
[CHAN_NOSV_SUBSYSTEM] = &nosv_ss_values,
|
||||
[CHAN_NOSV_RANK] = &default_values,
|
||||
@ -212,7 +212,7 @@ char *pcf_chan_name[CHAN_MAX] = {
|
||||
[CHAN_OVNI_FLUSH] = "Flushing state",
|
||||
|
||||
[CHAN_NOSV_TASKID] = "nOS-V TaskID",
|
||||
[CHAN_NOSV_TYPEID] = "nOS-V task TypeID",
|
||||
[CHAN_NOSV_TYPE] = "nOS-V task type",
|
||||
[CHAN_NOSV_APPID] = "nOS-V task AppID",
|
||||
[CHAN_NOSV_SUBSYSTEM] = "nOS-V subsystem",
|
||||
[CHAN_NOSV_RANK] = "MPI rank",
|
||||
@ -244,7 +244,7 @@ int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = {
|
||||
[CHAN_OVNI_FLUSH] = { CUR_TH, RUN_TH },
|
||||
|
||||
[CHAN_NOSV_TASKID] = { RUN_TH, RUN_TH },
|
||||
[CHAN_NOSV_TYPEID] = { RUN_TH, RUN_TH },
|
||||
[CHAN_NOSV_TYPE] = { RUN_TH, RUN_TH },
|
||||
[CHAN_NOSV_APPID] = { RUN_TH, RUN_TH },
|
||||
[CHAN_NOSV_SUBSYSTEM] = { ACT_TH, RUN_TH },
|
||||
[CHAN_NOSV_RANK] = { RUN_TH, RUN_TH },
|
||||
@ -385,30 +385,38 @@ pcf_find_type(struct pcf_file *pcf, int type_id)
|
||||
struct pcf_type *
|
||||
pcf_add_type(struct pcf_file *pcf, int type_id, const char *label)
|
||||
{
|
||||
struct pcf_type *type;
|
||||
struct pcf_type *pcftype;
|
||||
|
||||
type = pcf_find_type(pcf, type_id);
|
||||
pcftype = pcf_find_type(pcf, type_id);
|
||||
|
||||
if(type != NULL)
|
||||
if(pcftype != NULL)
|
||||
die("PCF type %d already defined\n", type_id);
|
||||
|
||||
type = calloc(1, sizeof(struct pcf_type));
|
||||
|
||||
if(type == NULL)
|
||||
pcftype = calloc(1, sizeof(struct pcf_type));
|
||||
if(pcftype == NULL)
|
||||
die("calloc failed: %s\n", strerror(errno));
|
||||
|
||||
type->id = type_id;
|
||||
type->values = NULL;
|
||||
type->nvalues = 0;
|
||||
if(snprintf(type->label, MAX_PCF_LABEL,
|
||||
"%s", label) >= MAX_PCF_LABEL)
|
||||
{
|
||||
die("PCF label too long\n");
|
||||
pcftype->id = type_id;
|
||||
pcftype->values = NULL;
|
||||
pcftype->nvalues = 0;
|
||||
|
||||
int len = snprintf(pcftype->label, MAX_PCF_LABEL, "%s", label);
|
||||
if(len >= MAX_PCF_LABEL)
|
||||
die("PCF type label too long\n");
|
||||
|
||||
HASH_ADD_INT(pcf->types, id, pcftype);
|
||||
|
||||
return pcftype;
|
||||
}
|
||||
|
||||
HASH_ADD_INT(pcf->types, id, type);
|
||||
struct pcf_value *
|
||||
pcf_find_value(struct pcf_type *type, int value)
|
||||
{
|
||||
struct pcf_value *pcfvalue;
|
||||
|
||||
return type;
|
||||
HASH_FIND_INT(type->values, &value, pcfvalue);
|
||||
|
||||
return pcfvalue;
|
||||
}
|
||||
|
||||
/** Adds a new value to the given pcf_type. The label can be disposed
|
||||
@ -419,30 +427,26 @@ pcf_add_type(struct pcf_file *pcf, int type_id, const char *label)
|
||||
struct pcf_value *
|
||||
pcf_add_value(struct pcf_type *type, int value, const char *label)
|
||||
{
|
||||
struct pcf_value *pv;
|
||||
struct pcf_value *pcfvalue = pcf_find_value(type, value);
|
||||
|
||||
HASH_FIND_INT(type->values, &value, pv);
|
||||
|
||||
if(pv != NULL)
|
||||
if(pcfvalue != NULL)
|
||||
die("PCF value %d already in type %d\n", value, type->id);
|
||||
|
||||
pv = calloc(1, sizeof(struct pcf_value));
|
||||
|
||||
if(pv == NULL)
|
||||
pcfvalue = calloc(1, sizeof(struct pcf_value));
|
||||
if(pcfvalue == NULL)
|
||||
die("calloc failed: %s\n", strerror(errno));
|
||||
|
||||
pv->value = value;
|
||||
|
||||
int len = snprintf(pv->label, MAX_PCF_LABEL, "%s", label);
|
||||
pcfvalue->value = value;
|
||||
|
||||
int len = snprintf(pcfvalue->label, MAX_PCF_LABEL, "%s", label);
|
||||
if(len >= MAX_PCF_LABEL)
|
||||
die("PCF label too long\n");
|
||||
die("PCF value label too long\n");
|
||||
|
||||
HASH_ADD_INT(type->values, value, pv);
|
||||
HASH_ADD_INT(type->values, value, pcfvalue);
|
||||
|
||||
type->nvalues++;
|
||||
|
||||
return pv;
|
||||
return pcfvalue;
|
||||
}
|
||||
|
||||
/** Writes the defined event and values to the PCF file. */
|
||||
|
Loading…
Reference in New Issue
Block a user