Add jumbo events
This commit is contained in:
parent
77a879c0a0
commit
d7c81b3048
12
dump.c
12
dump.c
@ -55,7 +55,7 @@ void emit(struct ovni_stream *stream, struct ovni_ev *ev)
|
|||||||
|
|
||||||
printf("%d.%d.%d %c %c %c % 20lu % 15ld ",
|
printf("%d.%d.%d %c %c %c % 20lu % 15ld ",
|
||||||
stream->loom, stream->proc, stream->tid,
|
stream->loom, stream->proc, stream->tid,
|
||||||
ev->model, ev->class, ev->value, clock, delta);
|
ev->header.model, ev->header.class, ev->header.value, clock, delta);
|
||||||
|
|
||||||
payloadsize = ovni_payload_size(ev);
|
payloadsize = ovni_payload_size(ev);
|
||||||
for(i=0; i<payloadsize; i++)
|
for(i=0; i<payloadsize; i++)
|
||||||
@ -97,7 +97,7 @@ void dump_events(struct ovni_trace *trace)
|
|||||||
if(!stream->active)
|
if(!stream->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev = &stream->last;
|
ev = stream->cur_ev;
|
||||||
if(f < 0 || ovni_ev_get_clock(ev) < minclock)
|
if(f < 0 || ovni_ev_get_clock(ev) < minclock)
|
||||||
{
|
{
|
||||||
f = i;
|
f = i;
|
||||||
@ -112,16 +112,16 @@ void dump_events(struct ovni_trace *trace)
|
|||||||
|
|
||||||
stream = &trace->stream[f];
|
stream = &trace->stream[f];
|
||||||
|
|
||||||
if(lastclock > ovni_ev_get_clock(&stream->last))
|
if(lastclock > ovni_ev_get_clock(stream->cur_ev))
|
||||||
{
|
{
|
||||||
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
|
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
|
||||||
lastclock, ovni_ev_get_clock(&stream->last));
|
lastclock, ovni_ev_get_clock(stream->cur_ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit current event */
|
/* Emit current event */
|
||||||
emit(stream, &stream->last);
|
emit(stream, stream->cur_ev);
|
||||||
|
|
||||||
lastclock = ovni_ev_get_clock(&stream->last);
|
lastclock = ovni_ev_get_clock(stream->cur_ev);
|
||||||
|
|
||||||
/* Read the next one */
|
/* Read the next one */
|
||||||
ovni_load_next_event(stream);
|
ovni_load_next_event(stream);
|
||||||
|
39
emu.c
39
emu.c
@ -29,7 +29,7 @@ emit_ev(struct ovni_stream *stream, struct ovni_ev *ev)
|
|||||||
|
|
||||||
dbg("%d.%d.%d %c %c %c % 20lu % 15ld ",
|
dbg("%d.%d.%d %c %c %c % 20lu % 15ld ",
|
||||||
stream->loom, stream->proc, stream->tid,
|
stream->loom, stream->proc, stream->tid,
|
||||||
ev->model, ev->class, ev->value, clock, delta);
|
ev->header.model, ev->header.class, ev->header.value, clock, delta);
|
||||||
|
|
||||||
payloadsize = ovni_payload_size(ev);
|
payloadsize = ovni_payload_size(ev);
|
||||||
for(i=0; i<payloadsize; i++)
|
for(i=0; i<payloadsize; i++)
|
||||||
@ -47,27 +47,6 @@ emu_emit(struct ovni_emu *emu)
|
|||||||
emit_ev(emu->cur_stream, emu->cur_ev);
|
emit_ev(emu->cur_stream, emu->cur_ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
load_first_event(struct ovni_stream *stream)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
size_t n;
|
|
||||||
struct ovni_ev *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;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ovni_ethread *
|
struct ovni_ethread *
|
||||||
find_thread(struct ovni_eproc *proc, pid_t tid)
|
find_thread(struct ovni_eproc *proc, pid_t tid)
|
||||||
{
|
{
|
||||||
@ -89,7 +68,7 @@ hook_pre(struct ovni_emu *emu)
|
|||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
|
|
||||||
switch(emu->cur_ev->model)
|
switch(emu->cur_ev->header.model)
|
||||||
{
|
{
|
||||||
case 'O': hook_pre_ovni(emu); break;
|
case 'O': hook_pre_ovni(emu); break;
|
||||||
case 'V': hook_pre_nosv(emu); break;
|
case 'V': hook_pre_nosv(emu); break;
|
||||||
@ -104,7 +83,7 @@ hook_view(struct ovni_emu *emu)
|
|||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
|
|
||||||
switch(emu->cur_ev->model)
|
switch(emu->cur_ev->header.model)
|
||||||
{
|
{
|
||||||
case 'O': hook_view_ovni(emu); break;
|
case 'O': hook_view_ovni(emu); break;
|
||||||
case 'V': hook_view_nosv(emu); break;
|
case 'V': hook_view_nosv(emu); break;
|
||||||
@ -119,7 +98,7 @@ hook_post(struct ovni_emu *emu)
|
|||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
|
|
||||||
switch(emu->cur_ev->model)
|
switch(emu->cur_ev->header.model)
|
||||||
{
|
{
|
||||||
case 'O': hook_post_ovni(emu); break;
|
case 'O': hook_post_ovni(emu); break;
|
||||||
default:
|
default:
|
||||||
@ -132,7 +111,7 @@ static void
|
|||||||
set_current(struct ovni_emu *emu, struct ovni_stream *stream)
|
set_current(struct ovni_emu *emu, struct ovni_stream *stream)
|
||||||
{
|
{
|
||||||
emu->cur_stream = stream;
|
emu->cur_stream = stream;
|
||||||
emu->cur_ev = &stream->last;
|
emu->cur_ev = stream->cur_ev;
|
||||||
emu->cur_loom = &emu->trace.loom[stream->loom];
|
emu->cur_loom = &emu->trace.loom[stream->loom];
|
||||||
emu->cur_proc = &emu->cur_loom->proc[stream->proc];
|
emu->cur_proc = &emu->cur_loom->proc[stream->proc];
|
||||||
emu->cur_thread = &emu->cur_proc->thread[stream->thread];
|
emu->cur_thread = &emu->cur_proc->thread[stream->thread];
|
||||||
@ -163,7 +142,7 @@ next_event(struct ovni_emu *emu)
|
|||||||
if(!stream->active)
|
if(!stream->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev = &stream->last;
|
ev = stream->cur_ev;
|
||||||
if(f < 0 || ovni_ev_get_clock(ev) < minclock)
|
if(f < 0 || ovni_ev_get_clock(ev) < minclock)
|
||||||
{
|
{
|
||||||
f = i;
|
f = i;
|
||||||
@ -179,13 +158,13 @@ next_event(struct ovni_emu *emu)
|
|||||||
|
|
||||||
set_current(emu, stream);
|
set_current(emu, stream);
|
||||||
|
|
||||||
if(emu->lastclock > ovni_ev_get_clock(&stream->last))
|
if(emu->lastclock > ovni_ev_get_clock(stream->cur_ev))
|
||||||
{
|
{
|
||||||
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
|
fprintf(stdout, "warning: backwards jump in time %lu -> %lu\n",
|
||||||
emu->lastclock, ovni_ev_get_clock(&stream->last));
|
emu->lastclock, ovni_ev_get_clock(stream->cur_ev));
|
||||||
}
|
}
|
||||||
|
|
||||||
emu->lastclock = ovni_ev_get_clock(&stream->last);
|
emu->lastclock = ovni_ev_get_clock(stream->cur_ev);
|
||||||
|
|
||||||
if(t0 < 0)
|
if(t0 < 0)
|
||||||
t0 = emu->lastclock;
|
t0 = emu->lastclock;
|
||||||
|
15
emu.h
15
emu.h
@ -25,7 +25,6 @@ enum ethread_state {
|
|||||||
TH_ST_DEAD,
|
TH_ST_DEAD,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
enum nosv_task_state {
|
enum nosv_task_state {
|
||||||
TASK_ST_CREATED,
|
TASK_ST_CREATED,
|
||||||
TASK_ST_RUNNING,
|
TASK_ST_RUNNING,
|
||||||
@ -45,17 +44,17 @@ struct nosv_task {
|
|||||||
|
|
||||||
struct nosv_task_type {
|
struct nosv_task_type {
|
||||||
int id;
|
int id;
|
||||||
|
const char *label;
|
||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* State of each emulated thread */
|
/* State of each emulated thread */
|
||||||
struct ovni_ethread {
|
struct ovni_ethread {
|
||||||
/* Emulated thread tid */
|
/* Emulated thread tid */
|
||||||
pid_t tid;
|
pid_t tid;
|
||||||
|
|
||||||
/* Stream file */
|
/* Stream fd */
|
||||||
FILE *f;
|
int stream_fd;
|
||||||
|
|
||||||
enum ethread_state state;
|
enum ethread_state state;
|
||||||
|
|
||||||
@ -95,14 +94,17 @@ struct ovni_loom {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ovni_stream {
|
struct ovni_stream {
|
||||||
FILE *f;
|
uint8_t *buf;
|
||||||
|
size_t size;
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
int tid;
|
int tid;
|
||||||
int thread;
|
int thread;
|
||||||
int proc;
|
int proc;
|
||||||
int loom;
|
int loom;
|
||||||
int loaded;
|
int loaded;
|
||||||
int active;
|
int active;
|
||||||
struct ovni_ev last;
|
struct ovni_ev *cur_ev;
|
||||||
uint64_t lastclock;
|
uint64_t lastclock;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -142,7 +144,6 @@ struct ovni_cpu {
|
|||||||
struct ovni_ethread *thread[OVNI_MAX_THR];
|
struct ovni_ethread *thread[OVNI_MAX_THR];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct ovni_emu {
|
struct ovni_emu {
|
||||||
struct ovni_trace trace;
|
struct ovni_trace trace;
|
||||||
|
|
||||||
|
35
emu_nosv.c
35
emu_nosv.c
@ -148,7 +148,7 @@ static void
|
|||||||
pre_task(struct ovni_emu *emu)
|
pre_task(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
emu_emit(emu);
|
emu_emit(emu);
|
||||||
switch(emu->cur_ev->value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 'c': pre_task_create(emu); break;
|
case 'c': pre_task_create(emu); break;
|
||||||
case 'x': pre_task_execute(emu); break;
|
case 'x': pre_task_execute(emu); break;
|
||||||
@ -165,16 +165,27 @@ static void
|
|||||||
pre_type_create(struct ovni_emu *emu)
|
pre_type_create(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
struct nosv_task_type *type, *p = NULL;
|
struct nosv_task_type *type, *p = NULL;
|
||||||
int typeid;
|
uint8_t *data;
|
||||||
|
uint32_t *typeid;
|
||||||
|
const char *label;
|
||||||
|
|
||||||
typeid = emu->cur_ev->payload.i32[0];
|
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
|
||||||
|
{
|
||||||
|
err("expecting a jumbo event\n");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
data = &emu->cur_ev->payload.jumbo.data[0];
|
||||||
|
typeid = (uint32_t *) data;
|
||||||
|
data += sizeof(*typeid);
|
||||||
|
label = (const char *) data;
|
||||||
|
|
||||||
/* Ensure the type id is new */
|
/* Ensure the type id is new */
|
||||||
HASH_FIND_INT(types, &typeid, type);
|
HASH_FIND_INT(types, typeid, type);
|
||||||
|
|
||||||
if(type != NULL)
|
if(type != NULL)
|
||||||
{
|
{
|
||||||
err("A task type with id %d already exists\n", p->id);
|
err("A task type with id %d already exists\n", *typeid);
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -186,18 +197,20 @@ pre_type_create(struct ovni_emu *emu)
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
type->id = typeid;
|
type->id = *typeid;
|
||||||
|
type->label = label;
|
||||||
|
|
||||||
/* Add the new task type to the hash table */
|
/* Add the new task type to the hash table */
|
||||||
HASH_ADD_INT(types, id, type);
|
HASH_ADD_INT(types, id, type);
|
||||||
|
|
||||||
dbg("new task type created id=%d\n", type->id);
|
dbg("new task type created id=%d label=%s\n", type->id,
|
||||||
|
type->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pre_type(struct ovni_emu *emu)
|
pre_type(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
switch(emu->cur_ev->value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 'c': pre_type_create(emu); break;
|
case 'c': pre_type_create(emu); break;
|
||||||
default:
|
default:
|
||||||
@ -209,7 +222,7 @@ void
|
|||||||
hook_pre_nosv(struct ovni_emu *emu)
|
hook_pre_nosv(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
dbg("pre nosv\n");
|
dbg("pre nosv\n");
|
||||||
switch(emu->cur_ev->class)
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
case 'T': pre_task(emu); break;
|
case 'T': pre_task(emu); break;
|
||||||
case 'Y': pre_type(emu); break;
|
case 'Y': pre_type(emu); break;
|
||||||
@ -266,7 +279,7 @@ emit_task_end(struct ovni_emu *emu)
|
|||||||
static void
|
static void
|
||||||
emit_task(struct ovni_emu *emu)
|
emit_task(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
switch(emu->cur_ev->value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 'c': emit_task_create(emu); break;
|
case 'c': emit_task_create(emu); break;
|
||||||
case 'x': emit_task_execute(emu); break;
|
case 'x': emit_task_execute(emu); break;
|
||||||
@ -282,7 +295,7 @@ void
|
|||||||
hook_view_nosv(struct ovni_emu *emu)
|
hook_view_nosv(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
dbg("pre nosv\n");
|
dbg("pre nosv\n");
|
||||||
switch(emu->cur_ev->class)
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
case 'T': emit_task(emu); break;
|
case 'T': emit_task(emu); break;
|
||||||
default:
|
default:
|
||||||
|
18
emu_ovni.c
18
emu_ovni.c
@ -158,7 +158,7 @@ ev_thread(struct ovni_emu *emu)
|
|||||||
cpu = thread->cpu;
|
cpu = thread->cpu;
|
||||||
ev = emu->cur_ev;
|
ev = emu->cur_ev;
|
||||||
|
|
||||||
switch(ev->value)
|
switch(ev->header.value)
|
||||||
{
|
{
|
||||||
case 'c': /* create */
|
case 'c': /* create */
|
||||||
dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n",
|
dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n",
|
||||||
@ -231,13 +231,13 @@ static void
|
|||||||
ev_affinity(struct ovni_emu *emu)
|
ev_affinity(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
switch(emu->cur_ev->value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 's': ev_affinity_set(emu); break;
|
case 's': ev_affinity_set(emu); break;
|
||||||
case 'r': ev_affinity_remote(emu); break;
|
case 'r': ev_affinity_remote(emu); break;
|
||||||
default:
|
default:
|
||||||
dbg("unknown affinity event value %c\n",
|
dbg("unknown affinity event value %c\n",
|
||||||
emu->cur_ev->value);
|
emu->cur_ev->header.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,13 +294,13 @@ ev_cpu_id(struct ovni_emu *emu)
|
|||||||
static void
|
static void
|
||||||
ev_cpu(struct ovni_emu *emu)
|
ev_cpu(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
switch(emu->cur_ev->value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 'n': ev_cpu_count(emu); break;
|
case 'n': ev_cpu_count(emu); break;
|
||||||
case 'i': ev_cpu_id(emu); break;
|
case 'i': ev_cpu_id(emu); break;
|
||||||
default:
|
default:
|
||||||
dbg("unknown cpu event value %c\n",
|
dbg("unknown cpu event value %c\n",
|
||||||
emu->cur_ev->value);
|
emu->cur_ev->header.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -310,15 +310,15 @@ hook_pre_ovni(struct ovni_emu *emu)
|
|||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
|
|
||||||
switch(emu->cur_ev->class)
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
case 'H': ev_thread(emu); break;
|
case 'H': ev_thread(emu); break;
|
||||||
case 'A': ev_affinity(emu); break;
|
case 'A': ev_affinity(emu); break;
|
||||||
case 'C': ev_cpu(emu); break;
|
case 'C': ev_cpu(emu); break;
|
||||||
case 'B': dbg("burst %c\n", emu->cur_ev->value); break;
|
case 'B': dbg("burst %c\n", emu->cur_ev->header.value); break;
|
||||||
default:
|
default:
|
||||||
dbg("unknown ovni event class %c\n",
|
dbg("unknown ovni event class %c\n",
|
||||||
emu->cur_ev->class);
|
emu->cur_ev->header.class);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ emit:
|
|||||||
void
|
void
|
||||||
hook_view_ovni(struct ovni_emu *emu)
|
hook_view_ovni(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
switch(emu->cur_ev->class)
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
case 'H':
|
case 'H':
|
||||||
case 'A':
|
case 'A':
|
||||||
|
229
ovni.c
229
ovni.c
@ -9,6 +9,7 @@
|
|||||||
#include <linux/limits.h>
|
#include <linux/limits.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
@ -284,8 +285,8 @@ flush_evbuf()
|
|||||||
static void
|
static void
|
||||||
ovni_ev_set_clock(struct ovni_ev *ev)
|
ovni_ev_set_clock(struct ovni_ev *ev)
|
||||||
{
|
{
|
||||||
ev->clock_lo = (uint32_t) (rthread.clockvalue & 0xffffffff);
|
ev->header.clock_lo = (uint32_t) (rthread.clockvalue & 0xffffffff);
|
||||||
ev->clock_hi = (uint16_t) ((rthread.clockvalue >> 32) & 0xffff);
|
ev->header.clock_hi = (uint16_t) ((rthread.clockvalue >> 32) & 0xffff);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t
|
uint64_t
|
||||||
@ -293,16 +294,22 @@ ovni_ev_get_clock(struct ovni_ev *ev)
|
|||||||
{
|
{
|
||||||
uint64_t clock;
|
uint64_t clock;
|
||||||
|
|
||||||
clock = ((uint64_t) ev->clock_hi) << 32 | ((uint64_t) ev->clock_lo);
|
clock = ((uint64_t) ev->header.clock_hi) << 32 | ((uint64_t) ev->header.clock_lo);
|
||||||
return clock;
|
return clock;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv)
|
ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv)
|
||||||
{
|
{
|
||||||
ev->model = mcv[0];
|
ev->header.model = mcv[0];
|
||||||
ev->class = mcv[1];
|
ev->header.class = mcv[1];
|
||||||
ev->value = mcv[2];
|
ev->header.value = mcv[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t
|
||||||
|
get_jumbo_payload_size(struct ovni_ev *ev)
|
||||||
|
{
|
||||||
|
return sizeof(ev->payload.jumbo.size) + ev->payload.jumbo.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -310,7 +317,10 @@ ovni_payload_size(struct ovni_ev *ev)
|
|||||||
{
|
{
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
size = ev->flags & 0x0f;
|
if(ev->header.flags & OVNI_EV_JUMBO)
|
||||||
|
return get_jumbo_payload_size(ev);
|
||||||
|
|
||||||
|
size = ev->header.flags & 0x0f;
|
||||||
|
|
||||||
if(size == 0)
|
if(size == 0)
|
||||||
return 0;
|
return 0;
|
||||||
@ -327,6 +337,9 @@ ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size)
|
|||||||
{
|
{
|
||||||
int payload_size;
|
int payload_size;
|
||||||
|
|
||||||
|
assert((ev->header.flags & OVNI_EV_JUMBO) == 0);
|
||||||
|
assert(size >= 2);
|
||||||
|
|
||||||
payload_size = ovni_payload_size(ev);
|
payload_size = ovni_payload_size(ev);
|
||||||
|
|
||||||
/* Ensure we have room */
|
/* Ensure we have room */
|
||||||
@ -335,37 +348,17 @@ ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size)
|
|||||||
memcpy(&ev->payload.u8[payload_size], buf, size);
|
memcpy(&ev->payload.u8[payload_size], buf, size);
|
||||||
payload_size += size;
|
payload_size += size;
|
||||||
|
|
||||||
ev->flags = ev->flags & 0xf0 | (payload_size-1) & 0x0f;
|
ev->header.flags = ev->header.flags & 0xf0 | (payload_size-1) & 0x0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
ovni_ev_size(struct ovni_ev *ev)
|
ovni_ev_size(struct ovni_ev *ev)
|
||||||
{
|
{
|
||||||
return sizeof(*ev) - sizeof(ev->payload) +
|
return sizeof(ev->header) + ovni_payload_size(ev);
|
||||||
ovni_payload_size(ev);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ovni_ev_add(struct ovni_ev *ev)
|
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
|
int
|
||||||
ovni_flush()
|
ovni_flush()
|
||||||
@ -393,6 +386,79 @@ ovni_flush()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ovni_ev_add_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize)
|
||||||
|
{
|
||||||
|
size_t evsize, totalsize;
|
||||||
|
|
||||||
|
assert(ovni_payload_size(ev) == 0);
|
||||||
|
|
||||||
|
ovni_payload_add(ev, (uint8_t *) &bufsize, sizeof(bufsize));
|
||||||
|
evsize = ovni_ev_size(ev);
|
||||||
|
|
||||||
|
totalsize = evsize + bufsize;
|
||||||
|
|
||||||
|
/* Check if the event fits or flush first otherwise */
|
||||||
|
if(rthread.evlen + totalsize >= OVNI_MAX_EV_BUF)
|
||||||
|
ovni_flush();
|
||||||
|
|
||||||
|
/* Se the jumbo flag here, so we capture the previous evsize
|
||||||
|
* properly, ignoring the jumbo buffer */
|
||||||
|
ev->header.flags |= OVNI_EV_JUMBO;
|
||||||
|
|
||||||
|
memcpy(&rthread.evbuf[rthread.evlen], ev, evsize);
|
||||||
|
rthread.evlen += evsize;
|
||||||
|
memcpy(&rthread.evbuf[rthread.evlen], buf, bufsize);
|
||||||
|
rthread.evlen += bufsize;
|
||||||
|
|
||||||
|
assert(rthread.evlen < OVNI_MAX_EV_BUF);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
ovni_ev_add(struct ovni_ev *ev)
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
|
||||||
|
size = ovni_ev_size(ev);
|
||||||
|
|
||||||
|
/* Check if the event fits or flush first otherwise */
|
||||||
|
if(rthread.evlen + size >= OVNI_MAX_EV_BUF)
|
||||||
|
ovni_flush();
|
||||||
|
|
||||||
|
memcpy(&rthread.evbuf[rthread.evlen], ev, size);
|
||||||
|
rthread.evlen += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize)
|
||||||
|
{
|
||||||
|
ovni_ev_set_clock(ev);
|
||||||
|
ovni_ev_add_jumbo(ev, buf, bufsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ovni_ev(struct ovni_ev *ev)
|
||||||
|
{
|
||||||
|
ovni_ev_set_clock(ev);
|
||||||
|
ovni_ev_add(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_thread(struct ovni_ethread *thread, int tid, char *filepath)
|
||||||
|
{
|
||||||
|
thread->tid = tid;
|
||||||
|
thread->stream_fd = open(filepath, O_RDONLY);
|
||||||
|
|
||||||
|
if(thread->stream_fd == -1)
|
||||||
|
{
|
||||||
|
perror("open");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
thread->state = TH_ST_UNKNOWN;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
load_proc(struct ovni_eproc *proc, char *procdir)
|
load_proc(struct ovni_eproc *proc, char *procdir)
|
||||||
@ -425,20 +491,12 @@ load_proc(struct ovni_eproc *proc, char *procdir)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sprintf(path, "%s/%s", procdir, dirent->d_name);
|
||||||
|
|
||||||
thread = &proc->thread[proc->nthreads++];
|
thread = &proc->thread[proc->nthreads++];
|
||||||
thread->tid = atoi(p);
|
|
||||||
|
|
||||||
sprintf(path, "%s/%s", procdir, dirent->d_name);
|
if(load_thread(thread, atoi(p), path) != 0)
|
||||||
thread->f = fopen(path, "r");
|
|
||||||
thread->state = TH_ST_UNKNOWN;
|
|
||||||
|
|
||||||
if(thread->f == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "fopen %s failed: %s\n",
|
|
||||||
path, strerror(errno));
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
closedir(dir);
|
||||||
@ -503,6 +561,30 @@ ovni_load_trace(struct ovni_trace *trace, char *tracedir)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_stream_buf(struct ovni_stream *stream, struct ovni_ethread *thread)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if(fstat(thread->stream_fd, &st) < 0)
|
||||||
|
{
|
||||||
|
perror("fstat");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->size = st.st_size;
|
||||||
|
stream->buf = mmap(NULL, stream->size, PROT_READ, MAP_SHARED,
|
||||||
|
thread->stream_fd, 0);
|
||||||
|
|
||||||
|
if(stream->buf == MAP_FAILED)
|
||||||
|
{
|
||||||
|
perror("mmap");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Populates the streams in a single array */
|
/* Populates the streams in a single array */
|
||||||
int
|
int
|
||||||
ovni_load_streams(struct ovni_trace *trace)
|
ovni_load_streams(struct ovni_trace *trace)
|
||||||
@ -549,13 +631,20 @@ ovni_load_streams(struct ovni_trace *trace)
|
|||||||
thread = &proc->thread[k];
|
thread = &proc->thread[k];
|
||||||
stream = &trace->stream[s++];
|
stream = &trace->stream[s++];
|
||||||
|
|
||||||
stream->f = thread->f;
|
if(load_stream_buf(stream, thread) != 0)
|
||||||
|
{
|
||||||
|
err("load_stream_buf failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
stream->tid = thread->tid;
|
stream->tid = thread->tid;
|
||||||
stream->thread = k;
|
stream->thread = k;
|
||||||
stream->proc = j;
|
stream->proc = j;
|
||||||
stream->loom = i;
|
stream->loom = i;
|
||||||
stream->active = 1;
|
stream->active = 1;
|
||||||
stream->lastclock = 0;
|
stream->lastclock = 0;
|
||||||
|
stream->offset = 0;
|
||||||
|
stream->cur_ev = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -569,45 +658,51 @@ ovni_free_streams(struct ovni_trace *trace)
|
|||||||
free(trace->stream);
|
free(trace->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
ovni_load_next_event(struct ovni_stream *stream)
|
ovni_load_next_event(struct ovni_stream *stream)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
size_t n, size;
|
size_t n, size;
|
||||||
struct ovni_ev *ev;
|
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
|
|
||||||
if(!stream->active)
|
if(stream->active == 0)
|
||||||
return;
|
|
||||||
|
|
||||||
ev = &stream->last;
|
|
||||||
if((n = fread(&ev->flags, sizeof(ev->flags), 1, stream->f)) != 1)
|
|
||||||
{
|
{
|
||||||
dbg("stream is empty\n");
|
dbg("stream is inactive, cannot load more events\n");
|
||||||
stream->active = 0;
|
return -1;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//dbg("flags = %d\n", ev->flags);
|
if(stream->cur_ev == NULL)
|
||||||
|
|
||||||
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->cur_ev = (struct ovni_ev *) stream->buf;
|
||||||
stream->active = 0;
|
stream->offset = 0;
|
||||||
return;
|
dbg("first event\n");
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//printf("advancing offset %ld bytes\n", ovni_ev_size(stream->cur_ev));
|
||||||
|
stream->offset += ovni_ev_size(stream->cur_ev);
|
||||||
|
|
||||||
|
/* We have reached the end */
|
||||||
|
if(stream->offset == stream->size)
|
||||||
|
{
|
||||||
|
stream->active = 0;
|
||||||
|
dbg("stream runs out of events\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* It cannot overflow, otherwise we are reading garbage */
|
||||||
|
assert(stream->offset < stream->size);
|
||||||
|
|
||||||
|
stream->cur_ev = (struct ovni_ev *) &stream->buf[stream->offset];
|
||||||
|
|
||||||
|
out:
|
||||||
|
|
||||||
|
//dbg("---------\n");
|
||||||
|
//dbg("ev size = %d\n", ovni_ev_size(stream->cur_ev));
|
||||||
|
//dbg("ev flags = %02x\n", stream->cur_ev->header.flags);
|
||||||
//dbg("loaded next event:\n");
|
//dbg("loaded next event:\n");
|
||||||
//hexdump((uint8_t *) ev, ovni_ev_size(ev));
|
//hexdump((uint8_t *) stream->cur_ev, ovni_ev_size(stream->cur_ev));
|
||||||
//dbg("---------\n");
|
//dbg("---------\n");
|
||||||
|
|
||||||
stream->active = 1;
|
return 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
44
ovni.h
44
ovni.h
@ -18,25 +18,46 @@
|
|||||||
|
|
||||||
/* ----------------------- common ------------------------ */
|
/* ----------------------- common ------------------------ */
|
||||||
|
|
||||||
union __attribute__((__packed__)) ovni_ev_payload {
|
enum ovni_ev_flags {
|
||||||
uint8_t u8[16];
|
OVNI_EV_JUMBO = 0x10,
|
||||||
int8_t i8[16];
|
|
||||||
uint16_t u16[8];
|
|
||||||
int16_t i16[8];
|
|
||||||
uint32_t u32[4];
|
|
||||||
int32_t i32[4];
|
|
||||||
uint64_t u64[2];
|
|
||||||
int64_t i64[2];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct __attribute__((__packed__)) ovni_ev {
|
struct __attribute__((__packed__)) ovni_jumbo_payload {
|
||||||
|
uint32_t size;
|
||||||
|
uint8_t data[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
union __attribute__((__packed__)) ovni_ev_payload {
|
||||||
|
|
||||||
|
int8_t i8[16];
|
||||||
|
int16_t i16[8];
|
||||||
|
int32_t i32[4];
|
||||||
|
int64_t i64[2];
|
||||||
|
|
||||||
|
uint8_t u8[16];
|
||||||
|
uint16_t u16[8];
|
||||||
|
uint32_t u32[4];
|
||||||
|
uint64_t u64[2];
|
||||||
|
|
||||||
|
struct ovni_jumbo_payload jumbo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((__packed__)) ovni_ev_header {
|
||||||
/* first 4 bits reserved, last 4 for payload size */
|
/* first 4 bits reserved, last 4 for payload size */
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint8_t model;
|
uint8_t model;
|
||||||
uint8_t class;
|
uint8_t class;
|
||||||
uint8_t value;
|
uint8_t value;
|
||||||
uint16_t clock_hi;
|
|
||||||
uint32_t clock_lo;
|
uint32_t clock_lo;
|
||||||
|
uint16_t clock_hi;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __attribute__((__packed__)) ovni_ev {
|
||||||
|
struct ovni_ev_header header;
|
||||||
|
|
||||||
|
/* The payload size may vary depending on the ev type:
|
||||||
|
* - normal: 0, or 2 to 16 bytes
|
||||||
|
* - jumbo: 0 to 2^32 - 1 bytes */
|
||||||
union ovni_ev_payload payload;
|
union ovni_ev_payload payload;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -100,6 +121,7 @@ int ovni_payload_size(struct ovni_ev *ev);
|
|||||||
|
|
||||||
/* Set the current clock in the event and queue it */
|
/* Set the current clock in the event and queue it */
|
||||||
void ovni_ev(struct ovni_ev *ev);
|
void ovni_ev(struct ovni_ev *ev);
|
||||||
|
void ovni_ev_jumbo(struct ovni_ev *ev, uint8_t *buf, uint32_t bufsize);
|
||||||
|
|
||||||
int ovni_flush();
|
int ovni_flush();
|
||||||
|
|
||||||
|
10
ovni2prv.c
10
ovni2prv.c
@ -31,7 +31,7 @@ void emit(struct ovni_stream *stream, struct ovni_ev *ev)
|
|||||||
//2:0:1:1:7:1542091:6400025:1
|
//2:0:1:1:7:1542091:6400025:1
|
||||||
//2:0:1:1:7:1542091:6400017:0
|
//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);
|
printf("2:0:1:1:%d:%ld:%d:%d\n", stream->thread+1, delta, ev->header.class, ev->header.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void dump_events(struct ovni_trace *trace)
|
void dump_events(struct ovni_trace *trace)
|
||||||
@ -63,7 +63,7 @@ void dump_events(struct ovni_trace *trace)
|
|||||||
if(!stream->active)
|
if(!stream->active)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ev = &stream->last;
|
ev = stream->cur_ev;
|
||||||
if(f < 0 || ovni_ev_get_clock(ev) < minclock)
|
if(f < 0 || ovni_ev_get_clock(ev) < minclock)
|
||||||
{
|
{
|
||||||
f = i;
|
f = i;
|
||||||
@ -78,15 +78,15 @@ void dump_events(struct ovni_trace *trace)
|
|||||||
|
|
||||||
stream = &trace->stream[f];
|
stream = &trace->stream[f];
|
||||||
|
|
||||||
if(lastclock >= ovni_ev_get_clock(&stream->last))
|
if(lastclock >= ovni_ev_get_clock(stream->cur_ev))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "warning: backwards jump in time\n");
|
fprintf(stderr, "warning: backwards jump in time\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit current event */
|
/* Emit current event */
|
||||||
emit(stream, &stream->last);
|
emit(stream, stream->cur_ev);
|
||||||
|
|
||||||
lastclock = ovni_ev_get_clock(&stream->last);
|
lastclock = ovni_ev_get_clock(stream->cur_ev);
|
||||||
|
|
||||||
/* Read the next one */
|
/* Read the next one */
|
||||||
ovni_load_next_event(stream);
|
ovni_load_next_event(stream);
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
|
|
||||||
void ovni_load_next_event(struct ovni_stream *stream);
|
int ovni_load_next_event(struct ovni_stream *stream);
|
||||||
|
|
||||||
int ovni_load_trace(struct ovni_trace *trace, char *tracedir);
|
int ovni_load_trace(struct ovni_trace *trace, char *tracedir);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user