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

98
dump.c
View File

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

142
ovni.c
View File

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