From c22457d7d308a583a8a8e203b3f142d86742f7e6 Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Date: Tue, 31 May 2022 20:39:57 +0200 Subject: [PATCH] Add dynamic PCF types and values --- emu.c | 50 ++--- emu.h | 13 +- pcf.c | 607 ++++++++++++++++++++++++++-------------------------------- pcf.h | 46 ++++- 4 files changed, 347 insertions(+), 369 deletions(-) diff --git a/emu.c b/emu.c index 0ca08e0..b7d24c2 100644 --- a/emu.c +++ b/emu.c @@ -737,26 +737,10 @@ open_pcfs(struct ovni_emu *emu, char *tracedir) char path[PATH_MAX]; sprintf(path, "%s/%s", tracedir, "thread.pcf"); - - emu->pcf_thread = fopen(path, "w"); - - if(emu->pcf_thread == NULL) - { - err("error opening thread PCF file %s: %s\n", path, - strerror(errno)); - exit(EXIT_FAILURE); - } + pcf_open(&emu->pcf[CHAN_TH], path, CHAN_TH); sprintf(path, "%s/%s", tracedir, "cpu.pcf"); - - emu->pcf_cpu = fopen(path, "w"); - - if(emu->pcf_cpu == NULL) - { - err("error opening cpu PCF file %s: %s\n", path, - strerror(errno)); - exit(EXIT_FAILURE); - } + pcf_open(&emu->pcf[CHAN_CPU], path, CHAN_CPU); } /* Fix the trace duration at the end */ @@ -777,8 +761,8 @@ close_prvs(struct ovni_emu *emu) static void close_pcfs(struct ovni_emu *emu) { - fclose(emu->pcf_thread); - fclose(emu->pcf_cpu); + pcf_close(&emu->pcf[CHAN_TH]); + pcf_close(&emu->pcf[CHAN_CPU]); } static void @@ -1097,6 +1081,26 @@ init_cpus(struct ovni_emu *emu) } } +static void +create_pcf_cpus(struct ovni_emu *emu) +{ + /* Only needed for the thread PCF */ + struct pcf_file *pcf = &emu->pcf[CHAN_TH]; + int prvtype = CHAN_PRV_TH(CHAN_OVNI_CPU); + struct pcf_type *type = pcf_find_type(pcf, prvtype); + + if (type == NULL) + die("cannot find PCF type for CHAN_OVNI_CPU\n"); + + for(size_t i=0; itotal_ncpus; i++) + { + int value = i + 1; + char *label = emu->global_cpu[i]->name; + + pcf_add_value(type, value, label); + } +} + static void emu_init(struct ovni_emu *emu, int argc, char *argv[]) { @@ -1127,6 +1131,8 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[]) open_prvs(emu, emu->tracedir); open_pcfs(emu, emu->tracedir); + create_pcf_cpus(emu); + emu->global_size = 0; emu->global_offset = 0; @@ -1139,8 +1145,8 @@ static void emu_post(struct ovni_emu *emu) { /* Write the PCF files */ - pcf_write(emu->pcf_thread, emu); - pcf_write(emu->pcf_cpu, emu); + pcf_write(&emu->pcf[CHAN_TH]); + pcf_write(&emu->pcf[CHAN_CPU]); write_row_cpu(emu); write_row_thread(emu); diff --git a/emu.h b/emu.h index f8557dd..3469383 100644 --- a/emu.h +++ b/emu.h @@ -25,6 +25,7 @@ #include "uthash.h" #include "parson.h" #include "heap.h" +#include "pcf.h" /* Emulated thread runtime status */ enum ethread_state { @@ -163,10 +164,10 @@ enum chan { CHAN_MAX }; -enum chan_to_prv_type { - CHAN_ID = 0, - CHAN_TH = 1, - CHAN_CPU = 2, +enum chan_type { + CHAN_TH = 0, + CHAN_CPU = 1, + CHAN_MAXTYPE = 2, }; enum chan_dirty { @@ -468,8 +469,8 @@ struct ovni_emu { FILE *prv_thread; FILE *prv_cpu; - FILE *pcf_thread; - FILE *pcf_cpu; + + struct pcf_file pcf[CHAN_MAXTYPE]; char *clock_offset_file; char *tracedir; diff --git a/pcf.c b/pcf.c index 8c0372f..cb427ac 100644 --- a/pcf.c +++ b/pcf.c @@ -21,6 +21,7 @@ #include #include +#include const char *pcf_def_header = "DEFAULT_OPTIONS\n" @@ -72,91 +73,28 @@ const uint32_t pcf_def_palette[] = { LIGHTGREY, /* busy wait */ RED, /* task */ GREEN, - YELLOW, - ORANGE, - PURPLE, - CYAN, - MAGENTA, - LIME, - PINK, - TEAL, - GREY, - LAVENDER, - BROWN, - BEIGE, - MAROON, - MINT, - OLIVE, - APRICOT, - NAVY, - DEEPBLUE + YELLOW, ORANGE, PURPLE, CYAN, MAGENTA, LIME, PINK, + TEAL, GREY, LAVENDER, BROWN, BEIGE, MAROON, MINT, + OLIVE, APRICOT, NAVY, DEEPBLUE }; const uint32_t *pcf_palette = pcf_def_palette; const int pcf_palette_len = ARRAY_LEN(pcf_def_palette); -struct event_value { +/* Only used to generate tables */ +struct pcf_value_label { int value; - const char *label; + char *label; }; -struct event_type { - int index; - int chan_id; - int chan_type; - const char *label; - const struct event_value *values; -}; +/* ------------------ Value labels --------------------- */ -/* ---------------- CHAN_OVNI_PID ---------------- */ - -static const struct event_value ovni_pid_values[] = { - { 0, "None" }, - { ST_TOO_MANY_TH, "Unknown PID: Multiple threads running" }, - /* FIXME: PID values may collide with error code values */ +struct pcf_value_label default_values[] = { + { ST_TOO_MANY_TH, "Unknown: Multiple threads running" }, { -1, NULL }, }; -static const struct event_type thread_ovni_pid = { - 0, CHAN_OVNI_PID, CHAN_TH, - "Thread: PID of the RUNNING thread", - ovni_pid_values -}; - -static const struct event_type cpu_ovni_pid = { - 0, CHAN_OVNI_PID, CHAN_CPU, - "CPU: PID of the RUNNING thread", - ovni_pid_values -}; - -/* ---------------- CHAN_OVNI_TID ---------------- */ - -static const struct event_value ovni_tid_values[] = { - { 0, "None" }, - { ST_TOO_MANY_TH, "Unknown TID: Multiple threads running" }, - /* FIXME: TID values may collide with error code values */ - { -1, NULL }, -}; - -static const struct event_type thread_ovni_tid = { - 0, CHAN_OVNI_TID, CHAN_TH, - "Thread: TID of the RUNNING thread", - ovni_tid_values -}; - -static const struct event_type cpu_ovni_tid = { - 0, CHAN_OVNI_TID, CHAN_CPU, - "CPU: TID of the RUNNING thread", - ovni_tid_values -}; - -/* ---------------- CHAN_OVNI_NRTHREADS ---------------- */ - -/* Not used */ - -/* ---------------- CHAN_OVNI_STATE ---------------- */ - -static const struct event_value ovni_state_values[] = { +struct pcf_value_label ovni_state_values[] = { { TH_ST_UNKNOWN, "Unknown" }, { TH_ST_RUNNING, "Running" }, { TH_ST_PAUSED, "Paused" }, @@ -166,121 +104,25 @@ static const struct event_value ovni_state_values[] = { { -1, NULL }, }; -static const struct event_type thread_ovni_state = { - 0, CHAN_OVNI_STATE, CHAN_TH, - "Thread: State of the CURRENT thread", - ovni_state_values -}; - -/* PRV CPU not used for the state */ - -/* ---------------- CHAN_OVNI_APPID ---------------- */ - -/* Not used */ - -/* ---------------- CHAN_OVNI_CPU ---------------- */ - -static const struct event_type thread_cpu_affinity = { - 0, CHAN_OVNI_CPU, CHAN_TH, - "Thread: CPU affinity of the CURRENT thread", - /* Ignored */ NULL -}; - -/* ---------------- CHAN_OVNI_FLUSH ---------------- */ - -static const struct event_value ovni_flush_values[] = { +struct pcf_value_label ovni_flush_values[] = { { 0, "None" }, { ST_OVNI_FLUSHING, "Flushing" }, { ST_TOO_MANY_TH, "Unknown flushing state: Multiple threads running" }, { -1, NULL }, }; -static const struct event_type thread_ovni_flush = { - 0, CHAN_OVNI_FLUSH, CHAN_TH, - "Thread: Flushing state of the CURRENT thread", - ovni_flush_values -}; - -static const struct event_type cpu_ovni_flush = { - 0, CHAN_OVNI_FLUSH, CHAN_CPU, - "CPU: Flusing state of the RUNNING thread", - ovni_flush_values -}; - -/* ---------------- CHAN_NOSV_TASKID ---------------- */ - -static const struct event_value nosv_taskid_values[] = { - { ST_TOO_MANY_TH, "Unknown TaskID: Multiple threads running" }, - /* FIXME: Task ID values may collide with error code values */ - { -1, NULL }, -}; - -static const struct event_type thread_nosv_taskid = { - 0, CHAN_NOSV_TASKID, CHAN_TH, - "Thread: nOS-V TaskID of the RUNNING thread", - nosv_taskid_values -}; - -static const struct event_type cpu_nosv_taskid = { - 0, CHAN_NOSV_TASKID, CHAN_CPU, - "CPU: nOS-V TaskID of the RUNNING thread", - nosv_taskid_values -}; - -/* ---------------- CHAN_NOSV_TYPEID ---------------- */ - -static const struct event_value nosv_typeid_values[] = { - { ST_TOO_MANY_TH, "Unknown Task TypeID: Multiple threads running" }, - /* FIXME: Task ID values may collide with error code values */ - { -1, NULL }, -}; - -static const struct event_type thread_nosv_typeid = { - 0, CHAN_NOSV_TYPEID, CHAN_TH, - "Thread: nOS-V task TypeID of the RUNNING thread", - nosv_typeid_values -}; - -static const struct event_type cpu_nosv_typeid = { - 0, CHAN_NOSV_TYPEID, CHAN_CPU, - "CPU: nOS-V task TypeID of the RUNNING thread", - nosv_typeid_values -}; - -/* ---------------- CHAN_NOSV_APPID ---------------- */ - -static const struct event_value nosv_appid_values[] = { - { ST_TOO_MANY_TH, "Unknown Task AppID: Multiple threads running" }, - /* FIXME: Task ID values may collide with error code values */ - { -1, NULL }, -}; - -static const struct event_type thread_nosv_appid = { - 0, CHAN_NOSV_APPID, CHAN_TH, - "Thread: nOS-V task AppID of the RUNNING thread", - nosv_appid_values -}; - -static const struct event_type cpu_nosv_appid = { - 0, CHAN_NOSV_APPID, CHAN_CPU, - "CPU: nOS-V task AppID of the RUNNING thread", - nosv_appid_values -}; - -/* ---------------- CHAN_NOSV_SUBSYSTEM ---------------- */ - -static const struct event_value nosv_ss_values[] = { +struct pcf_value_label nosv_ss_values[] = { /* Errors */ - { ST_BAD, "Unknown subsystem: Bad happened (report bug)" }, - { ST_TOO_MANY_TH, "Unknown subsystem: Multiple threads running" }, + { ST_BAD, "Unknown: bad happened (report bug)" }, + { ST_TOO_MANY_TH, "Unknown: multiple threads running" }, /* Good values */ - { ST_NULL, "No subsystem" }, + { ST_NULL, "No subsystem" }, { ST_NOSV_SCHED_HUNGRY, "Scheduler: Hungry" }, { ST_NOSV_SCHED_SERVING, "Scheduler: Serving" }, { ST_NOSV_SCHED_SUBMITTING, "Scheduler: Submitting" }, - { ST_NOSV_TASK_RUNNING, "Task: Running" }, { 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" }, @@ -295,113 +137,123 @@ static const struct event_value nosv_ss_values[] = { { -1, NULL }, }; -static const struct event_type thread_nosv_ss = { - 0, CHAN_NOSV_SUBSYSTEM, CHAN_TH, - "Thread: nOS-V subsystem of the ACTIVE thread", - nosv_ss_values -}; - -static const struct event_type cpu_nosv_ss = { - 0, CHAN_NOSV_SUBSYSTEM, CHAN_CPU, - "CPU: nOS-V subsystem of the RUNNING thread", - nosv_ss_values -}; - -/* ---------------- CHAN_TAMPI_MODE ---------------- */ - -static const struct event_value tampi_mode_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "TAMPI: Unknown, multiple threads running" }, - { ST_TAMPI_SEND, "TAMPI: Send" }, - { ST_TAMPI_RECV, "TAMPI: Recv" }, - { ST_TAMPI_ISEND, "TAMPI: Isend" }, - { ST_TAMPI_IRECV, "TAMPI: Irecv" }, - { ST_TAMPI_WAIT, "TAMPI: Wait" }, - { ST_TAMPI_WAITALL, "TAMPI: Waitall" }, +struct pcf_value_label tampi_mode_values[] = { + { ST_NULL, "NULL" }, + { ST_TOO_MANY_TH, "TAMPI: Unknown, multiple threads running" }, + { ST_TAMPI_SEND, "TAMPI: Send" }, + { ST_TAMPI_RECV, "TAMPI: Recv" }, + { ST_TAMPI_ISEND, "TAMPI: Isend" }, + { ST_TAMPI_IRECV, "TAMPI: Irecv" }, + { ST_TAMPI_WAIT, "TAMPI: Wait" }, + { ST_TAMPI_WAITALL, "TAMPI: Waitall" }, { -1, NULL }, }; -static const struct event_type thread_tampi_mode = { - 0, CHAN_TAMPI_MODE, CHAN_TH, - "Thread: TAMPI mode of the RUNNING thread", - tampi_mode_values -}; - -static const struct event_type cpu_tampi_mode = { - 0, CHAN_TAMPI_MODE, CHAN_CPU, - "CPU: TAMPI mode of the RUNNING thread", - tampi_mode_values -}; - -/* ---------------- CHAN_OPENMP_MODE ---------------- */ - -static const struct event_value openmp_mode_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "OpenMP: Unknown, multiple threads running" }, - { ST_OPENMP_TASK, "OpenMP: Task" }, - { ST_OPENMP_PARALLEL, "OpenMP: Parallel" }, +struct pcf_value_label openmp_mode_values[] = { + { ST_NULL, "NULL" }, + { ST_TOO_MANY_TH, "OpenMP: Unknown, multiple threads running" }, + { ST_OPENMP_TASK, "OpenMP: Task" }, + { ST_OPENMP_PARALLEL, "OpenMP: Parallel" }, { -1, NULL }, }; -static const struct event_type thread_openmp_mode = { - 0, CHAN_OPENMP_MODE, CHAN_TH, - "Thread: OpenMP mode of the RUNNING thread", - openmp_mode_values -}; - -static const struct event_type cpu_openmp_mode = { - 0, CHAN_OPENMP_MODE, CHAN_CPU, - "CPU: OpenMP mode of the RUNNING thread", - openmp_mode_values -}; - -/* ---------------- CHAN_NODES_SUBSYSTEM ---------------- */ - -static const struct event_value nodes_mode_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "NODES: Multiple threads running" }, - { ST_NODES_REGISTER, "Dependencies: Registering task accesses" }, - { ST_NODES_UNREGISTER, "Dependencies: Unregistering task accesses" }, - { ST_NODES_IF0_WAIT, "If0: Waiting for an If0 task" }, - { ST_NODES_IF0_INLINE, "If0: Executing an If0 task inline" }, - { ST_NODES_TASKWAIT, "Taskwait: Taskwait" }, - { ST_NODES_CREATE, "Add Task: Creating a task" }, - { ST_NODES_SUBMIT, "Add Task: Submitting a task" }, - { ST_NODES_SPAWN, "Spawn Function: Spawning a function" }, +struct pcf_value_label nodes_mode_values[] = { + { ST_NULL, "NULL" }, + { ST_TOO_MANY_TH, "NODES: Multiple threads running" }, + { ST_NODES_REGISTER, "Dependencies: Registering task accesses" }, + { ST_NODES_UNREGISTER, "Dependencies: Unregistering task accesses" }, + { ST_NODES_IF0_WAIT, "If0: Waiting for an If0 task" }, + { ST_NODES_IF0_INLINE, "If0: Executing an If0 task inline" }, + { ST_NODES_TASKWAIT, "Taskwait: Taskwait" }, + { ST_NODES_CREATE, "Add Task: Creating a task" }, + { ST_NODES_SUBMIT, "Add Task: Submitting a task" }, + { ST_NODES_SPAWN, "Spawn Function: Spawning a function" }, { -1, NULL }, }; -static const struct event_type cpu_nodes_mode = { - 0, CHAN_NODES_SUBSYSTEM, CHAN_CPU, - "CPU: NODES subsystem of the RUNNING thread", - nodes_mode_values -}; - -static const struct event_type thread_nodes_mode = { - 0, CHAN_NODES_SUBSYSTEM, CHAN_TH, - "Thread: NODES subsystem of the RUNNING thread", - nodes_mode_values -}; - -/* ---------------- CHAN_KERNEL_CS ---------------- */ - -struct event_value kernel_cs_values[] = { - { ST_NULL, "NULL" }, - { ST_TOO_MANY_TH, "Kernel CS: Unknown, multiple threads running" }, - { ST_KERNEL_CSOUT, "Context switch: Out of the CPU" }, +struct pcf_value_label kernel_cs_values[] = { + { ST_NULL, "NULL" }, + { ST_TOO_MANY_TH, "Unknown: multiple threads running" }, + { ST_KERNEL_CSOUT, "Context switch: Out of the CPU" }, { -1, NULL }, }; -struct event_type cpu_kernel_cs = { - 0, CHAN_KERNEL_CS, CHAN_CPU, - "CPU: Context switches of the ACTIVE thread", - kernel_cs_values +struct pcf_value_label (*pcf_chan_value_labels[CHAN_MAX])[] = { + [CHAN_OVNI_PID] = &default_values, + [CHAN_OVNI_TID] = &default_values, + [CHAN_OVNI_NRTHREADS] = &default_values, + [CHAN_OVNI_STATE] = &ovni_state_values, + [CHAN_OVNI_APPID] = &default_values, + [CHAN_OVNI_CPU] = &default_values, + [CHAN_OVNI_FLUSH] = &ovni_flush_values, + + [CHAN_NOSV_TASKID] = &default_values, + [CHAN_NOSV_TYPEID] = &default_values, + [CHAN_NOSV_APPID] = &default_values, + [CHAN_NOSV_SUBSYSTEM] = &nosv_ss_values, + [CHAN_NOSV_RANK] = &default_values, + + [CHAN_TAMPI_MODE] = &tampi_mode_values, + [CHAN_OPENMP_MODE] = &openmp_mode_values, + [CHAN_NODES_SUBSYSTEM] = &nodes_mode_values, + + [CHAN_KERNEL_CS] = &kernel_cs_values, }; -struct event_type thread_kernel_cs = { - 0, CHAN_KERNEL_CS, CHAN_TH, - "Thread: Context switches of the CURRENT thread", - kernel_cs_values +/* ------------------ Type labels --------------------- */ + +char *pcf_chan_name[CHAN_MAX] = { + [CHAN_OVNI_PID] = "PID", + [CHAN_OVNI_TID] = "TID", + [CHAN_OVNI_NRTHREADS] = "Number of RUNNING threads", + [CHAN_OVNI_STATE] = "Execution state", + [CHAN_OVNI_APPID] = "AppID", + [CHAN_OVNI_CPU] = "CPU affinity", + [CHAN_OVNI_FLUSH] = "Flushing state", + + [CHAN_NOSV_TASKID] = "nOS-V TaskID", + [CHAN_NOSV_TYPEID] = "nOS-V task TypeID", + [CHAN_NOSV_APPID] = "nOS-V task AppID", + [CHAN_NOSV_SUBSYSTEM] = "nOS-V subsystem", + [CHAN_NOSV_RANK] = "MPI rank", + + [CHAN_TAMPI_MODE] = "TAMPI mode", + [CHAN_OPENMP_MODE] = "OpenMP mode", + [CHAN_NODES_SUBSYSTEM] = "NODES subsystem", + + [CHAN_KERNEL_CS] = "Context switches", +}; + +enum pcf_suffix { NONE = 0, CUR_TH, RUN_TH, ACT_TH, SUFFIX_MAX }; + +char *pcf_suffix_name[SUFFIX_MAX] = { + [NONE] = "", + [CUR_TH] = "of the CURRENT thread", + [RUN_TH] = "of the RUNNING thread", + [ACT_TH] = "of the ACTIVE thread", +}; + +int pcf_chan_suffix[CHAN_MAX][CHAN_MAXTYPE] = { + /* Thread CPU */ + [CHAN_OVNI_PID] = { CUR_TH, CUR_TH }, + [CHAN_OVNI_TID] = { CUR_TH, CUR_TH }, + [CHAN_OVNI_NRTHREADS] = { NONE, NONE }, + [CHAN_OVNI_STATE] = { CUR_TH, NONE }, + [CHAN_OVNI_APPID] = { NONE, RUN_TH }, + [CHAN_OVNI_CPU] = { CUR_TH, NONE }, + [CHAN_OVNI_FLUSH] = { CUR_TH, RUN_TH }, + + [CHAN_NOSV_TASKID] = { RUN_TH, RUN_TH }, + [CHAN_NOSV_TYPEID] = { 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 }, + + [CHAN_TAMPI_MODE] = { RUN_TH, RUN_TH }, + [CHAN_OPENMP_MODE] = { RUN_TH, RUN_TH }, + [CHAN_NODES_SUBSYSTEM] = { RUN_TH, RUN_TH }, + + [CHAN_KERNEL_CS] = { CUR_TH, ACT_TH }, }; /* ----------------------------------------------- */ @@ -437,94 +289,173 @@ write_colors(FILE *f, const uint32_t *palette, int n) } static void -write_event_type_header(FILE *f, int index, int type, const char *label) +write_type(FILE *f, struct pcf_type *type) { fprintf(f, "\n\n"); fprintf(f, "EVENT_TYPE\n"); - fprintf(f, "%-4d %-10d %s\n", index, type, label); -} - -static void -write_event_type(FILE *f, const struct event_type *ev) -{ - int i, type; - - type = chan_to_prvtype[ev->chan_id][ev->chan_type]; - write_event_type_header(f, ev->index, type, ev->label); - + fprintf(f, "0 %-10d %s\n", type->id, type->label); fprintf(f, "VALUES\n"); - for(i=0; ev->values[i].label; i++) - { - fprintf(f, "%-4d %s\n", - ev->values[i].value, - ev->values[i].label); - } + for(struct pcf_value *v = type->values; v != NULL; v = v->hh.next) + fprintf(f, "%-4d %s\n", v->value, v->label); } static void -write_cpu_type(FILE *f, const struct event_type *ev, struct ovni_emu *emu) +write_types(struct pcf_file *pcf) { - size_t i; - int type; + struct pcf_type *t; - type = chan_to_prvtype[ev->chan_id][ev->chan_type]; - write_event_type_header(f, ev->index, type, ev->label); - - fprintf(f, "VALUES\n"); - - for(i=0; itotal_ncpus; i++) - { - fprintf(f, "%-4ld %s\n", i+1, emu->global_cpu[i]->name); - } + for(t = pcf->types; t != NULL; t = t->hh.next) + write_type(pcf->f, t); } static void -write_events(FILE *f, struct ovni_emu *emu) +create_values(struct pcf_type *t, enum chan c) { - /* Threads */ - write_event_type(f, &thread_ovni_pid); - write_event_type(f, &thread_ovni_tid); - /* thread_ovni_nthreads not needed */ - write_event_type(f, &thread_ovni_state); - /* thread_ovni_appid not needed */ - write_event_type(f, &thread_ovni_flush); - write_event_type(f, &thread_nosv_taskid); - write_event_type(f, &thread_nosv_typeid); - write_event_type(f, &thread_nosv_appid); - write_event_type(f, &thread_nosv_ss); - write_event_type(f, &thread_tampi_mode); - write_event_type(f, &thread_openmp_mode); - write_event_type(f, &thread_nodes_mode); - write_event_type(f, &thread_kernel_cs); + struct pcf_value_label (*q)[] = pcf_chan_value_labels[c]; - /* CPU */ - write_event_type(f, &cpu_ovni_pid); - write_event_type(f, &cpu_ovni_tid); - /* cpu_ovni_nthreads not needed */ - /* cpu_ovni_state not needed */ - /* cpu_ovni_appid not needed */ - /* cpu_ovni_cpu not needed */ - write_event_type(f, &cpu_ovni_flush); - write_event_type(f, &cpu_nosv_taskid); - write_event_type(f, &cpu_nosv_typeid); - write_event_type(f, &cpu_nosv_appid); - write_event_type(f, &cpu_nosv_ss); - write_event_type(f, &cpu_tampi_mode); - write_event_type(f, &cpu_openmp_mode); - write_event_type(f, &cpu_nodes_mode); - write_event_type(f, &cpu_kernel_cs); + if(q == NULL) + return; - /* Custom */ - write_cpu_type(f, &thread_cpu_affinity, emu); + for(struct pcf_value_label *p = *q; p->label != NULL; p++) + pcf_add_value(t, p->value, p->label); } -int -pcf_write(FILE *f, struct ovni_emu *emu) +static void +create_type(struct pcf_file *pcf, enum chan c) { - write_header(f); - write_colors(f, pcf_palette, pcf_palette_len); - write_events(f, emu); + char label[MAX_PCF_LABEL]; + enum chan_type ct = pcf->chantype; + int prv_type = chan_to_prvtype[c][ct]; - return 0; + if(prv_type == -1) + return; + + /* Compute the label by joining the two parts */ + char *prefix = pcf_chan_name[c]; + int isuffix = pcf_chan_suffix[c][ct]; + char *suffix = pcf_suffix_name[isuffix]; + + int ret = snprintf(label, MAX_PCF_LABEL, "%s %s", + prefix, suffix); + + if(ret >= MAX_PCF_LABEL) + die("computed type label too long\n"); + + struct pcf_type *t = pcf_add_type(pcf, prv_type, label); + + create_values(t, c); +} + +/** Open the given PCF file and create the default events. */ +void +pcf_open(struct pcf_file *pcf, char *path, int chantype) +{ + memset(pcf, 0, sizeof(*pcf)); + + pcf->f = fopen(path, "w"); + pcf->chantype = chantype; + + if(pcf->f == NULL) + { + die("cannot open PCF file '%s': %s\n", + path, strerror(errno)); + } + + /* Create default types and values */ + for(enum chan c = 0; c < CHAN_MAX; c++) + create_type(pcf, c); +} + +struct pcf_type * +pcf_find_type(struct pcf_file *pcf, int type_id) +{ + struct pcf_type *type; + + HASH_FIND_INT(pcf->types, &type_id, type); + + return type; +} + +/** Creates a new pcf_type with the given type_id and label. The label + * can be disposed after return. + * + * @return The pcf_type created. + */ +struct pcf_type * +pcf_add_type(struct pcf_file *pcf, int type_id, const char *label) +{ + struct pcf_type *type; + + type = pcf_find_type(pcf, type_id); + + if(type != NULL) + die("PCF type %d already defined\n", type_id); + + type = calloc(1, sizeof(struct pcf_type)); + + if(type == 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"); + } + + HASH_ADD_INT(pcf->types, id, type); + + return type; +} + +/** Adds a new value to the given pcf_type. The label can be disposed + * after return. + * + * @return The new pcf_value created + */ +struct pcf_value * +pcf_add_value(struct pcf_type *type, int value, const char *label) +{ + struct pcf_value *pv; + + HASH_FIND_INT(type->values, &value, pv); + + if(pv != NULL) + die("PCF value %d already in type %d\n", value, type->id); + + pv = calloc(1, sizeof(struct pcf_value)); + + if(pv == NULL) + die("calloc failed: %s\n", strerror(errno)); + + pv->value = value; + + int len = snprintf(pv->label, MAX_PCF_LABEL, "%s", label); + + if(len >= MAX_PCF_LABEL) + die("PCF label too long\n"); + + HASH_ADD_INT(type->values, value, pv); + + type->nvalues++; + + return pv; +} + +/** Writes the defined event and values to the PCF file. */ +void +pcf_write(struct pcf_file *pcf) +{ + write_header(pcf->f); + write_colors(pcf->f, pcf_palette, pcf_palette_len); + write_types(pcf); +} + +void +pcf_close(struct pcf_file *pcf) +{ + fclose(pcf->f); } diff --git a/pcf.h b/pcf.h index 931d21c..656038d 100644 --- a/pcf.h +++ b/pcf.h @@ -19,9 +19,49 @@ #define OVNI_PCF_H #include -#include "emu.h" +#include "uthash.h" -int -pcf_write(FILE *f, struct ovni_emu *emu); +#define MAX_PCF_LABEL 512 + +struct pcf_value; +struct pcf_type; + +struct pcf_value { + int value; + char label[MAX_PCF_LABEL]; + + UT_hash_handle hh; +}; + +struct pcf_type { + int id; + char label[MAX_PCF_LABEL]; + + int nvalues; + struct pcf_value *values; + + UT_hash_handle hh; +}; + +struct pcf_file { + FILE *f; + int chantype; + int pcf_ntypes; + struct pcf_type *types; +}; + +void pcf_open(struct pcf_file *pcf, char *path, int chantype); + +void pcf_write(struct pcf_file *pcf); + +void pcf_close(struct pcf_file *pcf); + +struct pcf_type *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_value *pcf_add_value(struct pcf_type *type, int value, + const char *label); #endif /* OVNI_PCF_H */