Store traces per thread

This commit is contained in:
Rodrigo Arias 2021-07-19 19:05:26 +02:00
parent 1092faebf3
commit fe5d223190
4 changed files with 196 additions and 161 deletions

104
def.h
View File

@ -3,49 +3,105 @@
#define MAX_CPU 256 #define MAX_CPU 256
#define MAX_PROC 32 #define MAX_PROC 32
#define MAX_THR 32
#define MAX_LOOM 4 #define MAX_LOOM 4
#define TRACEDIR "ovni" #define TRACEDIR "ovni"
struct ovnithr { /* ----------------------- common ------------------------ */
int cpu;
uint64_t clockvalue; enum thread_state {
ST_THREAD_UNINIT = 0,
ST_THREAD_INIT = 1
}; };
struct ovniproc { struct __attribute__((__packed__)) event {
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; uint64_t clock;
uint8_t fsm; uint8_t fsm;
uint8_t event; uint8_t event;
int32_t data; int32_t data;
}; };
struct ovnistream { /* ----------------------- 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 */
FILE *stream;
enum thread_state state;
};
/* 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];
};
/* ----------------------- 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; FILE *f;
int cpu; int cpu;
int loaded; int loaded;
int active; int active;
struct ovnievent last; struct event last;
}; };
struct ovnitrace { struct trace {
int nlooms; int nlooms;
struct ovniloom loom[MAX_LOOM]; struct loom loom[MAX_LOOM];
int nstreams; int nstreams;
struct ovnistream *stream; struct stream *stream;
}; };
#endif /* OVNI_DEF_H */ #endif /* OVNI_DEF_H */

98
dump.c
View File

@ -6,32 +6,61 @@
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdatomic.h> #include <stdatomic.h>
#include <dirent.h>
#include "def.h" #include "def.h"
int load_proc(struct ovniproc *proc, char *procdir) int load_proc(struct eproc *proc, char *procdir)
{ {
FILE *f; struct dirent *dirent;
int cpu; DIR *dir;
char path[PATH_MAX]; char path[PATH_MAX];
char *p;
struct ethread *thread;
for(cpu=0; cpu<MAX_CPU; cpu++) if((dir = opendir(procdir)) == NULL)
{ {
sprintf(path, "%s/cpu.%d", procdir, cpu); fprintf(stderr, "opendir %s failed: %s\n",
f = fopen(path, "r"); procdir, strerror(errno));
return -1;
if(f == NULL)
break;
proc->cpustream[cpu] = f;
} }
proc->ncpus = cpu; 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; return 0;
} }
int load_loom(struct ovniloom *loom, char *loomdir) int load_loom(struct loom *loom, char *loomdir)
{ {
int proc; int proc;
char path[PATH_MAX]; char path[PATH_MAX];
@ -43,7 +72,7 @@ int load_loom(struct ovniloom *loom, char *loomdir)
if(stat(path, &st) != 0) if(stat(path, &st) != 0)
{ {
/* Proc numbers exausted */ /* No more proc.N directories */
if(errno == ENOENT) if(errno == ENOENT)
break; break;
@ -67,7 +96,7 @@ int load_loom(struct ovniloom *loom, char *loomdir)
return 0; return 0;
} }
int load_trace(struct ovnitrace *trace, char *tracedir) int load_trace(struct trace *trace, char *tracedir)
{ {
int loom, nlooms; int loom, nlooms;
char path[PATH_MAX]; char path[PATH_MAX];
@ -87,12 +116,12 @@ int load_trace(struct ovnitrace *trace, char *tracedir)
} }
/* Populates the streams in a single array */ /* Populates the streams in a single array */
int load_streams(struct ovnitrace *trace) int load_streams(struct trace *trace)
{ {
int i, j, k, s; int i, j, k, s;
struct ovniloom *loom; struct loom *loom;
struct ovniproc *proc; struct eproc *proc;
struct ovnistream *stream; struct stream *stream;
trace->nstreams = 0; trace->nstreams = 0;
@ -102,14 +131,14 @@ int load_streams(struct ovnitrace *trace)
for(j=0; j<loom->nprocs; j++) for(j=0; j<loom->nprocs; j++)
{ {
proc = &loom->proc[j]; proc = &loom->proc[j];
for(k=0; k<proc->ncpus; k++) for(k=0; k<proc->nthreads; k++)
{ {
trace->nstreams++; trace->nstreams++;
} }
} }
} }
trace->stream = calloc(trace->nstreams, sizeof(struct ovnistream)); trace->stream = calloc(trace->nstreams, sizeof(struct stream));
if(trace->stream == NULL) if(trace->stream == NULL)
{ {
@ -125,11 +154,10 @@ int load_streams(struct ovnitrace *trace)
for(j=0; j<loom->nprocs; j++) for(j=0; j<loom->nprocs; j++)
{ {
proc = &loom->proc[j]; proc = &loom->proc[j];
for(k=0; k<proc->ncpus; k++) for(k=0; k<proc->nthreads; k++)
{ {
stream = &trace->stream[s++]; stream = &trace->stream[s++];
stream->f = proc->cpustream[k]; stream->f = proc->thread[k].f;
stream->cpu = k;
stream->active = 1; stream->active = 1;
} }
} }
@ -138,11 +166,11 @@ int load_streams(struct ovnitrace *trace)
return 0; return 0;
} }
int load_first_event(struct ovnitrace *trace) int load_first_event(struct trace *trace)
{ {
int i; int i;
struct ovnistream *stream; struct stream *stream;
struct ovnievent *ev; struct event *ev;
for(i=0; i<trace->nstreams; i++) for(i=0; i<trace->nstreams; i++)
{ {
@ -160,7 +188,7 @@ int load_first_event(struct ovnitrace *trace)
return 0; return 0;
} }
void emit(struct ovnievent *ev, int cpu) void emit(struct event *ev, int cpu)
{ {
static uint64_t lastclock = 0; static uint64_t lastclock = 0;
uint64_t delta; uint64_t delta;
@ -173,11 +201,11 @@ void emit(struct ovnievent *ev, int cpu)
lastclock = ev->clock; lastclock = ev->clock;
} }
void load_next_event(struct ovnistream *stream) void load_next_event(struct stream *stream)
{ {
int i; int i;
size_t n; size_t n;
struct ovnievent *ev; struct event *ev;
if(!stream->active) if(!stream->active)
return; return;
@ -193,12 +221,12 @@ void load_next_event(struct ovnistream *stream)
stream->active = 1; stream->active = 1;
} }
void dump_events(struct ovnitrace *trace) void dump_events(struct trace *trace)
{ {
int i, f; int i, f;
uint64_t minclock, lastclock; uint64_t minclock, lastclock;
struct ovnievent *ev; struct event *ev;
struct ovnistream *stream; struct stream *stream;
/* Load events */ /* Load events */
for(i=0; i<trace->nstreams; i++) for(i=0; i<trace->nstreams; i++)
@ -257,7 +285,7 @@ void dump_events(struct ovnitrace *trace)
} }
} }
void free_streams(struct ovnitrace *trace) void free_streams(struct trace *trace)
{ {
free(trace->stream); free(trace->stream);
} }
@ -265,7 +293,7 @@ void free_streams(struct ovnitrace *trace)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char *tracedir; char *tracedir;
struct ovnitrace trace; struct trace trace;
if(argc != 2) if(argc != 2)
{ {

144
ovni.c
View File

@ -7,15 +7,16 @@
#include <errno.h> #include <errno.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdatomic.h> #include <stdatomic.h>
#include <assert.h>
#include "ovni.h" #include "ovni.h"
#include "def.h" #include "def.h"
/* Data per process */ /* Data per process */
struct ovniproc ovniproc = {0}; struct rproc rproc = {0};
/* Data per thread */ /* Data per thread */
_Thread_local struct ovnithr ovnithr = {0}; _Thread_local struct rthread rthread = {0};
static int static int
create_trace_dirs(char *tracedir, int loom, int proc) create_trace_dirs(char *tracedir, int loom, int proc)
@ -41,11 +42,11 @@ create_trace_dirs(char *tracedir, int loom, int proc)
//return -1; //return -1;
} }
snprintf(ovniproc.dir, PATH_MAX, "%s/loom.%d/proc.%d", tracedir, loom, proc); snprintf(rproc.dir, PATH_MAX, "%s/loom.%d/proc.%d", tracedir, loom, proc);
if(mkdir(ovniproc.dir, 0755)) if(mkdir(rproc.dir, 0755))
{ {
fprintf(stderr, "mkdir %s: %s\n", ovniproc.dir, strerror(errno)); fprintf(stderr, "mkdir %s: %s\n", rproc.dir, strerror(errno));
return -1; return -1;
} }
@ -53,47 +54,53 @@ create_trace_dirs(char *tracedir, int loom, int proc)
} }
static int static int
create_trace_streams(int ncpus) create_trace_stream()
{ {
char path[PATH_MAX]; char path[PATH_MAX];
int i;
for(i=0; i<ncpus; i++) snprintf(path, PATH_MAX, "%s/thread.%d", rproc.dir, rthread.tid);
if((rthread.stream = fopen(path, "w")) == NULL)
{ {
snprintf(path, PATH_MAX, "%s/cpu.%d", ovniproc.dir, i); fprintf(stderr, "fopen %s failed: %s\n", path, strerror(errno));
if((ovniproc.cpustream[i] = fopen(path, "w")) == NULL) return -1;
{
perror("fopen");
return -1;
}
} }
return 0; return 0;
} }
int int
ovni_init(int loom, int proc, int ncpus) ovni_proc_init(int loom, int proc, int ncpus)
{ {
int i; int i;
memset(&rproc, 0, sizeof(rproc));
fprintf(stderr, "ovni_init\n"); rproc.loom = loom;
memset(&ovniproc, 0, sizeof(ovniproc)); rproc.proc = proc;
memset(&ovnithr, 0, sizeof(ovnithr)); rproc.ncpus = ncpus;
for(i=0; i<MAX_CPU; i++)
ovniproc.opened[i] = ATOMIC_VAR_INIT(0);
ovniproc.loom = loom;
ovniproc.proc = proc;
ovniproc.ncpus = ncpus;
/* By default we use the monotonic clock */ /* By default we use the monotonic clock */
ovniproc.clockid = CLOCK_MONOTONIC; rproc.clockid = CLOCK_MONOTONIC;
if(create_trace_dirs(TRACEDIR, loom, proc)) if(create_trace_dirs(TRACEDIR, loom, proc))
return -1; return -1;
if(create_trace_streams(ncpus)) return 0;
}
int
ovni_thread_init(pid_t tid)
{
int i;
assert(tid != 0);
memset(&rthread, 0, sizeof(rthread));
rthread.tid = tid;
rthread.cpu = -1;
rthread.state = ST_THREAD_INIT;
if(create_trace_stream(tid))
return -1; return -1;
return 0; return 0;
@ -102,7 +109,7 @@ ovni_init(int loom, int proc, int ncpus)
void void
ovni_cpu_set(int cpu) ovni_cpu_set(int cpu)
{ {
ovnithr.cpu = cpu; rthread.cpu = cpu;
} }
/* Sets the current time so that all subsequent events have the new /* Sets the current time so that all subsequent events have the new
@ -114,63 +121,22 @@ ovni_clock_update()
uint64_t ns = 1000LL * 1000LL * 1000LL; uint64_t ns = 1000LL * 1000LL * 1000LL;
uint64_t raw; uint64_t raw;
if(clock_gettime(ovniproc.clockid, &tp)) if(clock_gettime(rproc.clockid, &tp))
return -1; return -1;
raw = tp.tv_sec * ns + tp.tv_nsec; raw = tp.tv_sec * ns + tp.tv_nsec;
//raw = raw >> 6; //raw = raw >> 6;
ovnithr.clockvalue = (uint64_t) raw; rthread.clockvalue = (uint64_t) raw;
return 0; 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 static void
pack_uint32(uint8_t **q, uint32_t n) hexdump(uint8_t *buf, size_t size)
{ {
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; int i, j;
printf("writing %ld bytes in cpu=%d\n", size, ovnithr.cpu); //printf("writing %ld bytes in cpu=%d\n", size, rthread.cpu);
for(i=0; i<size; i+=16) for(i=0; i<size; i+=16)
{ {
@ -180,16 +146,19 @@ ovni_write(uint8_t *buf, size_t size)
} }
printf("\n"); printf("\n");
} }
}
f = ovniproc.cpustream[ovnithr.cpu]; static int
ovni_write(uint8_t *buf, size_t size)
if(fwrite(buf, 1, size, f) != size) {
fprintf(stderr, "writing %ld bytes in thread.%d\n", size, rthread.tid);
if(fwrite(buf, 1, size, rthread.stream) != size)
{ {
perror("fwrite"); perror("fwrite");
return -1; return -1;
} }
fflush(f); fflush(rthread.stream);
return 0; return 0;
} }
@ -197,9 +166,9 @@ ovni_write(uint8_t *buf, size_t size)
static int static int
ovni_ev(uint8_t fsm, uint8_t event, int32_t data) ovni_ev(uint8_t fsm, uint8_t event, int32_t data)
{ {
struct ovnievent ev; struct event ev;
ev.clock = ovnithr.clockvalue; ev.clock = rthread.clockvalue;
ev.fsm = fsm; ev.fsm = fsm;
ev.event = event; ev.event = event;
ev.data = data; ev.data = data;
@ -210,21 +179,6 @@ ovni_ev(uint8_t fsm, uint8_t event, int32_t data)
int int
ovni_ev_worker(uint8_t fsm, uint8_t event, int32_t data) ovni_ev_worker(uint8_t fsm, uint8_t event, int32_t data)
{ {
assert(rthread.state == ST_THREAD_INIT);
return ovni_ev(fsm, event, data); return ovni_ev(fsm, event, data);
} }
void
ovni_stream_open(int cpu)
{
if(atomic_fetch_add(&ovniproc.opened[cpu], 1) + 1 > 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);
}

11
ovni.h
View File

@ -2,7 +2,10 @@
#define OVNI_H #define OVNI_H
int int
ovni_init(int loom, int proc, int ncpus); ovni_proc_init(int loom, int proc, int ncpus);
int
ovni_thread_init(pid_t tid);
int int
ovni_clock_update(); ovni_clock_update();
@ -13,10 +16,4 @@ ovni_ev_worker(uint8_t fsm, uint8_t event, int32_t data);
void void
ovni_cpu_set(int cpu); ovni_cpu_set(int cpu);
void
ovni_stream_open(int cpu);
void
ovni_stream_close(int cpu);
#endif /* OVNI_H */ #endif /* OVNI_H */