From fbfbb8fc0f03bcea4597cc7c28248ba28ec45ecf Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Date: Thu, 21 Oct 2021 16:15:29 +0200 Subject: [PATCH] Introduce channels --- Makefile | 2 +- chan.c | 176 ++++++++++++++++++++++++++ chan.h | 33 +++++ emu.c | 55 ++++++++ emu.h | 65 +++++++--- emu_nosv.c | 28 +++++ emu_nosv_ss.c | 337 +++++--------------------------------------------- emu_ovni.c | 112 +++++++++++------ 8 files changed, 443 insertions(+), 365 deletions(-) create mode 100644 chan.c create mode 100644 chan.h diff --git a/Makefile b/Makefile index 6a601ee..a0dccd1 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ dump: ovni.o dump.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 $(LINK.c) -shared $^ -o $@ diff --git a/chan.c b/chan.c new file mode 100644 index 0000000..74244f4 --- /dev/null +++ b/chan.c @@ -0,0 +1,176 @@ +#include + +#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; +} diff --git a/chan.h b/chan.h new file mode 100644 index 0000000..2e60c35 --- /dev/null +++ b/chan.h @@ -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 */ diff --git a/emu.c b/emu.c index 2b97c07..d9b2487 100644 --- a/emu.c +++ b/emu.c @@ -17,6 +17,7 @@ #include "emu.h" #include "prv.h" #include "pcf.h" +#include "chan.h" /* Obtains the corrected clock of the given event */ int64_t @@ -75,6 +76,18 @@ find_thread(struct ovni_eproc *proc, pid_t tid) return NULL; } +static void +emit_channels(struct ovni_emu *emu) +{ + struct ovni_ethread *th; + int i; + + th = emu->cur_thread; + + for(i=0; ichan[i]); +} + static void hook_pre(struct ovni_emu *emu) { @@ -99,6 +112,8 @@ hook_emit(struct ovni_emu *emu) { //emu_emit(emu); + emit_channels(emu); + switch(emu->cur_ev->header.model) { case 'O': hook_emit_ovni(emu); @@ -665,6 +680,44 @@ emu_virtual_ev(struct ovni_emu *emu, char *mcv) trace->nvirtual++; } +static void +init_thread(struct ovni_emu *emu, struct ovni_ethread *th) +{ + int i, row; + + row = th->gindex + 1; + + for(i=0; ichan[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; inlooms; i++) + { + loom = &trace->loom[i]; + for(j=0; jnprocs; j++) + { + proc = &loom->proc[j]; + for(k=0; knthreads; k++) + { + thread = &proc->thread[k]; + + init_thread(emu, thread); + } + } + } +} + static void 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_pcfs(emu, emu->tracedir); + + init_threads(emu); } static void diff --git a/emu.h b/emu.h index e4c7e6d..4cd9084 100644 --- a/emu.h +++ b/emu.h @@ -64,7 +64,54 @@ struct nosv_task_type { 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 */ enum prv_type { @@ -105,22 +152,14 @@ struct ovni_ethread { /* Current 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 * structures */ /* nosv task */ struct nosv_task *task; - /* Should we print the subsystem? */ - int show_ss; + /* Channels are used to output the emulator state in PRV */ + struct ovni_chan chan[CHAN_MAX]; }; /* State of each emulated process */ @@ -180,10 +219,6 @@ struct ovni_cpu { /* The threads the cpu is currently running */ size_t nthreads; struct ovni_ethread *thread[OVNI_MAX_THR]; - - ///* Each channel emits events in the PRV file */ - //int nchannels; - //struct ovni_channel *channel; }; /* ----------------------- trace ------------------------ */ diff --git a/emu_nosv.c b/emu_nosv.c index a5d36bb..260381f 100644 --- a/emu_nosv.c +++ b/emu_nosv.c @@ -5,6 +5,7 @@ #include "ovni_trace.h" #include "emu.h" #include "prv.h" +#include "chan.h" enum nosv_prv_type { PRV_TYPE_PROCID @@ -15,6 +16,28 @@ struct hook_entry { 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; itotal_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 ------------------------------- */ static void @@ -286,6 +309,11 @@ emit_task(struct ovni_emu *emu) void hook_emit_nosv(struct ovni_emu *emu) { + struct ovni_ethread *th; + int i; + + th = emu->cur_thread; + switch(emu->cur_ev->header.class) { case 'T': emit_task(emu); break; diff --git a/emu_nosv_ss.c b/emu_nosv_ss.c index 1a8b101..5ca4481 100644 --- a/emu_nosv_ss.c +++ b/emu_nosv_ss.c @@ -5,6 +5,7 @@ #include "ovni_trace.h" #include "emu.h" #include "prv.h" +#include "chan.h" /* 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 @@ -12,94 +13,34 @@ * execution. Events such as task received by a thread are emitted as * 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 ------------------------------- */ static void pre_sched(struct ovni_emu *emu) { struct ovni_ethread *th; + struct ovni_chan *chan; th = emu->cur_thread; + chan = &th->chan[CHAN_NOSV_SS]; + switch(emu->cur_ev->header.value) { case 'h': - ss_push(th, ST_SCHED_HUNGRY); + chan_push(chan, ST_SCHED_HUNGRY); break; case 'f': /* Fill: no longer hungry */ - ss_pop(th, ST_SCHED_HUNGRY); + chan_pop(chan, ST_SCHED_HUNGRY); break; case '[': /* Server enter */ - ss_push(th, ST_SCHED_SERVING); + chan_push(chan, ST_SCHED_SERVING); break; case ']': /* Server exit */ - ss_pop(th, ST_SCHED_SERVING); + chan_pop(chan, ST_SCHED_SERVING); break; - case '@': ss_ev(th, EV_SCHED_SELF); break; - case 'r': ss_ev(th, EV_SCHED_RECV); break; - case 's': ss_ev(th, EV_SCHED_SEND); break; + case '@': chan_ev(chan, EV_SCHED_SELF); break; + case 'r': chan_ev(chan, EV_SCHED_RECV); break; + case 's': chan_ev(chan, EV_SCHED_SEND); break; default: break; } @@ -109,12 +50,15 @@ static void pre_submit(struct ovni_emu *emu) { struct ovni_ethread *th; + struct ovni_chan *chan; th = emu->cur_thread; + chan = &th->chan[CHAN_NOSV_SS]; + switch(emu->cur_ev->header.value) { - case '[': ss_push(th, ST_SCHED_SUBMITTING); break; - case ']': ss_pop(th, ST_SCHED_SUBMITTING); break; + case '[': chan_push(chan, ST_SCHED_SUBMITTING); break; + case ']': chan_pop(chan, ST_SCHED_SUBMITTING); break; default: break; } @@ -124,94 +68,30 @@ static void pre_memory(struct ovni_emu *emu) { struct ovni_ethread *th; + struct ovni_chan *chan; th = emu->cur_thread; + chan = &th->chan[CHAN_NOSV_SS]; + switch(emu->cur_ev->header.value) { - case '[': ss_push(th, ST_MEM_ALLOCATING); break; - case ']': ss_pop(th, ST_MEM_ALLOCATING); break; + case '[': chan_push(chan, ST_MEM_ALLOCATING); break; + case ']': chan_pop(chan, ST_MEM_ALLOCATING); break; default: 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 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 '*': - switch(emu->cur_ev->header.class) - { - 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; + case 'S': pre_sched(emu); break; + case 'U': pre_submit(emu); break; + case 'M': pre_memory(emu); break; default: break; } @@ -219,173 +99,15 @@ hook_pre_nosv_ss(struct ovni_emu *emu) /* --------------------------- 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; inupdated_cpus; i++) - //{ - // cpu = loom->updated_cpu[i]; - - // if(cpu->nthreads > 1) - // { - // prv_stream_disable(cpu->ss_stream); - // } - //} -} - void 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_chan *chan; th = emu->cur_thread; - if(th->show_ss == 0) - { - 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)); + chan_emit(&th->chan[CHAN_NOSV_SS]); } /* --------------------------- post ------------------------------- */ @@ -393,5 +115,4 @@ hook_emit_nosv_ss(struct ovni_emu *emu) void hook_post_nosv_ss(struct ovni_emu *emu) { - emu->cur_thread->ss_event = EV_NULL; } diff --git a/emu_ovni.c b/emu_ovni.c index e380e72..d287cd6 100644 --- a/emu_ovni.c +++ b/emu_ovni.c @@ -1,12 +1,35 @@ #include "ovni.h" #include "emu.h" #include "prv.h" +#include "chan.h" #include /* The emulator ovni module provides the execution model by tracking the thread * 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; ichan[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 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); } - static void print_threads_state(struct ovni_loom *loom) { @@ -116,61 +138,64 @@ print_threads_state(struct ovni_loom *loom) } static void -ev_thread_execute(struct ovni_emu *emu) +pre_thread_execute(struct ovni_emu *emu) { struct ovni_cpu *cpu; + struct ovni_ethread *th; int cpuid; + th = emu->cur_thread; + /* 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]; - //dbg("thread %d runs in cpuid %d\n", emu->cur_thread->tid, + //dbg("thread %d runs in cpuid %d\n", th->tid, // cpuid); cpu = emu_get_cpu(emu->cur_loom, cpuid); - emu->cur_thread->state = TH_ST_RUNNING; - emu->cur_thread->cpu = cpu; + thread_set_state(th, TH_ST_RUNNING); + th->cpu = cpu; - emu_cpu_add_thread(emu, cpu, emu->cur_thread); + emu_cpu_add_thread(emu, cpu, th); } 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->cpu); 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; } 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->cpu); 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 -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->cpu); 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 -ev_thread(struct ovni_emu *emu) +pre_thread(struct ovni_emu *emu) { struct ovni_ev *ev; struct ovni_cpu *cpu; @@ -193,27 +218,19 @@ ev_thread(struct ovni_emu *emu) 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; + case 'x': pre_thread_execute(emu); break; + case 'e': pre_thread_end(emu); break; + case 'p': pre_thread_pause(emu); break; + case 'r': pre_thread_resume(emu); break; default: err("unknown thread event value %c\n", ev->header.value); 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 -ev_affinity_set(struct ovni_emu *emu) +pre_affinity_set(struct ovni_emu *emu) { int cpuid; struct ovni_cpu *newcpu; @@ -235,7 +252,7 @@ ev_affinity_set(struct ovni_emu *emu) } static void -ev_affinity_remote(struct ovni_emu *emu) +pre_affinity_remote(struct ovni_emu *emu) { int cpuid, tid; struct ovni_cpu *newcpu; @@ -279,13 +296,13 @@ ev_affinity_remote(struct ovni_emu *emu) } static void -ev_affinity(struct ovni_emu *emu) +pre_affinity(struct ovni_emu *emu) { //emu_emit(emu); switch(emu->cur_ev->header.value) { - case 's': ev_affinity_set(emu); break; - case 'r': ev_affinity_remote(emu); break; + case 's': pre_affinity_set(emu); break; + case 'r': pre_affinity_remote(emu); break; default: dbg("unknown affinity event value %c\n", emu->cur_ev->header.value); @@ -303,8 +320,8 @@ hook_pre_ovni(struct ovni_emu *emu) switch(emu->cur_ev->header.class) { - case 'H': ev_thread(emu); break; - case 'A': ev_affinity(emu); break; + case 'H': pre_thread(emu); break; + case 'A': pre_affinity(emu); break; case 'B': //dbg("burst %c\n", emu->cur_ev->header.value); break; @@ -317,21 +334,26 @@ hook_pre_ovni(struct ovni_emu *emu) //print_threads_state(emu); } +/* --------------------------- emit ------------------------------- */ + static void emit_thread_state(struct ovni_emu *emu) { - int row, st, tid; - - st = emu->cur_thread->state; - row = emu->cur_thread->gindex + 1; - tid = emu->cur_thread->tid; + int i, row; + struct ovni_ethread *th; - prv_ev_thread(emu, row, PTT_THREAD_STATE, st); + th = emu->cur_thread; + row = th->gindex + 1; - if(st == TH_ST_RUNNING) - prv_ev_thread(emu, row, PTT_THREAD_TID, tid); + prv_ev_thread(emu, row, PTT_THREAD_STATE, th->state); + + if(th->state == TH_ST_RUNNING) + prv_ev_thread(emu, row, PTT_THREAD_TID, th->tid); else prv_ev_thread(emu, row, PTT_THREAD_TID, 0); + + chan_set(&th->chan[CHAN_OVNI_TID], th->tid); + } static void @@ -390,6 +412,8 @@ emit_current_pid(struct ovni_emu *emu) void hook_emit_ovni(struct ovni_emu *emu) { + int i; + if(emu->cur_ev->header.model != 'O') return; @@ -405,8 +429,14 @@ hook_emit_ovni(struct ovni_emu *emu) default: break; } + + /* Emit all enabled channels */ + for(i=0; icur_thread->chan[i]); } +/* --------------------------- post ------------------------------- */ + /* Reset thread state */ static void post_virtual_thread(struct ovni_emu *emu)