commit 1092faebf348952917649344d8c8cf7eddd32ac9 Author: Rodrigo Arias Mallo Date: Mon Jul 19 15:11:41 2021 +0200 Initial commit diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..a5f350e --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +CFLAGS=-g -O0 -fPIC + +CFLAGS+=-fsanitize=address +LDFLAGS+=-fsanitize=address + +BIN=dump libovni.a + +all: $(BIN) + +libovni.a: ovni.o + ar -crs $@ $^ + +dump: ovni.o dump.o + +clean: + rm -f *.o $(BIN) diff --git a/def.h b/def.h new file mode 100644 index 0000000..368816c --- /dev/null +++ b/def.h @@ -0,0 +1,51 @@ +#ifndef OVNI_DEF_H +#define OVNI_DEF_H + +#define MAX_CPU 256 +#define MAX_PROC 32 +#define MAX_LOOM 4 +#define TRACEDIR "ovni" + +struct ovnithr { + int cpu; + uint64_t clockvalue; +}; + +struct ovniproc { + int proc; + int loom; + int ncpus; + FILE *cpustream[MAX_CPU]; + atomic_int opened[MAX_CPU]; + char dir[PATH_MAX]; + clockid_t clockid; +}; + +struct ovniloom { + int nprocs; + struct ovniproc proc[MAX_PROC]; +}; + +struct __attribute__((__packed__)) ovnievent { + uint64_t clock; + uint8_t fsm; + uint8_t event; + int32_t data; +}; + +struct ovnistream { + FILE *f; + int cpu; + int loaded; + int active; + struct ovnievent last; +}; + +struct ovnitrace { + int nlooms; + struct ovniloom loom[MAX_LOOM]; + int nstreams; + struct ovnistream *stream; +}; + +#endif /* OVNI_DEF_H */ diff --git a/dump.c b/dump.c new file mode 100644 index 0000000..392e7a4 --- /dev/null +++ b/dump.c @@ -0,0 +1,289 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "def.h" + +int load_proc(struct ovniproc *proc, char *procdir) +{ + FILE *f; + int cpu; + char path[PATH_MAX]; + + for(cpu=0; cpucpustream[cpu] = f; + } + + proc->ncpus = cpu; + + return 0; +} + +int load_loom(struct ovniloom *loom, char *loomdir) +{ + int proc; + char path[PATH_MAX]; + struct stat st; + + for(proc=0; procproc[proc], path)) + return -1; + } + + loom->nprocs = proc; + + return 0; +} + +int load_trace(struct ovnitrace *trace, char *tracedir) +{ + int loom, nlooms; + char path[PATH_MAX]; + + /* TODO: For now only one loom */ + nlooms = 1; + loom = 0; + + sprintf(path, "%s/loom.%d", tracedir, loom); + + if(load_loom(&trace->loom[loom], path)) + return -1; + + trace->nlooms = nlooms; + + return 0; +} + +/* Populates the streams in a single array */ +int load_streams(struct ovnitrace *trace) +{ + int i, j, k, s; + struct ovniloom *loom; + struct ovniproc *proc; + struct ovnistream *stream; + + trace->nstreams = 0; + + for(i=0; inlooms; i++) + { + loom = &trace->loom[i]; + for(j=0; jnprocs; j++) + { + proc = &loom->proc[j]; + for(k=0; kncpus; k++) + { + trace->nstreams++; + } + } + } + + trace->stream = calloc(trace->nstreams, sizeof(struct ovnistream)); + + if(trace->stream == NULL) + { + perror("calloc"); + return -1; + } + + fprintf(stderr, "loaded %d streams\n", trace->nstreams); + + for(s=0, i=0; inlooms; i++) + { + loom = &trace->loom[i]; + for(j=0; jnprocs; j++) + { + proc = &loom->proc[j]; + for(k=0; kncpus; k++) + { + stream = &trace->stream[s++]; + stream->f = proc->cpustream[k]; + stream->cpu = k; + stream->active = 1; + } + } + } + + return 0; +} + +int load_first_event(struct ovnitrace *trace) +{ + int i; + struct ovnistream *stream; + struct ovnievent *ev; + + for(i=0; instreams; i++) + { + stream = &trace->stream[i]; + ev = &stream->last; + if(fread(ev, sizeof(*ev), 1, stream->f) != 1) + { + fprintf(stderr, "failed to read and event\n"); + return -1; + } + + fprintf(stderr, "ev clock %u\n", ev->clock); + } + + return 0; +} + +void emit(struct ovnievent *ev, int cpu) +{ + static uint64_t lastclock = 0; + uint64_t delta; + + delta = ev->clock - lastclock; + + printf("%d %c %c %d %020lu (+%lu) ns\n", + cpu, ev->fsm, ev->event, ev->data, ev->clock, delta); + + lastclock = ev->clock; +} + +void load_next_event(struct ovnistream *stream) +{ + int i; + size_t n; + struct ovnievent *ev; + + if(!stream->active) + return; + + ev = &stream->last; + if((n = fread(ev, sizeof(*ev), 1, stream->f)) != 1) + { + //fprintf(stderr, "failed to read an event, n=%ld\n", n); + stream->active = 0; + return; + } + + stream->active = 1; +} + +void dump_events(struct ovnitrace *trace) +{ + int i, f; + uint64_t minclock, lastclock; + struct ovnievent *ev; + struct ovnistream *stream; + + /* Load events */ + for(i=0; instreams; i++) + { + stream = &trace->stream[i]; + load_next_event(stream); + } + + lastclock = 0; + + while(1) + { + f = -1; + minclock = 0; + + /* Select next event based on the clock */ + for(i=0; instreams; i++) + { + stream = &trace->stream[i]; + + if(!stream->active) + continue; + + ev = &stream->last; + if(f < 0 || ev->clock < minclock) + { + f = i; + minclock = ev->clock; + } + } + + //fprintf(stderr, "f=%d minclock=%u\n", f, minclock); + + if(f < 0) + break; + + stream = &trace->stream[f]; + + if(lastclock >= stream->last.clock) + { + fprintf(stderr, "warning: backwards jump in time\n"); + } + + /* Emit current event */ + emit(&stream->last, stream->cpu); + + lastclock = stream->last.clock; + + /* Read the next one */ + load_next_event(stream); + + /* Unset the index */ + f = -1; + minclock = 0; + + } +} + +void free_streams(struct ovnitrace *trace) +{ + free(trace->stream); +} + +int main(int argc, char *argv[]) +{ + char *tracedir; + struct ovnitrace trace; + + if(argc != 2) + { + fprintf(stderr, "missing tracedir\n"); + exit(EXIT_FAILURE); + } + + tracedir = argv[1]; + + if(load_trace(&trace, tracedir)) + return 1; + + if(load_streams(&trace)) + return 1; + + dump_events(&trace); + + free_streams(&trace); + + return 0; +} diff --git a/ovni.c b/ovni.c new file mode 100644 index 0000000..6b144ff --- /dev/null +++ b/ovni.c @@ -0,0 +1,230 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ovni.h" +#include "def.h" + +/* Data per process */ +struct ovniproc ovniproc = {0}; + +/* Data per thread */ +_Thread_local struct ovnithr ovnithr = {0}; + +static int +create_trace_dirs(char *tracedir, int loom, int proc) +{ + char path[PATH_MAX]; + + fprintf(stderr, "create trace dirs for loom=%d, proc=%d\n", + loom, proc); + + snprintf(path, PATH_MAX, "%s", tracedir); + + if(mkdir(path, 0755)) + { + fprintf(stderr, "mkdir %s: %s\n", path, strerror(errno)); + //return -1; + } + + snprintf(path, PATH_MAX, "%s/loom.%d", tracedir, loom); + + if(mkdir(path, 0755)) + { + fprintf(stderr, "mkdir %s: %s\n", path, strerror(errno)); + //return -1; + } + + snprintf(ovniproc.dir, PATH_MAX, "%s/loom.%d/proc.%d", tracedir, loom, proc); + + if(mkdir(ovniproc.dir, 0755)) + { + fprintf(stderr, "mkdir %s: %s\n", ovniproc.dir, strerror(errno)); + return -1; + } + + return 0; +} + +static int +create_trace_streams(int ncpus) +{ + char path[PATH_MAX]; + int i; + + for(i=0; i> 6; + ovnithr.clockvalue = (uint64_t) raw; + + return 0; +} + +//static void +//pack_int64(uint8_t **q, int64_t n) +//{ +// uint8_t *p = *q; +// +// *p++ = (n >> 0) & 0xff; +// *p++ = (n >> 8) & 0xff; +// *p++ = (n >> 16) & 0xff; +// *p++ = (n >> 24) & 0xff; +// *p++ = (n >> 32) & 0xff; +// *p++ = (n >> 40) & 0xff; +// *p++ = (n >> 48) & 0xff; +// *p++ = (n >> 56) & 0xff; +// +// *q = p; +//} + +static void +pack_uint32(uint8_t **q, uint32_t n) +{ + uint8_t *p = *q; + + *p++ = (n >> 0) & 0xff; + *p++ = (n >> 8) & 0xff; + *p++ = (n >> 16) & 0xff; + *p++ = (n >> 24) & 0xff; + + *q = p; +} + +static void +pack_uint8(uint8_t **q, uint8_t n) +{ + uint8_t *p = *q; + + *p++ = n; + + *q = p; +} + +static int +ovni_write(uint8_t *buf, size_t size) +{ + FILE *f; + int i, j; + + printf("writing %ld bytes in cpu=%d\n", size, ovnithr.cpu); + + for(i=0; i 1) + { + fprintf(stderr, "the stream for cpu.%d is already in use\n", cpu); + abort(); + } +} + +void +ovni_stream_close(int cpu) +{ + atomic_fetch_sub(&ovniproc.opened[cpu], 1); +} diff --git a/ovni.h b/ovni.h new file mode 100644 index 0000000..ca764a5 --- /dev/null +++ b/ovni.h @@ -0,0 +1,22 @@ +#ifndef OVNI_H +#define OVNI_H + +int +ovni_init(int loom, int proc, int ncpus); + +int +ovni_clock_update(); + +int +ovni_ev_worker(uint8_t fsm, uint8_t event, int32_t data); + +void +ovni_cpu_set(int cpu); + +void +ovni_stream_open(int cpu); + +void +ovni_stream_close(int cpu); + +#endif /* OVNI_H */