diff --git a/emu.h b/emu.h index 1d4488e..0271fe1 100644 --- a/emu.h +++ b/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 }, diff --git a/emu_nosv.c b/emu_nosv.c index db70d81..6915b89 100644 --- a/emu_nosv.c +++ b/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++) diff --git a/pcf.c b/pcf.c index cb427ac..ee5ac5c 100644 --- a/pcf.c +++ b/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; - HASH_ADD_INT(pcf->types, id, type); + int len = snprintf(pcftype->label, MAX_PCF_LABEL, "%s", label); + if(len >= MAX_PCF_LABEL) + die("PCF type label too long\n"); - return type; + HASH_ADD_INT(pcf->types, id, pcftype); + + return pcftype; +} + +struct pcf_value * +pcf_find_value(struct pcf_type *type, int value) +{ + struct pcf_value *pcfvalue; + + 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. */ diff --git a/pcf.h b/pcf.h index 656038d..df1fde6 100644 --- a/pcf.h +++ b/pcf.h @@ -64,4 +64,6 @@ struct pcf_type *pcf_add_type(struct pcf_file *pcf, int type_id, struct pcf_value *pcf_add_value(struct pcf_type *type, int value, const char *label); +struct pcf_value *pcf_find_value(struct pcf_type *type, int value); + #endif /* OVNI_PCF_H */