Introduce channels
This commit is contained in:
parent
13e6eabf33
commit
fbfbb8fc0f
2
Makefile
2
Makefile
@ -24,7 +24,7 @@ dump: ovni.o dump.o parson.o
|
|||||||
|
|
||||||
test_speed: test_speed.c ovni.o parson.o
|
test_speed: test_speed.c ovni.o parson.o
|
||||||
|
|
||||||
emu: emu.o emu_ovni.o emu_nosv.o emu_nosv_ss.o ovni.o prv.o pcf.o parson.o
|
emu: emu.o emu_ovni.o emu_nosv.o emu_nosv_ss.o ovni.o prv.o pcf.o parson.o chan.o
|
||||||
|
|
||||||
libovni.so: ovni.o parson.o
|
libovni.so: ovni.o parson.o
|
||||||
$(LINK.c) -shared $^ -o $@
|
$(LINK.c) -shared $^ -o $@
|
||||||
|
176
chan.c
Normal file
176
chan.c
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
#include "prv.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_init(struct ovni_chan *chan, int row, int type, FILE *prv, int64_t *clock)
|
||||||
|
{
|
||||||
|
chan->n = 0;
|
||||||
|
chan->type = type;
|
||||||
|
chan->enabled = 0;
|
||||||
|
chan->badst = ST_NULL;
|
||||||
|
chan->ev = -1;
|
||||||
|
chan->prv = prv;
|
||||||
|
chan->clock = clock;
|
||||||
|
chan->t = -1;
|
||||||
|
chan->row = row;
|
||||||
|
chan->dirty = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_enable(struct ovni_chan *chan, int enabled)
|
||||||
|
{
|
||||||
|
chan->enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chan_is_enabled(struct ovni_chan *chan)
|
||||||
|
{
|
||||||
|
return chan->enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_set(struct ovni_chan *chan, int st)
|
||||||
|
{
|
||||||
|
dbg("chan_set st=%d", st);
|
||||||
|
|
||||||
|
assert(chan->enabled);
|
||||||
|
assert(chan->dirty == 0);
|
||||||
|
|
||||||
|
if(chan->n == 0)
|
||||||
|
chan->n = 1;
|
||||||
|
|
||||||
|
chan->stack[chan->n] = st;
|
||||||
|
chan->t = *chan->clock;
|
||||||
|
chan->dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_push(struct ovni_chan *chan, int st)
|
||||||
|
{
|
||||||
|
dbg("chan_push st=%d", st);
|
||||||
|
|
||||||
|
assert(chan->enabled);
|
||||||
|
assert(chan->dirty == 0);
|
||||||
|
|
||||||
|
if(chan->n >= MAX_CHAN_STACK)
|
||||||
|
{
|
||||||
|
err("channel stack full\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->stack[chan->n++] = st;
|
||||||
|
chan->t = *chan->clock;
|
||||||
|
chan->dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chan_pop(struct ovni_chan *chan, int expected_st)
|
||||||
|
{
|
||||||
|
int st;
|
||||||
|
|
||||||
|
dbg("chan_pop expexted_st=%d", expected_st);
|
||||||
|
|
||||||
|
assert(chan->enabled);
|
||||||
|
assert(chan->dirty == 0);
|
||||||
|
|
||||||
|
if(chan->n <= 0)
|
||||||
|
{
|
||||||
|
err("channel empty\n");
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
st = chan->stack[chan->n - 1];
|
||||||
|
|
||||||
|
if(expected_st >= 0 && st != expected_st)
|
||||||
|
{
|
||||||
|
err("unexpected channel state %d (expected %d)\n",
|
||||||
|
st, expected_st);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
|
chan->n--;
|
||||||
|
chan->t = *chan->clock;
|
||||||
|
chan->dirty = 1;
|
||||||
|
|
||||||
|
return st;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_ev(struct ovni_chan *chan, int ev)
|
||||||
|
{
|
||||||
|
assert(chan->enabled);
|
||||||
|
assert(chan->dirty == 0);
|
||||||
|
assert(ev >= 0);
|
||||||
|
|
||||||
|
chan->ev = ev;
|
||||||
|
chan->t = *chan->clock;
|
||||||
|
chan->dirty = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
chan_get_st(struct ovni_chan *chan)
|
||||||
|
{
|
||||||
|
if(chan->enabled == 0)
|
||||||
|
return chan->badst;
|
||||||
|
|
||||||
|
assert(chan->n > 0);
|
||||||
|
return chan->stack[chan->n-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_ev(struct ovni_chan *chan)
|
||||||
|
{
|
||||||
|
int new, last;
|
||||||
|
|
||||||
|
assert(chan->enabled);
|
||||||
|
assert(chan->ev != -1);
|
||||||
|
|
||||||
|
new = chan->ev;
|
||||||
|
last = chan_get_st(chan);
|
||||||
|
|
||||||
|
prv_ev(chan->prv, chan->row, chan->t-1, chan->type, new);
|
||||||
|
prv_ev(chan->prv, chan->row, chan->t, chan->type, last);
|
||||||
|
|
||||||
|
chan->ev = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_st(struct ovni_chan *chan)
|
||||||
|
{
|
||||||
|
int st;
|
||||||
|
|
||||||
|
assert(chan->enabled);
|
||||||
|
|
||||||
|
st = chan_get_st(chan);
|
||||||
|
|
||||||
|
prv_ev(chan->prv, chan->row, chan->t, chan->type, st);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Emits either the current state or punctual event in the PRV file */
|
||||||
|
void
|
||||||
|
chan_emit(struct ovni_chan *chan)
|
||||||
|
{
|
||||||
|
if(chan->dirty == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Emit badst if disabled */
|
||||||
|
if(chan->enabled == 0)
|
||||||
|
{
|
||||||
|
/* No punctual events allowed when disabled */
|
||||||
|
assert(chan->ev == -1);
|
||||||
|
|
||||||
|
emit_st(chan);
|
||||||
|
goto shower;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Otherwise, emit punctual event if any or the state */
|
||||||
|
if(chan->ev != -1)
|
||||||
|
emit_ev(chan);
|
||||||
|
else
|
||||||
|
emit_st(chan);
|
||||||
|
|
||||||
|
shower:
|
||||||
|
chan->dirty = 0;
|
||||||
|
}
|
33
chan.h
Normal file
33
chan.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
#ifndef OVNI_CHAN_H
|
||||||
|
#define OVNI_CHAN_H
|
||||||
|
|
||||||
|
#include "emu.h"
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_init(struct ovni_chan *chan, int row, int type, FILE *prv, int64_t *clock);
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_enable(struct ovni_chan *chan, int enabled);
|
||||||
|
|
||||||
|
int
|
||||||
|
chan_is_enabled(struct ovni_chan *chan);
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_set(struct ovni_chan *chan, int st);
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_push(struct ovni_chan *chan, int st);
|
||||||
|
|
||||||
|
int
|
||||||
|
chan_pop(struct ovni_chan *chan, int expected_st);
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_ev(struct ovni_chan *chan, int ev);
|
||||||
|
|
||||||
|
int
|
||||||
|
chan_get_st(struct ovni_chan *chan);
|
||||||
|
|
||||||
|
void
|
||||||
|
chan_emit(struct ovni_chan *chan);
|
||||||
|
|
||||||
|
#endif /* OVNI_CHAN_H */
|
55
emu.c
55
emu.c
@ -17,6 +17,7 @@
|
|||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "prv.h"
|
#include "prv.h"
|
||||||
#include "pcf.h"
|
#include "pcf.h"
|
||||||
|
#include "chan.h"
|
||||||
|
|
||||||
/* Obtains the corrected clock of the given event */
|
/* Obtains the corrected clock of the given event */
|
||||||
int64_t
|
int64_t
|
||||||
@ -75,6 +76,18 @@ find_thread(struct ovni_eproc *proc, pid_t tid)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
emit_channels(struct ovni_emu *emu)
|
||||||
|
{
|
||||||
|
struct ovni_ethread *th;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
th = emu->cur_thread;
|
||||||
|
|
||||||
|
for(i=0; i<CHAN_MAX; i++)
|
||||||
|
chan_emit(&th->chan[i]);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hook_pre(struct ovni_emu *emu)
|
hook_pre(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
@ -99,6 +112,8 @@ hook_emit(struct ovni_emu *emu)
|
|||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
|
|
||||||
|
emit_channels(emu);
|
||||||
|
|
||||||
switch(emu->cur_ev->header.model)
|
switch(emu->cur_ev->header.model)
|
||||||
{
|
{
|
||||||
case 'O': hook_emit_ovni(emu);
|
case 'O': hook_emit_ovni(emu);
|
||||||
@ -665,6 +680,44 @@ emu_virtual_ev(struct ovni_emu *emu, char *mcv)
|
|||||||
trace->nvirtual++;
|
trace->nvirtual++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_thread(struct ovni_emu *emu, struct ovni_ethread *th)
|
||||||
|
{
|
||||||
|
int i, row;
|
||||||
|
|
||||||
|
row = th->gindex + 1;
|
||||||
|
|
||||||
|
for(i=0; i<CHAN_MAX; i++)
|
||||||
|
{
|
||||||
|
chan_init(&th->chan[i], row, type, emu->prv_thread,
|
||||||
|
&emu->delta_clock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
init_threads(struct ovni_emu *emu)
|
||||||
|
{
|
||||||
|
struct ovni_loom *loom;
|
||||||
|
struct ovni_eproc *proc;
|
||||||
|
struct ovni_ethread *thread;
|
||||||
|
int i, j, k;
|
||||||
|
|
||||||
|
for(i=0; i<trace->nlooms; i++)
|
||||||
|
{
|
||||||
|
loom = &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];
|
||||||
|
|
||||||
|
init_thread(emu, thread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emu_init(struct ovni_emu *emu, int argc, char *argv[])
|
emu_init(struct ovni_emu *emu, int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -689,6 +742,8 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[])
|
|||||||
|
|
||||||
open_prvs(emu, emu->tracedir);
|
open_prvs(emu, emu->tracedir);
|
||||||
open_pcfs(emu, emu->tracedir);
|
open_pcfs(emu, emu->tracedir);
|
||||||
|
|
||||||
|
init_threads(emu);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
65
emu.h
65
emu.h
@ -64,7 +64,54 @@ struct nosv_task_type {
|
|||||||
UT_hash_handle hh;
|
UT_hash_handle hh;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_SS_STACK 128
|
#define MAX_CHAN_STACK 128
|
||||||
|
|
||||||
|
struct ovni_chan {
|
||||||
|
/* Number of states in the stack */
|
||||||
|
int n;
|
||||||
|
|
||||||
|
/* Stack of states */
|
||||||
|
int stack[MAX_CHAN_STACK];
|
||||||
|
|
||||||
|
/* 1 if enabled, 0 if not. */
|
||||||
|
int enabled;
|
||||||
|
|
||||||
|
/* What state should be shown in errors */
|
||||||
|
int badst;
|
||||||
|
|
||||||
|
/* Punctual event: -1 if not used */
|
||||||
|
int ev;
|
||||||
|
|
||||||
|
/* Emit events of this type */
|
||||||
|
int type;
|
||||||
|
|
||||||
|
/* A pointer to a clock to sample the time */
|
||||||
|
int64_t *clock;
|
||||||
|
|
||||||
|
/* The time of the last state or event */
|
||||||
|
int64_t t;
|
||||||
|
|
||||||
|
/* Paraver row */
|
||||||
|
int row;
|
||||||
|
|
||||||
|
/* 1 if channel needs flush to PRV */
|
||||||
|
int dirty;
|
||||||
|
|
||||||
|
/* Where should the events be written to? */
|
||||||
|
FILE *prv;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum chan {
|
||||||
|
/* Ovni */
|
||||||
|
CHAN_OVNI_STATE = 0,
|
||||||
|
CHAN_OVNI_TID,
|
||||||
|
CHAN_OVNI_PID,
|
||||||
|
|
||||||
|
/* nOS-V */
|
||||||
|
CHAN_NOSV_TASK_ID,
|
||||||
|
CHAN_NOSV_SS, /* Subsystem */
|
||||||
|
CHAN_MAX
|
||||||
|
};
|
||||||
|
|
||||||
/* All PRV event types */
|
/* All PRV event types */
|
||||||
enum prv_type {
|
enum prv_type {
|
||||||
@ -105,22 +152,14 @@ struct ovni_ethread {
|
|||||||
/* Current cpu */
|
/* Current cpu */
|
||||||
struct ovni_cpu *cpu;
|
struct ovni_cpu *cpu;
|
||||||
|
|
||||||
/* Number of subsystem states in the stack */
|
|
||||||
int nss;
|
|
||||||
|
|
||||||
/* Stack of subsystem states */
|
|
||||||
int ss[MAX_SS_STACK];
|
|
||||||
|
|
||||||
int ss_event;
|
|
||||||
|
|
||||||
/* FIXME: Use a table with registrable pointers to custom data
|
/* FIXME: Use a table with registrable pointers to custom data
|
||||||
* structures */
|
* structures */
|
||||||
|
|
||||||
/* nosv task */
|
/* nosv task */
|
||||||
struct nosv_task *task;
|
struct nosv_task *task;
|
||||||
|
|
||||||
/* Should we print the subsystem? */
|
/* Channels are used to output the emulator state in PRV */
|
||||||
int show_ss;
|
struct ovni_chan chan[CHAN_MAX];
|
||||||
};
|
};
|
||||||
|
|
||||||
/* State of each emulated process */
|
/* State of each emulated process */
|
||||||
@ -180,10 +219,6 @@ struct ovni_cpu {
|
|||||||
/* The threads the cpu is currently running */
|
/* The threads the cpu is currently running */
|
||||||
size_t nthreads;
|
size_t nthreads;
|
||||||
struct ovni_ethread *thread[OVNI_MAX_THR];
|
struct ovni_ethread *thread[OVNI_MAX_THR];
|
||||||
|
|
||||||
///* Each channel emits events in the PRV file */
|
|
||||||
//int nchannels;
|
|
||||||
//struct ovni_channel *channel;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ----------------------- trace ------------------------ */
|
/* ----------------------- trace ------------------------ */
|
||||||
|
28
emu_nosv.c
28
emu_nosv.c
@ -5,6 +5,7 @@
|
|||||||
#include "ovni_trace.h"
|
#include "ovni_trace.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "prv.h"
|
#include "prv.h"
|
||||||
|
#include "chan.h"
|
||||||
|
|
||||||
enum nosv_prv_type {
|
enum nosv_prv_type {
|
||||||
PRV_TYPE_PROCID
|
PRV_TYPE_PROCID
|
||||||
@ -15,6 +16,28 @@ struct hook_entry {
|
|||||||
void (*hook)(struct ovni_emu *);
|
void (*hook)(struct ovni_emu *);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* --------------------------- init ------------------------------- */
|
||||||
|
|
||||||
|
void
|
||||||
|
hook_nosv_init(struct ovni_emu *emu)
|
||||||
|
{
|
||||||
|
struct ovni_ethread *th;
|
||||||
|
int i, row, type;
|
||||||
|
FILE *prv;
|
||||||
|
int64_t *clock;
|
||||||
|
|
||||||
|
for(i=0; i<emu->total_nthreads; i++)
|
||||||
|
{
|
||||||
|
th = emu->global_thread[i];
|
||||||
|
row = th->gindex + 1;
|
||||||
|
|
||||||
|
//chan_init(struct ovni_chan *chan, int row, int type, FILE *prv, int64_t *clock)
|
||||||
|
|
||||||
|
chan_init(th->chan[CHAN_NOSV_TASK_ID], row, PTT_TASK_ID, prv,
|
||||||
|
clock);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* --------------------------- pre ------------------------------- */
|
/* --------------------------- pre ------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -286,6 +309,11 @@ emit_task(struct ovni_emu *emu)
|
|||||||
void
|
void
|
||||||
hook_emit_nosv(struct ovni_emu *emu)
|
hook_emit_nosv(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
|
struct ovni_ethread *th;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
th = emu->cur_thread;
|
||||||
|
|
||||||
switch(emu->cur_ev->header.class)
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
case 'T': emit_task(emu); break;
|
case 'T': emit_task(emu); break;
|
||||||
|
337
emu_nosv_ss.c
337
emu_nosv_ss.c
@ -5,6 +5,7 @@
|
|||||||
#include "ovni_trace.h"
|
#include "ovni_trace.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "prv.h"
|
#include "prv.h"
|
||||||
|
#include "chan.h"
|
||||||
|
|
||||||
/* This module manages the nos-v subsystem (ss) events, to track which
|
/* This module manages the nos-v subsystem (ss) events, to track which
|
||||||
* actions are being performed by each thread at a given time. A stack
|
* actions are being performed by each thread at a given time. A stack
|
||||||
@ -12,94 +13,34 @@
|
|||||||
* execution. Events such as task received by a thread are emitted as
|
* execution. Events such as task received by a thread are emitted as
|
||||||
* fake events with very short period. */
|
* fake events with very short period. */
|
||||||
|
|
||||||
|
|
||||||
/* --------------------------- ss helpers ------------------------------- */
|
|
||||||
|
|
||||||
static void
|
|
||||||
ss_init(struct ovni_ethread *t)
|
|
||||||
{
|
|
||||||
t->nss = 0;
|
|
||||||
t->show_ss = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ss_push(struct ovni_ethread *t, int st)
|
|
||||||
{
|
|
||||||
if(t->nss >= MAX_SS_STACK)
|
|
||||||
{
|
|
||||||
err("thread %d subsystem stack full\n", t->tid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
t->ss[t->nss] = st;
|
|
||||||
t->nss++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ss_pop(struct ovni_ethread *t, int expected_st)
|
|
||||||
{
|
|
||||||
int st;
|
|
||||||
|
|
||||||
if(t->nss <= 0)
|
|
||||||
{
|
|
||||||
err("thread %d subsystem stack empty\n", t->tid);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
st = t->ss[t->nss - 1];
|
|
||||||
|
|
||||||
if(st > 0 && st != expected_st)
|
|
||||||
{
|
|
||||||
err("thread %d expected subsystem state %d (got %d)\n",
|
|
||||||
t->tid, expected_st, st);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
t->nss--;
|
|
||||||
|
|
||||||
return st;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ss_ev(struct ovni_ethread *th, int ev)
|
|
||||||
{
|
|
||||||
th->ss_event = ev;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
ss_last_st(struct ovni_ethread *th)
|
|
||||||
{
|
|
||||||
if(th->nss == 0)
|
|
||||||
return ST_NULL;
|
|
||||||
|
|
||||||
return th->ss[th->nss - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* --------------------------- pre ------------------------------- */
|
/* --------------------------- pre ------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pre_sched(struct ovni_emu *emu)
|
pre_sched(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
struct ovni_ethread *th;
|
struct ovni_ethread *th;
|
||||||
|
struct ovni_chan *chan;
|
||||||
|
|
||||||
th = emu->cur_thread;
|
th = emu->cur_thread;
|
||||||
|
chan = &th->chan[CHAN_NOSV_SS];
|
||||||
|
|
||||||
switch(emu->cur_ev->header.value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 'h':
|
case 'h':
|
||||||
ss_push(th, ST_SCHED_HUNGRY);
|
chan_push(chan, ST_SCHED_HUNGRY);
|
||||||
break;
|
break;
|
||||||
case 'f': /* Fill: no longer hungry */
|
case 'f': /* Fill: no longer hungry */
|
||||||
ss_pop(th, ST_SCHED_HUNGRY);
|
chan_pop(chan, ST_SCHED_HUNGRY);
|
||||||
break;
|
break;
|
||||||
case '[': /* Server enter */
|
case '[': /* Server enter */
|
||||||
ss_push(th, ST_SCHED_SERVING);
|
chan_push(chan, ST_SCHED_SERVING);
|
||||||
break;
|
break;
|
||||||
case ']': /* Server exit */
|
case ']': /* Server exit */
|
||||||
ss_pop(th, ST_SCHED_SERVING);
|
chan_pop(chan, ST_SCHED_SERVING);
|
||||||
break;
|
break;
|
||||||
case '@': ss_ev(th, EV_SCHED_SELF); break;
|
case '@': chan_ev(chan, EV_SCHED_SELF); break;
|
||||||
case 'r': ss_ev(th, EV_SCHED_RECV); break;
|
case 'r': chan_ev(chan, EV_SCHED_RECV); break;
|
||||||
case 's': ss_ev(th, EV_SCHED_SEND); break;
|
case 's': chan_ev(chan, EV_SCHED_SEND); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -109,12 +50,15 @@ static void
|
|||||||
pre_submit(struct ovni_emu *emu)
|
pre_submit(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
struct ovni_ethread *th;
|
struct ovni_ethread *th;
|
||||||
|
struct ovni_chan *chan;
|
||||||
|
|
||||||
th = emu->cur_thread;
|
th = emu->cur_thread;
|
||||||
|
chan = &th->chan[CHAN_NOSV_SS];
|
||||||
|
|
||||||
switch(emu->cur_ev->header.value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case '[': ss_push(th, ST_SCHED_SUBMITTING); break;
|
case '[': chan_push(chan, ST_SCHED_SUBMITTING); break;
|
||||||
case ']': ss_pop(th, ST_SCHED_SUBMITTING); break;
|
case ']': chan_pop(chan, ST_SCHED_SUBMITTING); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -124,94 +68,30 @@ static void
|
|||||||
pre_memory(struct ovni_emu *emu)
|
pre_memory(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
struct ovni_ethread *th;
|
struct ovni_ethread *th;
|
||||||
|
struct ovni_chan *chan;
|
||||||
|
|
||||||
th = emu->cur_thread;
|
th = emu->cur_thread;
|
||||||
|
chan = &th->chan[CHAN_NOSV_SS];
|
||||||
|
|
||||||
switch(emu->cur_ev->header.value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case '[': ss_push(th, ST_MEM_ALLOCATING); break;
|
case '[': chan_push(chan, ST_MEM_ALLOCATING); break;
|
||||||
case ']': ss_pop(th, ST_MEM_ALLOCATING); break;
|
case ']': chan_pop(chan, ST_MEM_ALLOCATING); break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hook for the virtual "thread changed" event */
|
|
||||||
static void
|
|
||||||
pre_thread_change(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
struct ovni_ethread *th;
|
|
||||||
|
|
||||||
th = emu->cur_thread;
|
|
||||||
|
|
||||||
/* Only print the subsystem if the thread is running */
|
|
||||||
if(th->state == TH_ST_RUNNING)
|
|
||||||
th->show_ss = 1;
|
|
||||||
else
|
|
||||||
th->show_ss = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
pre_thread(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
switch(emu->cur_ev->header.value)
|
|
||||||
{
|
|
||||||
case 'c': pre_thread_change(emu); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hook for the virtual "cpu changed" event */
|
|
||||||
static void
|
|
||||||
pre_cpu_change(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
struct ovni_ethread *th;
|
|
||||||
|
|
||||||
th = emu->cur_thread;
|
|
||||||
|
|
||||||
/* Only print the subsystem if the thread is running */
|
|
||||||
if(th->state == TH_ST_RUNNING)
|
|
||||||
th->show_ss = 1;
|
|
||||||
else
|
|
||||||
th->show_ss = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
pre_cpu(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
switch(emu->cur_ev->header.value)
|
|
||||||
{
|
|
||||||
case 'c': pre_thread_change(emu); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hook_pre_nosv_ss(struct ovni_emu *emu)
|
hook_pre_nosv_ss(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
switch(emu->cur_ev->header.model)
|
assert(emu->cur_ev->header.model == 'V');
|
||||||
|
|
||||||
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
/* Listen for virtual events as well */
|
case 'S': pre_sched(emu); break;
|
||||||
case '*':
|
case 'U': pre_submit(emu); break;
|
||||||
switch(emu->cur_ev->header.class)
|
case 'M': pre_memory(emu); break;
|
||||||
{
|
|
||||||
case 'H': pre_thread(emu); break;
|
|
||||||
case 'C': pre_cpu(emu); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
switch(emu->cur_ev->header.class)
|
|
||||||
{
|
|
||||||
case 'S': pre_sched(emu); break;
|
|
||||||
case 'U': pre_submit(emu); break;
|
|
||||||
case 'M': pre_memory(emu); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -219,173 +99,15 @@ hook_pre_nosv_ss(struct ovni_emu *emu)
|
|||||||
|
|
||||||
/* --------------------------- emit ------------------------------- */
|
/* --------------------------- emit ------------------------------- */
|
||||||
|
|
||||||
static void
|
|
||||||
emit_thread_state(struct ovni_emu *emu, struct ovni_ethread *th,
|
|
||||||
int type, int st)
|
|
||||||
{
|
|
||||||
int row;
|
|
||||||
|
|
||||||
row = th->gindex + 1;
|
|
||||||
|
|
||||||
prv_ev_thread(emu, row, type, st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
emit_cpu_state(struct ovni_emu *emu, struct ovni_ethread *th,
|
|
||||||
int type, int st)
|
|
||||||
{
|
|
||||||
/* Detect multiple threads */
|
|
||||||
if(th->cpu && th->cpu->nthreads > 1)
|
|
||||||
st = ST_BAD;
|
|
||||||
|
|
||||||
prv_ev_autocpu(emu, type, st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
emit_thread_event(struct ovni_emu *emu, struct ovni_ethread *th,
|
|
||||||
int type, int st)
|
|
||||||
{
|
|
||||||
int64_t t0, t1;
|
|
||||||
int row;
|
|
||||||
int prev_st;
|
|
||||||
|
|
||||||
row = th->gindex + 1;
|
|
||||||
|
|
||||||
t0 = emu->delta_time - 1;
|
|
||||||
t1 = emu->delta_time;
|
|
||||||
|
|
||||||
prev_st = ss_last_st(th);
|
|
||||||
|
|
||||||
/* Fake event using 1 nanosecond in the past */
|
|
||||||
prv_ev_thread_raw(emu, row, t0, type, st);
|
|
||||||
prv_ev_thread_raw(emu, row, t1, type, prev_st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
emit_cpu_event(struct ovni_emu *emu, struct ovni_ethread *th,
|
|
||||||
int type, int st)
|
|
||||||
{
|
|
||||||
int64_t t0, t1;
|
|
||||||
int row;
|
|
||||||
int prev_st;
|
|
||||||
|
|
||||||
row = th->gindex + 1;
|
|
||||||
|
|
||||||
t0 = emu->delta_time - 1;
|
|
||||||
t1 = emu->delta_time;
|
|
||||||
|
|
||||||
prev_st = ss_last_st(th);
|
|
||||||
|
|
||||||
/* Detect multiple threads */
|
|
||||||
if(th->cpu && th->cpu->nthreads > 1)
|
|
||||||
{
|
|
||||||
st = ST_BAD;
|
|
||||||
prev_st = ST_BAD;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Fake event using 1 nanosecond in the past */
|
|
||||||
prv_ev_autocpu_raw(emu, t0, type, st);
|
|
||||||
prv_ev_autocpu_raw(emu, t1, type, prev_st);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
emit_thread_changed(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
dbg("emit_thread_changed\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
emit_cpu_changed(struct ovni_emu *emu)
|
|
||||||
{
|
|
||||||
dbg("emit_cpu_changed\n")
|
|
||||||
//int i;
|
|
||||||
//struct ovni_loom *loom;
|
|
||||||
//struct ovni_cpu *cpu;
|
|
||||||
|
|
||||||
///* Detect multiple threads */
|
|
||||||
//loom = emu->cur_loom;
|
|
||||||
|
|
||||||
//assert(loom->nupdated_cpus > 0);
|
|
||||||
|
|
||||||
//for(i=0; i<loom->nupdated_cpus; i++)
|
|
||||||
//{
|
|
||||||
// cpu = loom->updated_cpu[i];
|
|
||||||
|
|
||||||
// if(cpu->nthreads > 1)
|
|
||||||
// {
|
|
||||||
// prv_stream_disable(cpu->ss_stream);
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
hook_emit_nosv_ss(struct ovni_emu *emu)
|
hook_emit_nosv_ss(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
/* We need to emit events when a thread notifies us that the subsystem
|
|
||||||
* has changed, but also when the thread is paused, or scheduled to
|
|
||||||
* another CPU, as the CPU view must be updated as well. */
|
|
||||||
|
|
||||||
switch(emu->cur_ev->header.model)
|
|
||||||
{
|
|
||||||
/* Listen for virtual events as well */
|
|
||||||
case '*':
|
|
||||||
switch(emu->cur_ev->header.class)
|
|
||||||
{
|
|
||||||
case 'H':
|
|
||||||
switch(emu->cur_ev->header.value)
|
|
||||||
{
|
|
||||||
case 'c': emit_thread_changed(emu); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'C':
|
|
||||||
switch(emu->cur_ev->header.value)
|
|
||||||
{
|
|
||||||
case 'c': emit_cpu_changed(emu); break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'V':
|
|
||||||
switch(emu->cur_ev->header.class)
|
|
||||||
{
|
|
||||||
case 'S': pre_sched(emu); break;
|
|
||||||
case 'U': pre_submit(emu); break;
|
|
||||||
case 'M': pre_memory(emu); break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct ovni_ethread *th;
|
struct ovni_ethread *th;
|
||||||
|
struct ovni_chan *chan;
|
||||||
|
|
||||||
th = emu->cur_thread;
|
th = emu->cur_thread;
|
||||||
|
|
||||||
if(th->show_ss == 0)
|
chan_emit(&th->chan[CHAN_NOSV_SS]);
|
||||||
{
|
|
||||||
emit_thread_state(emu, th, PTT_SUBSYSTEM, ST_NULL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Only emit a state if needed */
|
|
||||||
if(th->ss_event != EV_NULL)
|
|
||||||
{
|
|
||||||
emit_thread_event(emu, th, PTT_SUBSYSTEM,
|
|
||||||
th->ss_event);
|
|
||||||
emit_cpu_event(emu, th, PTC_SUBSYSTEM,
|
|
||||||
th->ss_event);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit_thread_state(emu, th, PTT_SUBSYSTEM, ss_last_st(th));
|
|
||||||
emit_cpu_state(emu, th, PTC_SUBSYSTEM, ss_last_st(th));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* --------------------------- post ------------------------------- */
|
/* --------------------------- post ------------------------------- */
|
||||||
@ -393,5 +115,4 @@ hook_emit_nosv_ss(struct ovni_emu *emu)
|
|||||||
void
|
void
|
||||||
hook_post_nosv_ss(struct ovni_emu *emu)
|
hook_post_nosv_ss(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
emu->cur_thread->ss_event = EV_NULL;
|
|
||||||
}
|
}
|
||||||
|
110
emu_ovni.c
110
emu_ovni.c
@ -1,12 +1,35 @@
|
|||||||
#include "ovni.h"
|
#include "ovni.h"
|
||||||
#include "emu.h"
|
#include "emu.h"
|
||||||
#include "prv.h"
|
#include "prv.h"
|
||||||
|
#include "chan.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
/* The emulator ovni module provides the execution model by tracking the thread
|
/* The emulator ovni module provides the execution model by tracking the thread
|
||||||
* state and which threads run in each CPU */
|
* state and which threads run in each CPU */
|
||||||
|
|
||||||
|
/* --------------------------- pre ------------------------------- */
|
||||||
|
|
||||||
|
static void
|
||||||
|
thread_set_channel_enabled(struct ovni_ethread *th, int enabled)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
for(i=0; i<CHAN_MAX; i++)
|
||||||
|
chan_enable(&th->chan[i], enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
thread_set_state(struct ovni_ethread *th, int state)
|
||||||
|
{
|
||||||
|
int enabled;
|
||||||
|
|
||||||
|
th->state = state;
|
||||||
|
|
||||||
|
enabled = (state == TH_ST_RUNNING ? 1 : 0);
|
||||||
|
|
||||||
|
thread_set_channel_enabled(th, enabled);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu)
|
update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu)
|
||||||
{
|
{
|
||||||
@ -88,7 +111,6 @@ emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_et
|
|||||||
update_cpu(emu, cpu);
|
update_cpu(emu, cpu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
print_threads_state(struct ovni_loom *loom)
|
print_threads_state(struct ovni_loom *loom)
|
||||||
{
|
{
|
||||||
@ -116,61 +138,64 @@ print_threads_state(struct ovni_loom *loom)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_thread_execute(struct ovni_emu *emu)
|
pre_thread_execute(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
struct ovni_cpu *cpu;
|
struct ovni_cpu *cpu;
|
||||||
|
struct ovni_ethread *th;
|
||||||
int cpuid;
|
int cpuid;
|
||||||
|
|
||||||
|
th = emu->cur_thread;
|
||||||
|
|
||||||
/* The thread cannot be already running */
|
/* The thread cannot be already running */
|
||||||
assert(emu->cur_thread->state != TH_ST_RUNNING);
|
assert(th->state != TH_ST_RUNNING);
|
||||||
|
|
||||||
cpuid = emu->cur_ev->payload.i32[0];
|
cpuid = emu->cur_ev->payload.i32[0];
|
||||||
//dbg("thread %d runs in cpuid %d\n", emu->cur_thread->tid,
|
//dbg("thread %d runs in cpuid %d\n", th->tid,
|
||||||
// cpuid);
|
// cpuid);
|
||||||
cpu = emu_get_cpu(emu->cur_loom, cpuid);
|
cpu = emu_get_cpu(emu->cur_loom, cpuid);
|
||||||
|
|
||||||
emu->cur_thread->state = TH_ST_RUNNING;
|
thread_set_state(th, TH_ST_RUNNING);
|
||||||
emu->cur_thread->cpu = cpu;
|
th->cpu = cpu;
|
||||||
|
|
||||||
emu_cpu_add_thread(emu, cpu, emu->cur_thread);
|
emu_cpu_add_thread(emu, cpu, th);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_thread_end(struct ovni_emu *emu)
|
pre_thread_end(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
assert(emu->cur_thread->state == TH_ST_RUNNING);
|
assert(emu->cur_thread->state == TH_ST_RUNNING);
|
||||||
assert(emu->cur_thread->cpu);
|
assert(emu->cur_thread->cpu);
|
||||||
|
|
||||||
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
|
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
|
||||||
|
|
||||||
emu->cur_thread->state = TH_ST_DEAD;
|
thread_set_state(emu->cur_thread, TH_ST_DEAD);
|
||||||
emu->cur_thread->cpu = NULL;
|
emu->cur_thread->cpu = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_thread_pause(struct ovni_emu *emu)
|
pre_thread_pause(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
assert(emu->cur_thread->state == TH_ST_RUNNING);
|
assert(emu->cur_thread->state == TH_ST_RUNNING);
|
||||||
assert(emu->cur_thread->cpu);
|
assert(emu->cur_thread->cpu);
|
||||||
|
|
||||||
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
|
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
|
||||||
|
|
||||||
emu->cur_thread->state = TH_ST_PAUSED;
|
thread_set_state(emu->cur_thread, TH_ST_PAUSED);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_thread_resume(struct ovni_emu *emu)
|
pre_thread_resume(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
assert(emu->cur_thread->state == TH_ST_PAUSED);
|
assert(emu->cur_thread->state == TH_ST_PAUSED);
|
||||||
assert(emu->cur_thread->cpu);
|
assert(emu->cur_thread->cpu);
|
||||||
|
|
||||||
emu_cpu_add_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
|
emu_cpu_add_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
|
||||||
|
|
||||||
emu->cur_thread->state = TH_ST_RUNNING;
|
thread_set_state(emu->cur_thread, TH_ST_RUNNING);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_thread(struct ovni_emu *emu)
|
pre_thread(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
struct ovni_ev *ev;
|
struct ovni_ev *ev;
|
||||||
struct ovni_cpu *cpu;
|
struct ovni_cpu *cpu;
|
||||||
@ -193,27 +218,19 @@ ev_thread(struct ovni_emu *emu)
|
|||||||
ev->payload.u32[2]);
|
ev->payload.u32[2]);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case 'x': ev_thread_execute(emu); break;
|
case 'x': pre_thread_execute(emu); break;
|
||||||
case 'e': ev_thread_end(emu); break;
|
case 'e': pre_thread_end(emu); break;
|
||||||
case 'p': ev_thread_pause(emu); break;
|
case 'p': pre_thread_pause(emu); break;
|
||||||
case 'r': ev_thread_resume(emu); break;
|
case 'r': pre_thread_resume(emu); break;
|
||||||
default:
|
default:
|
||||||
err("unknown thread event value %c\n",
|
err("unknown thread event value %c\n",
|
||||||
ev->header.value);
|
ev->header.value);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* All but create events change the thread and CPU state: inject two
|
|
||||||
* virtual events to notify other modules. The order is important. */
|
|
||||||
if(ev->header.value != 'c')
|
|
||||||
{
|
|
||||||
emu_virtual_ev(emu, "*Hc");
|
|
||||||
emu_virtual_ev(emu, "*Cc");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_affinity_set(struct ovni_emu *emu)
|
pre_affinity_set(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
int cpuid;
|
int cpuid;
|
||||||
struct ovni_cpu *newcpu;
|
struct ovni_cpu *newcpu;
|
||||||
@ -235,7 +252,7 @@ ev_affinity_set(struct ovni_emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_affinity_remote(struct ovni_emu *emu)
|
pre_affinity_remote(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
int cpuid, tid;
|
int cpuid, tid;
|
||||||
struct ovni_cpu *newcpu;
|
struct ovni_cpu *newcpu;
|
||||||
@ -279,13 +296,13 @@ ev_affinity_remote(struct ovni_emu *emu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ev_affinity(struct ovni_emu *emu)
|
pre_affinity(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
//emu_emit(emu);
|
//emu_emit(emu);
|
||||||
switch(emu->cur_ev->header.value)
|
switch(emu->cur_ev->header.value)
|
||||||
{
|
{
|
||||||
case 's': ev_affinity_set(emu); break;
|
case 's': pre_affinity_set(emu); break;
|
||||||
case 'r': ev_affinity_remote(emu); break;
|
case 'r': pre_affinity_remote(emu); break;
|
||||||
default:
|
default:
|
||||||
dbg("unknown affinity event value %c\n",
|
dbg("unknown affinity event value %c\n",
|
||||||
emu->cur_ev->header.value);
|
emu->cur_ev->header.value);
|
||||||
@ -303,8 +320,8 @@ hook_pre_ovni(struct ovni_emu *emu)
|
|||||||
|
|
||||||
switch(emu->cur_ev->header.class)
|
switch(emu->cur_ev->header.class)
|
||||||
{
|
{
|
||||||
case 'H': ev_thread(emu); break;
|
case 'H': pre_thread(emu); break;
|
||||||
case 'A': ev_affinity(emu); break;
|
case 'A': pre_affinity(emu); break;
|
||||||
case 'B':
|
case 'B':
|
||||||
//dbg("burst %c\n", emu->cur_ev->header.value);
|
//dbg("burst %c\n", emu->cur_ev->header.value);
|
||||||
break;
|
break;
|
||||||
@ -317,21 +334,26 @@ hook_pre_ovni(struct ovni_emu *emu)
|
|||||||
//print_threads_state(emu);
|
//print_threads_state(emu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------- emit ------------------------------- */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
emit_thread_state(struct ovni_emu *emu)
|
emit_thread_state(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
int row, st, tid;
|
int i, row;
|
||||||
|
struct ovni_ethread *th;
|
||||||
|
|
||||||
st = emu->cur_thread->state;
|
th = emu->cur_thread;
|
||||||
row = emu->cur_thread->gindex + 1;
|
row = th->gindex + 1;
|
||||||
tid = emu->cur_thread->tid;
|
|
||||||
|
|
||||||
prv_ev_thread(emu, row, PTT_THREAD_STATE, st);
|
prv_ev_thread(emu, row, PTT_THREAD_STATE, th->state);
|
||||||
|
|
||||||
if(st == TH_ST_RUNNING)
|
if(th->state == TH_ST_RUNNING)
|
||||||
prv_ev_thread(emu, row, PTT_THREAD_TID, tid);
|
prv_ev_thread(emu, row, PTT_THREAD_TID, th->tid);
|
||||||
else
|
else
|
||||||
prv_ev_thread(emu, row, PTT_THREAD_TID, 0);
|
prv_ev_thread(emu, row, PTT_THREAD_TID, 0);
|
||||||
|
|
||||||
|
chan_set(&th->chan[CHAN_OVNI_TID], th->tid);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -390,6 +412,8 @@ emit_current_pid(struct ovni_emu *emu)
|
|||||||
void
|
void
|
||||||
hook_emit_ovni(struct ovni_emu *emu)
|
hook_emit_ovni(struct ovni_emu *emu)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
if(emu->cur_ev->header.model != 'O')
|
if(emu->cur_ev->header.model != 'O')
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -405,8 +429,14 @@ hook_emit_ovni(struct ovni_emu *emu)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Emit all enabled channels */
|
||||||
|
for(i=0; i<CHAN_MAX; i++)
|
||||||
|
chan_emit(&emu->cur_thread->chan[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --------------------------- post ------------------------------- */
|
||||||
|
|
||||||
/* Reset thread state */
|
/* Reset thread state */
|
||||||
static void
|
static void
|
||||||
post_virtual_thread(struct ovni_emu *emu)
|
post_virtual_thread(struct ovni_emu *emu)
|
||||||
|
Loading…
Reference in New Issue
Block a user