diff --git a/src/emu/CMakeLists.txt b/src/emu/CMakeLists.txt index 6157f90..3bd09ac 100644 --- a/src/emu/CMakeLists.txt +++ b/src/emu/CMakeLists.txt @@ -28,6 +28,7 @@ add_library(emu STATIC path.c proc.c pv/pcf.c + pv/prf.c pv/prv.c pv/pvt.c recorder.c diff --git a/src/emu/pv/prf.c b/src/emu/pv/prf.c new file mode 100644 index 0000000..b92cf76 --- /dev/null +++ b/src/emu/pv/prf.c @@ -0,0 +1,80 @@ +#include "prf.h" + +#include +#include "common.h" + +int +prf_open(struct prf *prf, const char *path, long nrows) +{ + memset(prf, 0, sizeof(*prf)); + + prf->f = fopen(path, "w"); + + if (prf->f == NULL) { + err("cannot open ROW file '%s':", path); + return -1; + } + + prf->nrows = nrows; + prf->rows = calloc(nrows, sizeof(struct prf_row)); + + if (prf->rows == NULL) { + err("calloc failed:"); + return -1; + } + + return 0; +} + +int +prf_add(struct prf *prf, long index, const char *label) +{ + if (index < 0 || index >= prf->nrows) { + err("index out of bounds"); + return -1; + } + + struct prf_row *row = &prf->rows[index]; + if (row->set) { + err("row %ld already set to '%s'", index, row->label); + return -1; + } + + int n = snprintf(row->label, MAX_PRF_LABEL, "%s", label); + + if (n >= MAX_PRF_LABEL) { + err("label '%s' too long", label); + return -1; + } + + row->set = 1; + return 0; +} + +int +prf_close(struct prf *prf) +{ + for (long i = 0; i < prf->nrows; i++) { + struct prf_row *row = &prf->rows[i]; + if (!row->set) { + err("row %ld not set", i); + return -1; + } + } + + FILE *f = prf->f; + fprintf(f, "LEVEL NODE SIZE 1\n"); + fprintf(f, "hostname\n"); + fprintf(f, "\n"); + + fprintf(f, "LEVEL THREAD SIZE %ld\n", prf->nrows); + + for (long i = 0; i < prf->nrows; i++) { + struct prf_row *row = &prf->rows[i]; + fprintf(f, "%s\n", row->label); + } + + fclose(f); + + return 0; +} diff --git a/src/emu/pv/prf.h b/src/emu/pv/prf.h new file mode 100644 index 0000000..d9101ff --- /dev/null +++ b/src/emu/pv/prf.h @@ -0,0 +1,27 @@ +/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC) + * SPDX-License-Identifier: GPL-3.0-or-later */ + +#ifndef PRF_H +#define PRF_H + +#include + +#define MAX_PRF_LABEL 512 + +struct prf_row { + char label[MAX_PRF_LABEL]; + int set; +}; + +struct prf { + FILE *f; + long nrows; + struct prf_row *rows; +}; + +int prf_open(struct prf *prf, const char *path, long nrows); +int prf_add(struct prf *prf, long index, const char *name); +int prf_close(struct prf *prf); + + +#endif /* PRF_H */ diff --git a/src/emu/pv/pvt.c b/src/emu/pv/pvt.c index 4bdf08e..bfba7de 100644 --- a/src/emu/pv/pvt.c +++ b/src/emu/pv/pvt.c @@ -37,6 +37,17 @@ pvt_open(struct pvt *pvt, long nrows, const char *dir, const char *name) return -1; } + char prfpath[PATH_MAX]; + if (snprintf(prfpath, PATH_MAX, "%s/%s.row", dir, name) >= PATH_MAX) { + err("snprintf failed: path too long"); + return -1; + } + + if (prf_open(&pvt->prf, prfpath, nrows) != 0) { + err("prf_open failed"); + return -1; + } + return 0; } @@ -52,6 +63,12 @@ pvt_get_pcf(struct pvt *pvt) return &pvt->pcf; } +struct prf * +pvt_get_prf(struct pvt *pvt) +{ + return &pvt->prf; +} + int pvt_advance(struct pvt *pvt, int64_t time) { @@ -62,12 +79,17 @@ int pvt_close(struct pvt *pvt) { if (prv_close(&pvt->prv) != 0) { - err("prv_close failed"); + err("prv_close failed for '%s'", pvt->name); return -1; } if (pcf_close(&pvt->pcf) != 0) { - err("pcf_close failed"); + err("pcf_close failed for '%s'", pvt->name); + return -1; + } + + if (prf_close(&pvt->prf) != 0) { + err("prf_close failed for '%s'", pvt->name); return -1; } diff --git a/src/emu/pv/pvt.h b/src/emu/pv/pvt.h index 2984f11..6ba40fc 100644 --- a/src/emu/pv/pvt.h +++ b/src/emu/pv/pvt.h @@ -6,6 +6,7 @@ #include "prv.h" #include "pcf.h" +#include "prf.h" #include "uthash.h" #include @@ -14,6 +15,7 @@ struct pvt { char name[PATH_MAX]; /* Without .prv extension */ struct prv prv; struct pcf pcf; + struct prf prf; struct UT_hash_handle hh; /* For recorder */ }; @@ -21,6 +23,7 @@ struct pvt { int pvt_open(struct pvt *pvt, long nrows, const char *dir, const char *name); struct prv *pvt_get_prv(struct pvt *pvt); struct pcf *pvt_get_pcf(struct pvt *pvt); +struct prf *pvt_get_prf(struct pvt *pvt); int pvt_advance(struct pvt *pvt, int64_t time); int pvt_close(struct pvt *pvt); diff --git a/src/emu/system.c b/src/emu/system.c index 8cbfb74..4891993 100644 --- a/src/emu/system.c +++ b/src/emu/system.c @@ -533,11 +533,14 @@ int system_connect(struct system *sys, struct bay *bay, struct recorder *rec) { /* Create Paraver traces */ - if (recorder_add_pvt(rec, "cpu", sys->ncpus) == NULL) { + struct pvt *pvt_cpu = NULL; + if ((pvt_cpu = recorder_add_pvt(rec, "cpu", sys->ncpus)) == NULL) { err("recorder_add_pvt failed"); return -1; } - if (recorder_add_pvt(rec, "thread", sys->nthreads) == NULL) { + + struct pvt *pvt_th = NULL; + if ((pvt_th = recorder_add_pvt(rec, "thread", sys->nthreads)) == NULL) { err("recorder_add_pvt failed"); return -1; } @@ -547,6 +550,20 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec) err("thread_connect failed\n"); return -1; } + + struct prf *prf = pvt_get_prf(pvt_th); + char name[128]; + int appid = th->proc->appid; + int tid = th->tid; + if (snprintf(name, 128, "TH %d.%d", appid, tid) >= 128) { + err("label too long"); + return -1; + } + + if (prf_add(prf, th->gindex, name) != 0) { + err("prf_add failed for thread '%s'", th->id); + return -1; + } } for (struct cpu *cpu = sys->cpus; cpu; cpu = cpu->next) { @@ -554,6 +571,12 @@ system_connect(struct system *sys, struct bay *bay, struct recorder *rec) err("cpu_connect failed\n"); return -1; } + + struct prf *prf = pvt_get_prf(pvt_cpu); + if (prf_add(prf, cpu->gindex, cpu->name) != 0) { + err("prf_add failed for cpu '%s'", cpu->name); + return -1; + } } return 0;