Distribute emulator into modules

This commit is contained in:
Rodrigo Arias 2021-07-28 11:56:35 +02:00
parent cfc4eb7527
commit d25bbed350
10 changed files with 805 additions and 116 deletions

View File

@ -3,15 +3,14 @@ CFLAGS=-fPIC
# Debug CFLAGS # Debug CFLAGS
#CFLAGS+=-fsanitize=address #CFLAGS+=-fsanitize=address
#LDFLAGS+=-fsanitize=address #LDFLAGS+=-fsanitize=address
#CFLAGS+=-g -O0 CFLAGS+=-g -O0
# Performance CFLAGS # Performance CFLAGS
CFLAGS+=-O3 #CFLAGS+=-O3
CFLAGS+=-fstack-protector-explicit #CFLAGS+=-fstack-protector-explicit
CFLAGS+=-flto #CFLAGS+=-flto
BIN=dump libovni.a test_speed ovni2prv BIN=dump libovni.a test_speed ovni2prv emu
#BIN=dump libovni.a prvth test_speed emu
all: $(BIN) all: $(BIN)
@ -22,7 +21,7 @@ dump: ovni.o dump.o
test_speed: test_speed.c ovni.o test_speed: test_speed.c ovni.o
emu: emu.c ovni.o emu: emu.o emu_ovni.o emu_nosv.o ovni.o
ovni2prv: ovni2prv.c ovni.o ovni2prv: ovni2prv.c ovni.o

4
dump.c
View File

@ -9,6 +9,8 @@
#include <dirent.h> #include <dirent.h>
#include "ovni.h" #include "ovni.h"
#include "ovni_trace.h"
#include "emu.h"
#define ENABLE_DEBUG #define ENABLE_DEBUG
@ -58,7 +60,7 @@ void emit(struct ovni_stream *stream, struct ovni_ev *ev)
payloadsize = ovni_payload_size(ev); payloadsize = ovni_payload_size(ev);
for(i=0; i<payloadsize; i++) for(i=0; i<payloadsize; i++)
{ {
printf("%d ", ev->payload.payload_u8[i]); printf("%02x ", ev->payload.u8[i]);
} }
printf("\n"); printf("\n");

312
emu.c Normal file
View File

@ -0,0 +1,312 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <linux/limits.h>
#include <errno.h>
#include <sys/stat.h>
#include <stdatomic.h>
#include <dirent.h>
#include <assert.h>
#include "ovni.h"
#include "ovni_trace.h"
#include "emu.h"
static void
emit_ev(struct ovni_stream *stream, struct ovni_ev *ev)
{
int64_t delta;
uint64_t clock;
int i, payloadsize;
//dbg("sizeof(*ev) = %d\n", sizeof(*ev));
//hexdump((uint8_t *) ev, sizeof(*ev));
clock = ovni_ev_get_clock(ev);
delta = clock - stream->lastclock;
dbg("%d.%d.%d %c %c %c % 20lu % 15ld ",
stream->loom, stream->proc, stream->tid,
ev->model, ev->class, ev->value, clock, delta);
payloadsize = ovni_payload_size(ev);
for(i=0; i<payloadsize; i++)
{
dbg("%d ", ev->payload.u8[i]);
}
dbg("\n");
stream->lastclock = clock;
}
void
emu_emit(struct ovni_emu *emu)
{
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 *
find_thread(struct ovni_eproc *proc, pid_t tid)
{
int i;
struct ovni_ethread *thread;
for(i=0; i<proc->nthreads; i++)
{
thread = &proc->thread[i];
if(thread->tid == tid)
return thread;
}
return NULL;
}
static void
step_emulator(struct ovni_emu *emu)
{
//emu_emit(emu);
switch(emu->cur_ev->model)
{
case 'O': emu_process_ovni_ev(emu); break;
//case 'V': emu_process_nosv_ev(emu); break;
//case 'M': emu_process_tampi_ev(emu); break;
default:
//dbg("unknown model %c\n", emu->cur_ev->model);
break;
}
}
static void
set_current(struct ovni_emu *emu, struct ovni_stream *stream)
{
emu->cur_stream = stream;
emu->cur_ev = &stream->last;
emu->cur_loom = &emu->trace.loom[stream->loom];
emu->cur_proc = &emu->cur_loom->proc[stream->proc];
emu->cur_thread = &emu->cur_proc->thread[stream->thread];
}
static int
next_event(struct ovni_emu *emu)
{
int i, f;
uint64_t minclock;
struct ovni_ev *ev;
struct ovni_stream *stream;
struct ovni_trace *trace;
trace = &emu->trace;
f = -1;
minclock = 0;
/* TODO: use a heap */
/* Select next event based on the clock */
for(i=0; i<trace->nstreams; 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);
}
}
if(f < 0)
return -1;
/* We have a valid stream with a new event */
stream = &trace->stream[f];
set_current(emu, stream);
if(emu->lastclock > ovni_ev_get_clock(&stream->last))
{
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->last);
return 0;
}
static void
emulate(struct ovni_emu *emu)
{
int i;
struct ovni_ev ev;
struct ovni_stream *stream;
struct ovni_trace *trace;
/* Load events */
trace = &emu->trace;
for(i=0; i<trace->nstreams; i++)
{
stream = &trace->stream[i];
ovni_load_next_event(stream);
}
emu->lastclock = 0;
/* Then process all events */
while(next_event(emu) == 0)
{
//fprintf(stdout, "step %i\n", i);
step_emulator(emu);
/* Read the next event */
ovni_load_next_event(emu->cur_stream);
}
}
int
emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
{
int i;
for(i=0; i<cpu->nthreads; i++)
if(cpu->thread[i] == thread)
break;
/* Not found */
if(i >= cpu->nthreads)
return -1;
return i;
}
void
emu_cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
{
int i, j;
i = emu_cpu_find_thread(cpu, thread);
/* Not found, abort */
if(i < 0)
abort();
for(j=i; j+1 < cpu->nthreads; j++)
{
cpu->thread[i] = cpu->thread[j+1];
}
cpu->nthreads--;
}
void
emu_cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
{
/* Found, abort */
if(emu_cpu_find_thread(cpu, thread) >= 0)
abort();
assert(cpu->nthreads < OVNI_MAX_THR);
cpu->thread[cpu->nthreads++] = thread;
}
struct ovni_cpu *
emu_get_cpu(struct ovni_emu *emu, int cpuid)
{
assert(cpuid < OVNI_MAX_CPU);
if(cpuid < 0)
{
return &emu->vcpu;
}
return &emu->cpu[emu->cpuind[cpuid]];
}
struct ovni_ethread *
emu_get_thread(struct ovni_emu *emu, int tid)
{
int i, j, k;
struct ovni_loom *loom;
struct ovni_eproc *proc;
struct ovni_ethread *thread;
for(i=0; i<emu->trace.nlooms; i++)
{
loom = &emu->trace.loom[i];
for(j=0; j<loom->nprocs; j++)
{
proc = &loom->proc[j];
for(k=0; k<proc->nthreads; k++)
{
thread = &proc->thread[k];
if(thread->tid == tid)
{
/* Only same process threads can
* change the affinity to each
* others */
assert(emu->cur_proc == proc);
return thread;
}
}
}
}
return thread;
}
int
main(int argc, char *argv[])
{
char *tracedir;
struct ovni_emu emu;
if(argc != 2)
{
fprintf(stderr, "missing tracedir\n");
exit(EXIT_FAILURE);
}
tracedir = argv[1];
memset(&emu, 0, sizeof(emu));
if(ovni_load_trace(&emu.trace, tracedir))
return 1;
if(ovni_load_streams(&emu.trace))
return 1;
emulate(&emu);
ovni_free_streams(&emu.trace);
return 0;
}

151
emu.h Normal file
View File

@ -0,0 +1,151 @@
#ifndef OVNI_EMU_H
#define OVNI_EMU_H
#include "ovni.h"
#include <stdio.h>
/* Debug macros */
#define ENABLE_DEBUG
#ifdef ENABLE_DEBUG
# define dbg(...) fprintf(stderr, __VA_ARGS__);
#else
# define dbg(...)
#endif
#define err(...) fprintf(stderr, __VA_ARGS__);
/* Emulated thread runtime status */
enum ethread_state {
TH_ST_UNKNOWN,
TH_ST_RUNNING,
TH_ST_PAUSED,
TH_ST_DEAD,
};
/* State of each emulated thread */
struct ovni_ethread {
/* Emulated thread tid */
pid_t tid;
/* Stream file */
FILE *f;
enum ethread_state state;
/* Thread stream */
struct ovni_stream *stream;
/* Current cpu */
struct ovni_cpu *cpu;
};
/* State of each emulated 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;
};
/* ------------------ emulation ---------------- */
enum ovni_cpu_type {
CPU_REAL,
CPU_VIRTUAL,
};
enum ovni_cpu_state {
CPU_ST_UNKNOWN,
CPU_ST_READY,
};
struct ovni_cpu {
/* Physical id */
int cpu_id;
/* Position in emu->cpu */
int index;
enum ovni_cpu_state state;
enum ovni_cpu_type type;
/* The threads the cpu is currently running */
size_t nthreads;
struct ovni_ethread *thread[OVNI_MAX_THR];
};
struct ovni_emu {
struct ovni_trace trace;
/* Physical CPUs */
int max_ncpus;
int ncpus;
struct ovni_cpu cpu[OVNI_MAX_CPU];
int cpuind[OVNI_MAX_CPU];
/* Virtual CPU */
struct ovni_cpu vcpu;
struct ovni_stream *cur_stream;
struct ovni_ev *cur_ev;
struct ovni_loom *cur_loom;
struct ovni_eproc *cur_proc;
struct ovni_ethread *cur_thread;
uint64_t lastclock;
};
/* Emulator function declaration */
void emu_emit(struct ovni_emu *emu);
void emu_process_ovni_ev(struct ovni_emu *emu);
int emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread);
void emu_cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread);
void emu_cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread);
struct ovni_cpu *emu_get_cpu(struct ovni_emu *emu, int cpuid);
struct ovni_ethread *emu_get_thread(struct ovni_emu *emu, int tid);
#endif /* OVNI_EMU_H */

13
emu_nosv.c Normal file
View File

@ -0,0 +1,13 @@
#include "ovni.h"
#include "ovni_trace.h"
#include "emu.h"
int
emu_nosv_thread_init(struct ovni_emu *emu, struct ovni_ethread *thread)
{
}
int
emu_nosv_process_ev(struct ovni_emu *emu)
{
}

265
emu_ovni.c Normal file
View File

@ -0,0 +1,265 @@
#include "ovni.h"
#include "emu.h"
#include <assert.h>
static void
print_threads_state(struct ovni_emu *emu)
{
struct ovni_cpu *cpu;
int i, j;
for(i=0; i<emu->ncpus; i++)
{
cpu = &emu->cpu[i];
dbg("-- cpu %d runs %d threads:", i, cpu->nthreads);
for(j=0; j<cpu->nthreads; j++)
{
dbg(" %d", cpu->thread[j]->tid);
}
dbg("\n");
}
dbg("-- vcpu runs %d threads:", emu->vcpu.nthreads);
for(j=0; j<emu->vcpu.nthreads; j++)
{
dbg(" %d", emu->vcpu.thread[j]->tid);
}
dbg("\n");
}
static void
ev_thread_execute(struct ovni_emu *emu)
{
struct ovni_cpu *cpu;
int cpuid;
/* The thread cannot be already running */
assert(emu->cur_thread->state != TH_ST_RUNNING);
cpuid = emu->cur_ev->payload.i32[0];
dbg("thread %d runs in cpuid %d\n", emu->cur_thread->tid,
cpuid);
cpu = emu_get_cpu(emu, cpuid);
emu->cur_thread->state = TH_ST_RUNNING;
emu->cur_thread->cpu = cpu;
emu_cpu_add_thread(cpu, emu->cur_thread);
}
static void
ev_thread_end(struct ovni_emu *emu)
{
assert(emu->cur_thread->state == TH_ST_RUNNING);
assert(emu->cur_thread->cpu);
emu_cpu_remove_thread(emu->cur_thread->cpu, emu->cur_thread);
emu->cur_thread->state = TH_ST_DEAD;
emu->cur_thread->cpu = NULL;
}
static void
ev_thread_pause(struct ovni_emu *emu)
{
assert(emu->cur_thread->state == TH_ST_RUNNING);
assert(emu->cur_thread->cpu);
emu_cpu_remove_thread(emu->cur_thread->cpu, emu->cur_thread);
emu->cur_thread->state = TH_ST_PAUSED;
}
static void
ev_thread_resume(struct ovni_emu *emu)
{
assert(emu->cur_thread->state == TH_ST_PAUSED);
assert(emu->cur_thread->cpu);
emu_cpu_add_thread(emu->cur_thread->cpu, emu->cur_thread);
emu->cur_thread->state = TH_ST_RUNNING;
}
static void
ev_thread(struct ovni_emu *emu)
{
struct ovni_ev *ev;
struct ovni_cpu *cpu;
struct ovni_ethread *thread, *remote_thread;
int i;
emu_emit(emu);
thread = emu->cur_thread;
cpu = thread->cpu;
ev = emu->cur_ev;
switch(ev->value)
{
case 'c': /* create */
dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n",
thread->tid,
ev->payload.u32[0],
ev->payload.u32[1],
ev->payload.u32[2]);
break;
case 'x': ev_thread_execute(emu); break;
case 'e': ev_thread_end(emu); break;
case 'p': ev_thread_pause(emu); break;
case 'r': ev_thread_resume(emu); break;
default:
break;
}
}
static void
ev_affinity_set(struct ovni_emu *emu)
{
int cpuid;
struct ovni_cpu *newcpu;
cpuid = emu->cur_ev->payload.i32[0];
assert(emu->cur_thread->state == TH_ST_RUNNING);
assert(emu->cur_thread->cpu);
/* Migrate current cpu to the one at cpuid */
newcpu = emu_get_cpu(emu, cpuid);
emu_cpu_remove_thread(emu->cur_thread->cpu, emu->cur_thread);
emu_cpu_add_thread(newcpu, emu->cur_thread);
emu->cur_thread->cpu = newcpu;
dbg("cpu %d now runs %d\n", cpuid, emu->cur_thread->tid);
}
static void
ev_affinity_remote(struct ovni_emu *emu)
{
int cpuid, tid;
struct ovni_cpu *newcpu;
struct ovni_ethread *thread;
cpuid = emu->cur_ev->payload.i32[0];
tid = emu->cur_ev->payload.i32[1];
thread = emu_get_thread(emu, tid);
assert(thread);
assert(thread->state == TH_ST_PAUSED);
assert(thread->cpu);
newcpu = emu_get_cpu(emu, cpuid);
/* It must not be running in any of the cpus */
assert(emu_cpu_find_thread(thread->cpu, thread) == -1);
assert(emu_cpu_find_thread(newcpu, thread) == -1);
thread->cpu = newcpu;
dbg("thread %d switches to cpu %d by remote petition\n", tid,
cpuid);
}
static void
ev_affinity(struct ovni_emu *emu)
{
emu_emit(emu);
switch(emu->cur_ev->value)
{
case 's': ev_affinity_set(emu); break;
case 'r': ev_affinity_remote(emu); break;
default:
dbg("unknown affinity event value %c\n",
emu->cur_ev->value);
break;
}
}
static void
ev_cpu_count(struct ovni_emu *emu)
{
int i, ncpus, maxcpu;
ncpus = emu->cur_ev->payload.i32[0];
maxcpu = emu->cur_ev->payload.i32[1];
assert(ncpus < OVNI_MAX_CPU);
assert(maxcpu < OVNI_MAX_CPU);
for(i=0; i<OVNI_MAX_CPU; i++)
{
emu->cpu[i].state = CPU_ST_UNKNOWN;
emu->cpu[i].cpu_id = -1;
emu->cpuind[i] = -1;
}
emu->ncpus = 0;
emu->max_ncpus = ncpus;
}
static void
ev_cpu_id(struct ovni_emu *emu)
{
int cpuid;
cpuid = emu->cur_ev->payload.i32[0];
assert(cpuid < emu->max_ncpus);
assert(emu->ncpus < emu->max_ncpus);
assert(emu->ncpus < OVNI_MAX_CPU);
assert(emu->cpu[emu->ncpus].state == CPU_ST_UNKNOWN);
emu->cpu[emu->ncpus].state = CPU_ST_READY;
emu->cpu[emu->ncpus].cpu_id = cpuid;
emu->cpu[emu->ncpus].index = emu->ncpus;
/* Fill the translation to cpu index too */
assert(emu->cpuind[cpuid] == -1);
emu->cpuind[cpuid] = emu->ncpus;
dbg("new cpu id=%d at %d\n", cpuid, emu->ncpus);
emu->ncpus++;
}
static void
ev_cpu(struct ovni_emu *emu)
{
switch(emu->cur_ev->value)
{
case 'n': ev_cpu_count(emu); break;
case 'i': ev_cpu_id(emu); break;
default:
dbg("unknown cpu event value %c\n",
emu->cur_ev->value);
break;
}
}
void
emu_process_ovni_ev(struct ovni_emu *emu)
{
//emu_emit(emu);
switch(emu->cur_ev->class)
{
case 'H': ev_thread(emu); break;
case 'A': ev_affinity(emu); break;
case 'C': ev_cpu(emu); break;
case 'B': dbg("burst %c\n", emu->cur_ev->value); break;
default:
dbg("unknown ovni event class %c\n",
emu->cur_ev->class);
break;
}
print_threads_state(emu);
}

32
ovni.c
View File

@ -17,6 +17,7 @@
#include <dirent.h> #include <dirent.h>
#include "ovni.h" #include "ovni.h"
#include "ovni_trace.h"
#define ENABLE_DEBUG #define ENABLE_DEBUG
@ -237,9 +238,9 @@ hexdump(uint8_t *buf, size_t size)
{ {
for(j=0; j<16 && i+j < size; j++) for(j=0; j<16 && i+j < size; j++)
{ {
printf("%02x ", buf[i+j]); dbg("%02x ", buf[i+j]);
} }
printf("\n"); dbg("\n");
} }
} }
@ -307,16 +308,34 @@ ovni_ev_set_mcv(struct ovni_ev *ev, char *mcv)
int int
ovni_payload_size(struct ovni_ev *ev) ovni_payload_size(struct ovni_ev *ev)
{ {
return ev->flags & 0x0f; int size;
size = ev->flags & 0x0f;
if(size == 0)
return 0;
/* The minimum size is 2 bytes, so we can encode a length of 16
* bytes using 4 bits (0x0f) */
size++;
return size;
} }
void void
ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size) ovni_payload_add(struct ovni_ev *ev, uint8_t *buf, int size)
{ {
/* Ensure we have room */ int payload_size;
assert(ovni_payload_size(ev) + size < 16);
ev->flags = ev->flags & 0xf0 | size & 0x0f; payload_size = ovni_payload_size(ev);
/* Ensure we have room */
assert(payload_size + size <= sizeof(ev->payload));
memcpy(&ev->payload.u8[payload_size], buf, size);
payload_size += size;
ev->flags = ev->flags & 0xf0 | (payload_size-1) & 0x0f;
} }
int int
@ -412,6 +431,7 @@ load_proc(struct ovni_eproc *proc, char *procdir)
sprintf(path, "%s/%s", procdir, dirent->d_name); sprintf(path, "%s/%s", procdir, dirent->d_name);
thread->f = fopen(path, "r"); thread->f = fopen(path, "r");
thread->state = TH_ST_UNKNOWN;
if(thread->f == NULL) if(thread->f == NULL)
{ {

115
ovni.h
View File

@ -1,13 +1,12 @@
#ifndef OVNI_H #ifndef OVNI_H
#define OVNI_H #define OVNI_H
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <linux/limits.h> #include <linux/limits.h>
#include "ovni.h"
#define OVNI_MAX_CPU 256 #define OVNI_MAX_CPU 256
#define OVNI_MAX_PROC 32 #define OVNI_MAX_PROC 32
#define OVNI_MAX_THR 32 #define OVNI_MAX_THR 32
@ -19,6 +18,17 @@
/* ----------------------- common ------------------------ */ /* ----------------------- common ------------------------ */
union __attribute__((__packed__)) ovni_ev_payload {
uint8_t u8[16];
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_ev {
/* first 4 bits reserved, last 4 for payload size */ /* first 4 bits reserved, last 4 for payload size */
uint8_t flags; uint8_t flags;
@ -27,12 +37,7 @@ struct __attribute__((__packed__)) ovni_ev {
uint8_t value; uint8_t value;
uint16_t clock_hi; uint16_t clock_hi;
uint32_t clock_lo; uint32_t clock_lo;
union { union ovni_ev_payload payload;
uint8_t payload_u8[16];
uint16_t payload_u16[8];
uint32_t payload_u32[4];
uint64_t payload_u64[2];
} payload;
}; };
/* ----------------------- runtime ------------------------ */ /* ----------------------- runtime ------------------------ */
@ -75,93 +80,6 @@ struct ovni_rproc {
int ready; 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_proc_init(int loom, int proc);
int ovni_thread_init(pid_t tid); int ovni_thread_init(pid_t tid);
@ -185,12 +103,5 @@ void ovni_ev(struct ovni_ev *ev);
int ovni_flush(); 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 */ #endif /* OVNI_H */

View File

@ -9,6 +9,7 @@
#include <dirent.h> #include <dirent.h>
#include "ovni.h" #include "ovni.h"
#include "ovni_trace.h"
void emit(struct ovni_stream *stream, struct ovni_ev *ev) void emit(struct ovni_stream *stream, struct ovni_ev *ev)
{ {

15
ovni_trace.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef OVNI_TRACE_H
#define OVNI_TRACE_H
#include "ovni.h"
#include "emu.h"
void ovni_load_next_event(struct ovni_stream *stream);
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);
#endif /* OVNI_TRACE_H */