diff --git a/Makefile b/Makefile index 0301194..169b76c 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,17 @@ CFLAGS=-fPIC +# Debug CFLAGS #CFLAGS+=-fsanitize=address #LDFLAGS+=-fsanitize=address #CFLAGS+=-g -O0 + +# Performance CFLAGS CFLAGS+=-O3 CFLAGS+=-fstack-protector-explicit +CFLAGS+=-flto -BIN=dump libovni.a prvth test_speed +BIN=dump libovni.a test_speed ovni2prv +#BIN=dump libovni.a prvth test_speed emu all: $(BIN) @@ -17,5 +22,9 @@ dump: ovni.o dump.o test_speed: test_speed.c ovni.o +emu: emu.c ovni.o + +ovni2prv: ovni2prv.c ovni.o + clean: rm -f *.o $(BIN) diff --git a/def.h b/def.h index cc2abd1..f587908 100644 --- a/def.h +++ b/def.h @@ -1,121 +1,5 @@ #ifndef OVNI_DEF_H #define OVNI_DEF_H -#define MAX_CPU 256 -#define MAX_PROC 32 -#define MAX_THR 32 -#define MAX_LOOM 4 -#define TRACEDIR "ovni" - -#define MAX_EV (16*1024) /* 16 kev per thread */ -//#define MAX_EV (16) /* 16 ev per thread */ - -/* ----------------------- common ------------------------ */ - -enum thread_state { - ST_THREAD_UNINIT = 0, - ST_THREAD_INIT = 1 -}; - -struct __attribute__((__packed__)) event { - uint64_t clock; - uint8_t fsm; - uint8_t event; - uint16_t a; - uint16_t b; -}; - -/* ----------------------- runtime ------------------------ */ - -/* State of each thread on runtime */ -struct rthread { - /* Current cpu the thread is running on. Set to -1 if unbounded or - * unknown */ - int cpu; - - /* Current thread id */ - pid_t tid; - - /* Clock value of the events being emitted */ - uint64_t clockvalue; - - /* Stream trace file descriptor */ - int streamfd; - - int ready; - - /* Buffer to write events */ - int nevents; - struct event events[MAX_EV]; -}; - -/* State of each process on runtime */ -struct rproc { - /* Path of the process tracedir */ - char dir[PATH_MAX]; - - int proc; - int loom; - int ncpus; - clockid_t clockid; - char procdir[PATH_MAX]; - - int ready; -}; - -/* ----------------------- emulated ------------------------ */ - -/* State of each thread on post-process */ -struct ethread { - /* Emulated thread tid */ - pid_t tid; - - /* Stream file */ - FILE *f; - - /* Thread stream */ - struct stream *stream; -}; - -/* State of each process on post-process */ -struct eproc { - /* Monotonic counter for process index */ - /* TODO: Use pid? */ - int proc; - - /* Path of the process tracedir */ - char dir[PATH_MAX]; - - /* Threads */ - size_t nthreads; - struct ethread thread[MAX_THR]; -}; - -/* ----------------------- trace ------------------------ */ - -/* State of each loom on post-process */ -struct loom { - size_t nprocs; - struct eproc proc[MAX_PROC]; -}; - -struct stream { - FILE *f; - int tid; - int thread; - int proc; - int loom; - int loaded; - int active; - struct event last; - uint64_t lastclock; -}; - -struct trace { - int nlooms; - struct loom loom[MAX_LOOM]; - int nstreams; - struct stream *stream; -}; #endif /* OVNI_DEF_H */ diff --git a/dump.c b/dump.c index 1f7ed52..7fd2435 100644 --- a/dump.c +++ b/dump.c @@ -8,238 +8,76 @@ #include #include -#include "def.h" +#include "ovni.h" -int load_proc(struct eproc *proc, char *procdir) +#define ENABLE_DEBUG + +#ifdef ENABLE_DEBUG +#define dbg(...) fprintf(stderr, __VA_ARGS__); +#else +#define dbg(...) +#endif + +#define err(...) fprintf(stderr, __VA_ARGS__); + + +static void +hexdump(uint8_t *buf, size_t size) { - struct dirent *dirent; - DIR *dir; - char path[PATH_MAX]; - char *p; - struct ethread *thread; + int i, j; - if((dir = opendir(procdir)) == NULL) + //printf("writing %ld bytes in cpu=%d\n", size, rthread.cpu); + + for(i=0; id_name[0] != 't') - continue; - p = strchr(dirent->d_name, '.'); - if(p == NULL) - continue; - p++; - if(*p == '\0') + for(j=0; j<16 && i+j < size; j++) { - fprintf(stderr, "bad thread stream file: %s\n", - dirent->d_name); - return -1; - } - - - thread = &proc->thread[proc->nthreads++]; - thread->tid = atoi(p); - - sprintf(path, "%s/%s", procdir, dirent->d_name); - thread->f = fopen(path, "r"); - - if(thread->f == NULL) - { - fprintf(stderr, "fopen %s failed: %s\n", - path, strerror(errno)); - return -1; + fprintf(stderr, "%02x ", buf[i+j]); } + fprintf(stderr, "\n"); } - - closedir(dir); - - return 0; } -int load_loom(struct loom *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 trace *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 trace *trace) -{ - int i, j, k, s; - struct loom *loom; - struct eproc *proc; - struct ethread *thread; - struct stream *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; knthreads; k++) - { - trace->nstreams++; - } - } - } - - trace->stream = calloc(trace->nstreams, sizeof(struct stream)); - - 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; knthreads; k++) - { - thread = &proc->thread[k]; - stream = &trace->stream[s++]; - - stream->f = thread->f; - stream->tid = thread->tid; - stream->proc = j; - stream->loom = i; - stream->active = 1; - stream->lastclock = 0; - } - } - } - - return 0; -} - -int load_first_event(struct trace *trace) -{ - int i; - struct stream *stream; - struct event *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 stream *stream, struct event *ev) +void emit(struct ovni_stream *stream, struct ovni_ev *ev) { int64_t delta; + uint64_t clock; + int i, payloadsize; - delta = ev->clock - stream->lastclock; + //printf("sizeof(*ev) = %d\n", sizeof(*ev)); + //hexdump((uint8_t *) ev, sizeof(*ev)); - printf("%d.%d.%d %c %c % 6u % 6u % 20lu % 15ld\n", + clock = ovni_ev_get_clock(ev); + + delta = clock - stream->lastclock; + + printf("%d.%d.%d %c %c %c % 20lu % 15ld ", stream->loom, stream->proc, stream->tid, - ev->fsm, ev->event, ev->a, ev->b, ev->clock, delta); + ev->model, ev->class, ev->value, clock, delta); - stream->lastclock = ev->clock; -} - -void load_next_event(struct stream *stream) -{ - int i; - size_t n; - struct event *ev; - - if(!stream->active) - return; - - ev = &stream->last; - if((n = fread(ev, sizeof(*ev), 1, stream->f)) != 1) + payloadsize = ovni_payload_size(ev); + for(i=0; iactive = 0; - return; + printf("%d ", ev->payload.payload_u8[i]); } + printf("\n"); - stream->active = 1; + stream->lastclock = clock; } -void dump_events(struct trace *trace) + +void dump_events(struct ovni_trace *trace) { int i, f; uint64_t minclock, lastclock; - struct event *ev; - struct stream *stream; + struct ovni_ev *ev; + struct ovni_stream *stream; /* Load events */ for(i=0; instreams; i++) { stream = &trace->stream[i]; - load_next_event(stream); + ovni_load_next_event(stream); } lastclock = 0; @@ -258,10 +96,10 @@ void dump_events(struct trace *trace) continue; ev = &stream->last; - if(f < 0 || ev->clock < minclock) + if(f < 0 || ovni_ev_get_clock(ev) < minclock) { f = i; - minclock = ev->clock; + minclock = ovni_ev_get_clock(ev); } } @@ -272,19 +110,19 @@ void dump_events(struct trace *trace) stream = &trace->stream[f]; - if(lastclock > stream->last.clock) + if(lastclock > ovni_ev_get_clock(&stream->last)) { fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n", - lastclock, stream->last.clock); + lastclock, ovni_ev_get_clock(&stream->last)); } /* Emit current event */ emit(stream, &stream->last); - lastclock = stream->last.clock; + lastclock = ovni_ev_get_clock(&stream->last); /* Read the next one */ - load_next_event(stream); + ovni_load_next_event(stream); /* Unset the index */ f = -1; @@ -293,15 +131,10 @@ void dump_events(struct trace *trace) } } -void free_streams(struct trace *trace) -{ - free(trace->stream); -} - int main(int argc, char *argv[]) { char *tracedir; - struct trace trace; + struct ovni_trace trace; if(argc != 2) { @@ -311,15 +144,15 @@ int main(int argc, char *argv[]) tracedir = argv[1]; - if(load_trace(&trace, tracedir)) + if(ovni_load_trace(&trace, tracedir)) return 1; - if(load_streams(&trace)) + if(ovni_load_streams(&trace)) return 1; dump_events(&trace); - free_streams(&trace); + ovni_free_streams(&trace); return 0; } diff --git a/ovni.c b/ovni.c index 0d4977b..f2ba373 100644 --- a/ovni.c +++ b/ovni.c @@ -14,18 +14,29 @@ #include #include #include - +#include #include "ovni.h" -#include "def.h" + +#define ENABLE_DEBUG + +#ifdef ENABLE_DEBUG +#define dbg(...) fprintf(stderr, __VA_ARGS__); +#else +#define dbg(...) +#endif + +#define err(...) fprintf(stderr, __VA_ARGS__); //#define ENABLE_SLOW_CHECKS +//#define USE_RDTSC + /* Data per process */ -struct rproc rproc = {0}; +struct ovni_rproc rproc = {0}; /* Data per thread */ -_Thread_local struct rthread rthread = {0}; +_Thread_local struct ovni_rthread rthread = {0}; static int create_trace_dirs(char *tracedir, int loom, int proc) @@ -102,7 +113,7 @@ ovni_proc_init(int loom, int proc) /* By default we use the monotonic clock */ rproc.clockid = CLOCK_MONOTONIC; - if(create_trace_dirs(TRACEDIR, loom, proc)) + if(create_trace_dirs(OVNI_TRACEDIR, loom, proc)) abort(); rproc.ready = 1; @@ -135,7 +146,14 @@ ovni_thread_init(pid_t tid) rthread.tid = tid; rthread.cpu = -666; - rthread.nevents = 0; + rthread.evlen = 0; + + rthread.evbuf = malloc(OVNI_MAX_EV_BUF); + if(rthread.evbuf == NULL) + { + perror("malloc"); + abort(); + } if(create_trace_stream(tid)) abort(); @@ -145,6 +163,13 @@ ovni_thread_init(pid_t tid) return 0; } +int +ovni_thread_free() +{ + assert(rthread.ready); + free(rthread.evbuf); +} + int ovni_thread_isready() { @@ -157,25 +182,48 @@ ovni_cpu_set(int cpu) rthread.cpu = cpu; } -/* Sets the current time so that all subsequent events have the new - * timestamp */ -void -ovni_clock_update() +static inline +uint64_t rdtsc(void) +{ + uint32_t lo, hi; + + // RDTSC copies contents of 64-bit TSC into EDX:EAX + asm volatile("rdtsc" : "=a" (lo), "=d" (hi)); + return (uint64_t) hi << 32 | lo; +} + +uint64_t +ovni_get_clock() { struct timespec tp; uint64_t ns = 1000LL * 1000LL * 1000LL; uint64_t raw; int ret; +#ifdef USE_RDTSC + raw = rdtsc(); +#else + ret = clock_gettime(rproc.clockid, &tp); #ifdef ENABLE_SLOW_CHECKS if(ret) abort(); -#endif +#endif /* ENABLE_SLOW_CHECKS */ raw = tp.tv_sec * ns + tp.tv_nsec; - //raw = raw >> 6; rthread.clockvalue = (uint64_t) raw; + +#endif /* USE_RDTSC */ + + return raw; +} + +/* Sets the current time so that all subsequent events have the new + * timestamp */ +void +ovni_clock_update() +{ + rthread.clockvalue = ovni_get_clock(); } static void @@ -217,61 +265,329 @@ ovni_write(uint8_t *buf, size_t size) return 0; } +static int +flush_evbuf() +{ + int ret; + + assert(rthread.ready); + assert(rproc.ready); + + ret = ovni_write(rthread.evbuf, rthread.evlen); + + rthread.evlen = 0; + + return ret; +} + +static void +ovni_ev_set_clock(struct ovni_ev *ev) +{ + ev->clock_lo = (uint32_t) (rthread.clockvalue & 0xffffffff); + ev->clock_hi = (uint16_t) ((rthread.clockvalue >> 32) & 0xffff); +} + +uint64_t +ovni_ev_get_clock(struct ovni_ev *ev) +{ + uint64_t clock; + + clock = ((uint64_t) ev->clock_hi) << 32 | ((uint64_t) ev->clock_lo); + return clock; +} + +void +ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv) +{ + ev->model = mcv[0]; + ev->class = mcv[1]; + ev->value = mcv[2]; +} + int -ovni_thread_flush() +ovni_payload_size(struct ovni_ev *ev) +{ + return ev->flags & 0x0f; +} + +void +ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size) +{ + /* Ensure we have room */ + assert(ovni_payload_size(ev) + size < 16); + + ev->flags = ev->flags & 0xf0 | size & 0x0f; +} + +int +ovni_ev_size(struct ovni_ev *ev) +{ + return sizeof(*ev) - sizeof(ev->payload) + + ovni_payload_size(ev); +} + + +static void +ovni_ev_add(struct ovni_ev *ev) +{ + int size; + + ovni_ev_set_clock(ev); + + size = ovni_ev_size(ev); + + + memcpy(&rthread.evbuf[rthread.evlen], ev, size); + rthread.evlen += size; +} + +void +ovni_ev(struct ovni_ev *ev) +{ + ovni_ev_set_clock(ev); + ovni_ev_add(ev); +} + +int +ovni_flush() { int ret = 0; - struct event pre={0}, post={0}; + struct ovni_ev pre={0}, post={0}; assert(rthread.ready); assert(rproc.ready); ovni_clock_update(); - pre.clock = rthread.clockvalue; - pre.fsm = 'F'; - pre.event = '['; + ovni_ev_set_clock(&pre); + ovni_ev_set_mcv(&pre, "OF["); - ret = ovni_write((uint8_t *) rthread.events, rthread.nevents * sizeof(struct event)); - rthread.nevents = 0; + ret = flush_evbuf(); ovni_clock_update(); - post.clock = rthread.clockvalue; - post.fsm = 'F'; - post.event = ']'; + ovni_ev_set_clock(&post); + ovni_ev_set_mcv(&post, "OF]"); - /* Also emit the two flush events */ - memcpy(&rthread.events[rthread.nevents++], &pre, sizeof(struct event));; - memcpy(&rthread.events[rthread.nevents++], &post, sizeof(struct event));; + /* Add the two flush events */ + ovni_ev_add(&pre); + ovni_ev_add(&post); return ret; } + +static int +load_proc(struct ovni_eproc *proc, char *procdir) +{ + struct dirent *dirent; + DIR *dir; + char path[PATH_MAX]; + char *p; + struct ovni_ethread *thread; + + if((dir = opendir(procdir)) == NULL) + { + fprintf(stderr, "opendir %s failed: %s\n", + procdir, strerror(errno)); + return -1; + } + + while((dirent = readdir(dir)) != NULL) + { + if(dirent->d_name[0] != 't') + continue; + p = strchr(dirent->d_name, '.'); + if(p == NULL) + continue; + p++; + if(*p == '\0') + { + fprintf(stderr, "bad thread stream file: %s\n", + dirent->d_name); + return -1; + } + + + thread = &proc->thread[proc->nthreads++]; + thread->tid = atoi(p); + + sprintf(path, "%s/%s", procdir, dirent->d_name); + thread->f = fopen(path, "r"); + + if(thread->f == NULL) + { + fprintf(stderr, "fopen %s failed: %s\n", + path, strerror(errno)); + return -1; + } + } + + closedir(dir); + + return 0; +} + static int -ovni_ev(uint8_t fsm, uint8_t event, uint16_t a, uint16_t b) +load_loom(struct ovni_loom *loom, char *loomdir) { - struct event *ev; - int ret = 0; + int proc; + char path[PATH_MAX]; + struct stat st; - ev = &rthread.events[rthread.nevents++]; + for(proc=0; procclock = rthread.clockvalue; - ev->fsm = fsm; - ev->event = event; - ev->a = a; - ev->b = b; + if(stat(path, &st) != 0) + { + /* No more proc.N directories */ + if(errno == ENOENT) + break; - /* Flush */ - if(rthread.nevents >= MAX_EV) - ret = ovni_thread_flush(); + fprintf(stderr, "cannot stat %s: %s\n", path, + strerror(errno)); + return -1; + } - return ret; + if(!S_ISDIR(st.st_mode)) + { + fprintf(stderr, "not a dir %s\n", path); + return -1; + } + + if(load_proc(&loom->proc[proc], path)) + return -1; + } + + loom->nprocs = proc; + + return 0; } int -ovni_thread_ev(uint8_t fsm, uint8_t event, uint16_t a, uint16_t b) +ovni_load_trace(struct ovni_trace *trace, char *tracedir) { - assert(rthread.ready); - assert(rproc.ready); - return ovni_ev(fsm, event, a, b); + 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 +ovni_load_streams(struct ovni_trace *trace) +{ + int i, j, k, s; + struct ovni_loom *loom; + struct ovni_eproc *proc; + struct ovni_ethread *thread; + struct ovni_stream *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; knthreads; k++) + { + trace->nstreams++; + } + } + } + + trace->stream = calloc(trace->nstreams, sizeof(struct ovni_stream)); + + 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; knthreads; k++) + { + thread = &proc->thread[k]; + stream = &trace->stream[s++]; + + stream->f = thread->f; + stream->tid = thread->tid; + stream->thread = k; + stream->proc = j; + stream->loom = i; + stream->active = 1; + stream->lastclock = 0; + } + } + } + + return 0; +} + +void +ovni_free_streams(struct ovni_trace *trace) +{ + free(trace->stream); +} + +void +ovni_load_next_event(struct ovni_stream *stream) +{ + int i; + size_t n, size; + struct ovni_ev *ev; + uint8_t flags; + + if(!stream->active) + return; + + ev = &stream->last; + if((n = fread(&ev->flags, sizeof(ev->flags), 1, stream->f)) != 1) + { + dbg("stream is empty\n"); + stream->active = 0; + return; + } + + //dbg("flags = %d\n", ev->flags); + + size = ovni_ev_size(ev) - sizeof(ev->flags); + //dbg("ev size = %d\n", size); + + + /* Clean payload from previous event */ + memset(&ev->payload, 0, sizeof(ev->payload)); + + if((n = fread(((uint8_t *) ev) + sizeof(ev->flags), 1, size, stream->f)) != size) + { + err("warning: garbage found at the end of the stream\n"); + stream->active = 0; + return; + } + + //dbg("loaded next event:\n"); + //hexdump((uint8_t *) ev, ovni_ev_size(ev)); + //dbg("---------\n"); + + stream->active = 1; + +} diff --git a/ovni.h b/ovni.h index f50fd49..5196ac3 100644 --- a/ovni.h +++ b/ovni.h @@ -1,22 +1,196 @@ #ifndef OVNI_H #define OVNI_H -int -ovni_proc_init(int loom, int proc); +#include +#include +#include +#include -int -ovni_thread_init(pid_t tid); +#include "ovni.h" -int -ovni_thread_isready(); +#define OVNI_MAX_CPU 256 +#define OVNI_MAX_PROC 32 +#define OVNI_MAX_THR 32 +#define OVNI_MAX_LOOM 4 +#define OVNI_TRACEDIR "ovni" -void -ovni_clock_update(); +/* Reserved buffer for event allocation */ +#define OVNI_MAX_EV_BUF (16 * 1024LL * 1024LL * 1024LL) -int -ovni_thread_ev(uint8_t fsm, uint8_t event, uint16_t a, uint16_t b); +/* ----------------------- common ------------------------ */ -int -ovni_thread_flush(); +struct __attribute__((__packed__)) ovni_ev { + /* first 4 bits reserved, last 4 for payload size */ + uint8_t flags; + uint8_t model; + uint8_t class; + uint8_t value; + uint16_t clock_hi; + uint32_t clock_lo; + union { + uint8_t payload_u8[16]; + uint16_t payload_u16[8]; + uint32_t payload_u32[4]; + uint64_t payload_u64[2]; + } payload; +}; + +/* ----------------------- runtime ------------------------ */ + +/* State of each thread on runtime */ +struct ovni_rthread { + /* Current cpu the thread is running on. Set to -1 if unbounded or + * unknown */ + int cpu; + + /* Current thread id */ + pid_t tid; + + /* Clock value of the events being emitted */ + uint64_t clockvalue; + + /* Stream trace file descriptor */ + int streamfd; + + int ready; + + /* The number of bytes filled with events */ + size_t evlen; + + /* Buffer to write events */ + uint8_t *evbuf; +}; + +/* State of each process on runtime */ +struct ovni_rproc { + /* Path of the process tracedir */ + char dir[PATH_MAX]; + + int proc; + int loom; + int ncpus; + clockid_t clockid; + char procdir[PATH_MAX]; + + int ready; +}; + +/* ----------------------- emulated ------------------------ */ + +struct ovni_cpu; + +/* State of each thread on post-process */ +struct ovni_ethread { + /* Emulated thread tid */ + pid_t tid; + + /* Stream file */ + FILE *f; + + /* Thread stream */ + struct ovni_stream *stream; + + /* Current cpu */ + struct ovni_cpu *cpu; +}; + +/* State of each process on post-process */ +struct ovni_eproc { + /* Monotonic counter for process index */ + /* TODO: Use pid? */ + int proc; + + /* Path of the process tracedir */ + char dir[PATH_MAX]; + + /* Threads */ + size_t nthreads; + struct ovni_ethread thread[OVNI_MAX_THR]; +}; + +/* ----------------------- trace ------------------------ */ + +/* State of each loom on post-process */ +struct ovni_loom { + size_t nprocs; + struct ovni_eproc proc[OVNI_MAX_PROC]; +}; + +struct ovni_stream { + FILE *f; + int tid; + int thread; + int proc; + int loom; + int loaded; + int active; + struct ovni_ev last; + uint64_t lastclock; +}; + +struct ovni_trace { + int nlooms; + struct ovni_loom loom[OVNI_MAX_LOOM]; + int nstreams; + struct ovni_stream *stream; +}; + +struct ovni_cpu { + /* The thread the cpu is currently running */ + struct ovni_ethread *thread; +}; + +struct ovni_evhead { + struct ovni_stream *stream; + + struct ovni_loom *loom; + struct ovni_eproc *proc; + struct ovni_ethread *thread; +}; + +struct ovni_emulator { + struct ovni_trace trace; + struct ovni_cpu cpu[OVNI_MAX_CPU]; + + struct ovni_evhead head; + uint64_t lastclock; +}; + + + + + + + +int ovni_proc_init(int loom, int proc); + +int ovni_thread_init(pid_t tid); + +int ovni_thread_isready(); + +void ovni_clock_update(); + +void ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv); + +uint64_t ovni_ev_get_clock(struct ovni_ev *ev); + +void ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size); + +int ovni_ev_size(struct ovni_ev *ev); + +int ovni_payload_size(struct ovni_ev *ev); + +/* Set the current clock in the event and queue it */ +void ovni_ev(struct ovni_ev *ev); + +int ovni_flush(); + +int ovni_load_trace(struct ovni_trace *trace, char *tracedir); + +int ovni_load_streams(struct ovni_trace *trace); + +void ovni_free_streams(struct ovni_trace *trace); + +void ovni_load_next_event(struct ovni_stream *stream); #endif /* OVNI_H */ diff --git a/ovni2prv.c b/ovni2prv.c new file mode 100644 index 0000000..dcf00a7 --- /dev/null +++ b/ovni2prv.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ovni.h" + +void emit(struct ovni_stream *stream, struct ovni_ev *ev) +{ + static uint64_t firstclock = 0; + int64_t delta; + int task; + + if(firstclock == 0) + firstclock = ovni_ev_get_clock(ev); + + delta = ovni_ev_get_clock(ev) - firstclock; + + //#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1) + //2:0:1:1:7:1540663:6400010:1 + //2:0:1:1:7:1540663:6400015:1 + //2:0:1:1:7:1540663:6400017:0 + //2:0:1:1:7:1542091:6400010:1 + //2:0:1:1:7:1542091:6400015:1 + //2:0:1:1:7:1542091:6400025:1 + //2:0:1:1:7:1542091:6400017:0 + + printf("2:0:1:1:%d:%ld:%d:%d\n", stream->thread+1, delta, ev->class, ev->value); +} + +void dump_events(struct ovni_trace *trace) +{ + int i, f; + uint64_t minclock, lastclock; + struct ovni_ev *ev; + struct ovni_stream *stream; + + /* Load events */ + for(i=0; instreams; i++) + { + stream = &trace->stream[i]; + ovni_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 || ovni_ev_get_clock(ev) < minclock) + { + f = i; + minclock = ovni_ev_get_clock(ev); + } + } + + //fprintf(stderr, "f=%d minclock=%u\n", f, minclock); + + if(f < 0) + break; + + stream = &trace->stream[f]; + + if(lastclock >= ovni_ev_get_clock(&stream->last)) + { + fprintf(stderr, "warning: backwards jump in time\n"); + } + + /* Emit current event */ + emit(stream, &stream->last); + + lastclock = ovni_ev_get_clock(&stream->last); + + /* Read the next one */ + ovni_load_next_event(stream); + + /* Unset the index */ + f = -1; + minclock = 0; + + } +} + +int main(int argc, char *argv[]) +{ + char *tracedir; + struct ovni_trace trace; + + if(argc != 2) + { + fprintf(stderr, "missing tracedir\n"); + exit(EXIT_FAILURE); + } + + tracedir = argv[1]; + + if(ovni_load_trace(&trace, tracedir)) + return 1; + + if(ovni_load_streams(&trace)) + return 1; + + printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", trace.nstreams); + + dump_events(&trace); + + ovni_free_streams(&trace); + + return 0; +} diff --git a/prvth.c b/prvth.c deleted file mode 100644 index d5987fd..0000000 --- a/prvth.c +++ /dev/null @@ -1,336 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "def.h" - -int load_proc(struct eproc *proc, char *procdir) -{ - struct dirent *dirent; - DIR *dir; - char path[PATH_MAX]; - char *p; - struct ethread *thread; - - if((dir = opendir(procdir)) == NULL) - { - fprintf(stderr, "opendir %s failed: %s\n", - procdir, strerror(errno)); - return -1; - } - - while((dirent = readdir(dir)) != NULL) - { - if(dirent->d_name[0] != 't') - continue; - p = strchr(dirent->d_name, '.'); - if(p == NULL) - continue; - p++; - if(*p == '\0') - { - fprintf(stderr, "bad thread stream file: %s\n", - dirent->d_name); - return -1; - } - - - thread = &proc->thread[proc->nthreads++]; - thread->tid = atoi(p); - - sprintf(path, "%s/%s", procdir, dirent->d_name); - thread->f = fopen(path, "r"); - - if(thread->f == NULL) - { - fprintf(stderr, "fopen %s failed: %s\n", - path, strerror(errno)); - return -1; - } - } - - closedir(dir); - - return 0; -} - -int load_loom(struct loom *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 trace *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 trace *trace) -{ - int i, j, k, s; - struct loom *loom; - struct eproc *proc; - struct ethread *thread; - struct stream *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; knthreads; k++) - { - trace->nstreams++; - } - } - } - - trace->stream = calloc(trace->nstreams, sizeof(struct stream)); - - 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; knthreads; k++) - { - thread = &proc->thread[k]; - stream = &trace->stream[s++]; - - stream->f = thread->f; - stream->tid = thread->tid; - stream->thread = k; - stream->proc = j; - stream->loom = i; - stream->active = 1; - } - } - } - - return 0; -} - -int load_first_event(struct trace *trace) -{ - int i; - struct stream *stream; - struct event *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 stream *stream, struct event *ev) -{ - static uint64_t firstclock = 0; - int64_t delta; - int task; - - if(firstclock == 0) - firstclock = ev->clock; - - delta = ev->clock - firstclock; - - //#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(00000000000000000008:1) - //2:0:1:1:7:1540663:6400010:1 - //2:0:1:1:7:1540663:6400015:1 - //2:0:1:1:7:1540663:6400017:0 - //2:0:1:1:7:1542091:6400010:1 - //2:0:1:1:7:1542091:6400015:1 - //2:0:1:1:7:1542091:6400025:1 - //2:0:1:1:7:1542091:6400017:0 - - printf("2:0:1:1:%d:%ld:%d:%d\n", stream->thread+1, delta, ev->fsm, ev->event); -} - -void load_next_event(struct stream *stream) -{ - int i; - size_t n; - struct event *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 trace *trace) -{ - int i, f; - uint64_t minclock, lastclock; - struct event *ev; - struct stream *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, &stream->last); - - lastclock = stream->last.clock; - - /* Read the next one */ - load_next_event(stream); - - /* Unset the index */ - f = -1; - minclock = 0; - - } -} - -void free_streams(struct trace *trace) -{ - free(trace->stream); -} - -int main(int argc, char *argv[]) -{ - char *tracedir; - struct trace 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; - - printf("#Paraver (19/01/38 at 03:14):00000000000000000000_ns:0:1:1(%d:1)\n", trace.nstreams); - - dump_events(&trace); - - free_streams(&trace); - - return 0; -} diff --git a/test_speed.c b/test_speed.c index 555463a..979872c 100644 --- a/test_speed.c +++ b/test_speed.c @@ -2,25 +2,29 @@ #include #include #include +#include #include "ovni.h" -#define N 1000 +#define N 100000 int main() { + struct ovni_ev ev = {0}; int i; ovni_proc_init(0, 0); ovni_thread_init(1); + ovni_ev_set_mcv(&ev, "OB."); + for(i=0; i