Handle all events with CPU and thread channels

This commit is contained in:
Rodrigo Arias 2021-10-21 16:46:42 +02:00
parent cd430a35ce
commit 3f22afc4b3
5 changed files with 354 additions and 281 deletions

26
emu.c
View File

@ -149,6 +149,13 @@ emit_channels(struct ovni_emu *emu)
} }
static void
hook_init(struct ovni_emu *emu)
{
hook_init_ovni(emu);
hook_init_nosv(emu);
}
static void static void
hook_pre(struct ovni_emu *emu) hook_pre(struct ovni_emu *emu)
{ {
@ -160,9 +167,6 @@ hook_pre(struct ovni_emu *emu)
break; break;
case 'V': hook_pre_nosv(emu); case 'V': hook_pre_nosv(emu);
break; break;
case '*': hook_pre_nosv(emu);
hook_pre_ovni(emu);
break;
default: default:
break; break;
} }
@ -177,13 +181,6 @@ hook_emit(struct ovni_emu *emu)
switch(emu->cur_ev->header.model) switch(emu->cur_ev->header.model)
{ {
case 'O': hook_emit_ovni(emu);
break;
case 'V': hook_emit_nosv(emu);
break;
case '*': hook_emit_nosv(emu);
hook_emit_ovni(emu);
break;
default: default:
//dbg("unknown model %c\n", emu->cur_ev->model); //dbg("unknown model %c\n", emu->cur_ev->model);
break; break;
@ -197,13 +194,6 @@ hook_post(struct ovni_emu *emu)
switch(emu->cur_ev->header.model) switch(emu->cur_ev->header.model)
{ {
case 'O': hook_post_ovni(emu);
break;
case 'V': hook_post_nosv(emu);
break;
case '*': hook_post_nosv(emu);
hook_post_ovni(emu);
break;
default: default:
//dbg("unknown model %c\n", emu->cur_ev->model); //dbg("unknown model %c\n", emu->cur_ev->model);
break; break;
@ -315,6 +305,8 @@ emulate(struct ovni_emu *emu)
emu->lastclock = 0; emu->lastclock = 0;
hook_init(emu);
/* Then process all events */ /* Then process all events */
while(next_event(emu) == 0) while(next_event(emu) == 0)
{ {

3
emu.h
View File

@ -353,14 +353,17 @@ struct ovni_emu {
void emu_emit(struct ovni_emu *emu); void emu_emit(struct ovni_emu *emu);
void hook_init_ovni(struct ovni_emu *emu);
void hook_pre_ovni(struct ovni_emu *emu); void hook_pre_ovni(struct ovni_emu *emu);
void hook_emit_ovni(struct ovni_emu *emu); void hook_emit_ovni(struct ovni_emu *emu);
void hook_post_ovni(struct ovni_emu *emu); void hook_post_ovni(struct ovni_emu *emu);
void hook_init_nosv(struct ovni_emu *emu);
void hook_pre_nosv(struct ovni_emu *emu); void hook_pre_nosv(struct ovni_emu *emu);
void hook_emit_nosv(struct ovni_emu *emu); void hook_emit_nosv(struct ovni_emu *emu);
void hook_post_nosv(struct ovni_emu *emu); void hook_post_nosv(struct ovni_emu *emu);
void hook_init_nosv_ss(struct ovni_emu *emu);
void hook_pre_nosv_ss(struct ovni_emu *emu); void hook_pre_nosv_ss(struct ovni_emu *emu);
void hook_emit_nosv_ss(struct ovni_emu *emu); void hook_emit_nosv_ss(struct ovni_emu *emu);
void hook_post_nosv_ss(struct ovni_emu *emu); void hook_post_nosv_ss(struct ovni_emu *emu);

View File

@ -7,34 +7,53 @@
#include "prv.h" #include "prv.h"
#include "chan.h" #include "chan.h"
enum nosv_prv_type {
PRV_TYPE_PROCID
};
struct hook_entry {
char id[4];
void (*hook)(struct ovni_emu *);
};
/* --------------------------- init ------------------------------- */ /* --------------------------- init ------------------------------- */
void void
hook_nosv_init(struct ovni_emu *emu) hook_init_nosv(struct ovni_emu *emu)
{ {
struct ovni_ethread *th; struct ovni_ethread *th;
struct ovni_cpu *cpu;
struct ovni_trace *trace;
int i, row, type; int i, row, type;
FILE *prv; FILE *prv_th, *prv_cpu;
int64_t *clock; int64_t *clock;
clock = &emu->delta_time;
prv_th = emu->prv_thread;
prv_cpu = emu->prv_cpu;
trace = &emu->trace;
/* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++) for(i=0; i<emu->total_nthreads; i++)
{ {
th = emu->global_thread[i]; th = emu->global_thread[i];
row = th->gindex + 1; row = th->gindex + 1;
//chan_init(struct ovni_chan *chan, int row, int type, FILE *prv, int64_t *clock) chan_th_init(th, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock);
chan_enable(&th->chan[CHAN_NOSV_TASKID], 1);
chan_set(&th->chan[CHAN_NOSV_TASKID], 0);
chan_enable(&th->chan[CHAN_NOSV_TASKID], 0);
chan_init(th->chan[CHAN_NOSV_TASK_ID], row, PTT_TASK_ID, prv, chan_th_init(th, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock);
clock); chan_th_init(th, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock);
chan_th_init(th, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, row, prv_th, clock);
}
/* Init the nosv channels in all cpus */
for(i=0; i<emu->total_ncpus; i++)
{
cpu = emu->global_cpu[i];
row = cpu->gindex + 1;
chan_cpu_init(cpu, CHAN_NOSV_TASKID, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock);
chan_enable(&cpu->chan[CHAN_NOSV_TASKID], 1);
chan_set(&cpu->chan[CHAN_NOSV_TASKID], 0);
chan_enable(&cpu->chan[CHAN_NOSV_TASKID], 0);
chan_cpu_init(cpu, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock);
chan_cpu_init(cpu, CHAN_NOSV_APPID, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock);
chan_cpu_init(cpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, row, prv_cpu, clock);
} }
} }
@ -169,10 +188,39 @@ pre_task_end(struct ovni_emu *emu)
dbg("task id=%d ends\n", task->id); dbg("task id=%d ends\n", task->id);
} }
static void
pre_task_running(struct ovni_emu *emu, struct nosv_task *task)
{
struct ovni_ethread *th;
struct ovni_eproc *proc;
th = emu->cur_thread;
proc = emu->cur_proc;
chan_set(&th->chan[CHAN_NOSV_TASKID], task->id + 1);
chan_set(&th->chan[CHAN_NOSV_TYPEID], task->type_id + 1);
chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid + 1);
}
static void
pre_task_not_running(struct ovni_emu *emu, struct nosv_task *task)
{
struct ovni_ethread *th;
th = emu->cur_thread;
chan_set(&th->chan[CHAN_NOSV_TASKID], 0);
chan_set(&th->chan[CHAN_NOSV_TYPEID], 0);
chan_set(&th->chan[CHAN_NOSV_APPID], 0);
}
static void static void
pre_task(struct ovni_emu *emu) pre_task(struct ovni_emu *emu)
{ {
emu_emit(emu); struct nosv_task *task;
task = emu->cur_task;
switch(emu->cur_ev->header.value) switch(emu->cur_ev->header.value)
{ {
case 'c': pre_task_create(emu); break; case 'c': pre_task_create(emu); break;
@ -181,8 +229,22 @@ pre_task(struct ovni_emu *emu)
case 'p': pre_task_pause(emu); break; case 'p': pre_task_pause(emu); break;
case 'r': pre_task_resume(emu); break; case 'r': pre_task_resume(emu); break;
default: default:
emu->cur_task = NULL; abort();
break; }
switch(emu->cur_ev->header.value)
{
case 'x':
case 'r':
pre_task_running(emu, task);
break;
case 'p':
case 'e':
pre_task_not_running(emu, task);
break;
case 'c':
default:
break;
} }
} }
@ -243,89 +305,100 @@ pre_type(struct ovni_emu *emu)
} }
} }
void
hook_pre_nosv(struct ovni_emu *emu)
{
switch(emu->cur_ev->header.model)
{
/* Only listen for nosv events */
case 'V':
switch(emu->cur_ev->header.class)
{
case 'T': pre_task(emu); break;
case 'Y': pre_type(emu); break;
default:
break;
}
break;
default:
break;
}
hook_pre_nosv_ss(emu);
}
/* --------------------------- emit ------------------------------- */
static void static void
emit_task_running(struct ovni_emu *emu, struct nosv_task *task) pre_sched(struct ovni_emu *emu)
{ {
prv_ev_autocpu(emu, PTC_TASK_ID, task->id + 1); struct ovni_ethread *th;
prv_ev_autocpu(emu, PTC_TASK_TYPE_ID, task->type_id + 1); struct ovni_chan *chan_th;
prv_ev_autocpu(emu, PTC_APP_ID, emu->cur_proc->appid + 1);
}
static void th = emu->cur_thread;
emit_task_not_running(struct ovni_emu *emu, struct nosv_task *task) chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
{
prv_ev_autocpu(emu, PTC_TASK_ID, 0);
prv_ev_autocpu(emu, PTC_TASK_TYPE_ID, 0);
prv_ev_autocpu(emu, PTC_APP_ID, 0);
}
static void
emit_task(struct ovni_emu *emu)
{
struct nosv_task *task;
task = emu->cur_task;
switch(emu->cur_ev->header.value) switch(emu->cur_ev->header.value)
{ {
case 'x': case 'h':
chan_push(chan_th, ST_SCHED_HUNGRY);
break;
case 'f': /* Fill: no longer hungry */
chan_pop(chan_th, ST_SCHED_HUNGRY);
break;
case '[': /* Server enter */
chan_push(chan_th, ST_SCHED_SERVING);
break;
case ']': /* Server exit */
chan_pop(chan_th, ST_SCHED_SERVING);
break;
case '@':
chan_ev(chan_th, EV_SCHED_SELF);
break;
case 'r': case 'r':
emit_task_running(emu, task); chan_ev(chan_th, EV_SCHED_RECV);
break; break;
case 'p': case 's':
case 'e': chan_ev(chan_th, EV_SCHED_SEND);
emit_task_not_running(emu, task);
break; break;
case 'c':
default: default:
break; break;
} }
} }
void static void
hook_emit_nosv(struct ovni_emu *emu) pre_submit(struct ovni_emu *emu)
{ {
struct ovni_ethread *th; struct ovni_ethread *th;
int i; struct ovni_chan *chan_th;
th = emu->cur_thread; th = emu->cur_thread;
chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value)
{
case '[':
chan_push(chan_th, ST_SCHED_SUBMITTING);
break;
case ']':
chan_pop(chan_th, ST_SCHED_SUBMITTING);
break;
default:
break;
}
}
static void
pre_memory(struct ovni_emu *emu)
{
struct ovni_ethread *th;
struct ovni_chan *chan_th;
th = emu->cur_thread;
chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value)
{
case '[':
chan_push(chan_th, ST_MEM_ALLOCATING);
break;
case ']':
chan_pop(chan_th, ST_MEM_ALLOCATING);
break;
default:
break;
}
}
void
hook_pre_nosv(struct ovni_emu *emu)
{
assert(emu->cur_ev->header.model == 'V');
switch(emu->cur_ev->header.class) switch(emu->cur_ev->header.class)
{ {
case 'T': emit_task(emu); break; case 'T': pre_task(emu); break;
case 'Y': pre_type(emu); break;
case 'S': pre_sched(emu); break;
case 'U': pre_submit(emu); break;
case 'M': pre_memory(emu); break;
default: default:
break; break;
} }
hook_emit_nosv_ss(emu);
}
void
hook_post_nosv(struct ovni_emu *emu)
{
hook_post_nosv_ss(emu);
} }

View File

@ -13,6 +13,30 @@
* 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. */
/* --------------------------- init ------------------------------- */
void
hook_init_nosv_ss(struct ovni_emu *emu)
{
struct ovni_ethread *th;
int i, row, type, track;
FILE *prv;
int64_t *clock;
clock = &emu->delta_time;
prv = emu->prv_thread;
track = CHAN_TRACK_TH_RUNNING;
/* Init the channels in all threads */
for(i=0; i<emu->total_nthreads; i++)
{
th = emu->global_thread[i];
row = th->gindex + 1;
chan_th_init(th, CHAN_NOSV_SUBSYSTEM, track, row, prv, clock);
}
}
/* --------------------------- pre ------------------------------- */ /* --------------------------- pre ------------------------------- */
static void static void
@ -22,7 +46,7 @@ pre_sched(struct ovni_emu *emu)
struct ovni_chan *chan; struct ovni_chan *chan;
th = emu->cur_thread; th = emu->cur_thread;
chan = &th->chan[CHAN_NOSV_SS]; chan = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch(emu->cur_ev->header.value)
{ {
@ -53,7 +77,7 @@ pre_submit(struct ovni_emu *emu)
struct ovni_chan *chan; struct ovni_chan *chan;
th = emu->cur_thread; th = emu->cur_thread;
chan = &th->chan[CHAN_NOSV_SS]; chan = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch(emu->cur_ev->header.value)
{ {
@ -71,7 +95,7 @@ pre_memory(struct ovni_emu *emu)
struct ovni_chan *chan; struct ovni_chan *chan;
th = emu->cur_thread; th = emu->cur_thread;
chan = &th->chan[CHAN_NOSV_SS]; chan = &th->chan[CHAN_NOSV_SUBSYSTEM];
switch(emu->cur_ev->header.value) switch(emu->cur_ev->header.value)
{ {
@ -107,7 +131,7 @@ hook_emit_nosv_ss(struct ovni_emu *emu)
th = emu->cur_thread; th = emu->cur_thread;
chan_emit(&th->chan[CHAN_NOSV_SS]); chan_emit(&th->chan[CHAN_NOSV_SUBSYSTEM]);
} }
/* --------------------------- post ------------------------------- */ /* --------------------------- post ------------------------------- */

View File

@ -8,14 +8,88 @@
/* 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 */
/* --------------------------- init ------------------------------- */
void
hook_init_ovni(struct ovni_emu *emu)
{
struct ovni_ethread *th;
struct ovni_cpu *cpu;
struct ovni_trace *trace;
int i, row, type;
FILE *prv_th, *prv_cpu;
int64_t *clock;
clock = &emu->delta_time;
prv_th = emu->prv_thread;
prv_cpu = emu->prv_cpu;
trace = &emu->trace;
/* Init the ovni channels in all threads */
for(i=0; i<emu->total_nthreads; i++)
{
th = emu->global_thread[i];
row = th->gindex + 1;
chan_th_init(th, CHAN_OVNI_TID, CHAN_TRACK_NONE, row, prv_th, clock);
chan_th_init(th, CHAN_OVNI_PID, CHAN_TRACK_NONE, row, prv_th, clock);
chan_th_init(th, CHAN_OVNI_CPU, CHAN_TRACK_NONE, row, prv_th, clock);
chan_th_init(th, CHAN_OVNI_STATE, CHAN_TRACK_NONE, row, prv_th, clock);
chan_enable(&th->chan[CHAN_OVNI_TID], 1);
chan_set(&th->chan[CHAN_OVNI_TID], th->tid);
chan_enable(&th->chan[CHAN_OVNI_TID], 0);
chan_enable(&th->chan[CHAN_OVNI_PID], 1);
chan_set(&th->chan[CHAN_OVNI_PID], th->proc->pid);
chan_enable(&th->chan[CHAN_OVNI_PID], 0);
}
/* Init the ovni channels in all cpus */
for(i=0; i<emu->total_ncpus; i++)
{
cpu = emu->global_cpu[i];
row = cpu->gindex + 1;
chan_cpu_init(cpu, CHAN_OVNI_TID, CHAN_TRACK_NONE, row, prv_cpu, clock);
chan_cpu_init(cpu, CHAN_OVNI_PID, CHAN_TRACK_NONE, row, prv_cpu, clock);
chan_cpu_init(cpu, CHAN_OVNI_NTHREADS, CHAN_TRACK_NONE, row, prv_cpu, clock);
chan_enable(&cpu->chan[CHAN_OVNI_TID], 1);
chan_set(&cpu->chan[CHAN_OVNI_TID], 0);
chan_emit(&cpu->chan[CHAN_OVNI_TID]);
chan_enable(&cpu->chan[CHAN_OVNI_PID], 1);
chan_set(&cpu->chan[CHAN_OVNI_PID], 0);
chan_emit(&cpu->chan[CHAN_OVNI_PID]);
chan_enable(&cpu->chan[CHAN_OVNI_NTHREADS], 1);
chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], cpu->nthreads);
chan_emit(&cpu->chan[CHAN_OVNI_NTHREADS]);
}
}
/* --------------------------- pre ------------------------------- */ /* --------------------------- pre ------------------------------- */
static void static void
thread_set_channel_enabled(struct ovni_ethread *th, int enabled) thread_set_channel_enabled(struct ovni_ethread *th, int enabled)
{ {
struct ovni_chan *chan;
int i; int i;
for(i=0; i<CHAN_MAX; i++) for(i=0; i<CHAN_MAX; i++)
chan_enable(&th->chan[i], enabled); {
chan = &th->chan[i];
if(chan->track == CHAN_TRACK_TH_RUNNING)
{
chan_enable(chan, enabled);
dbg("thread %d: %s chan %d\n",
th->tid,
enabled ? "enable" : "disable",
i);
}
}
} }
static void static void
@ -33,18 +107,54 @@ thread_set_state(struct ovni_ethread *th, int state)
void void
update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu) update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu)
{ {
int i, tid, pid, enabled;
struct ovni_loom *loom; struct ovni_loom *loom;
struct ovni_ethread *th;
struct ovni_chan *chan;
loom = emu->cur_loom; loom = emu->cur_loom;
if(loom->nupdated_cpus >= OVNI_MAX_CPU) chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], cpu->nthreads);
abort();
if(cpu->updated) th = NULL;
return;
cpu->updated = 1; if(cpu->nthreads == 0)
loom->updated_cpu[loom->nupdated_cpus++] = cpu; {
/* No thread running */
tid = pid = 0;
}
else if(cpu->nthreads == 1)
{
/* Take the info from the unique thread */
tid = cpu->thread[0]->tid;
pid = cpu->thread[0]->proc->pid;
th = cpu->thread[0];
}
else
{
/* Multiple threads */
tid = pid = 1;
}
chan_set(&cpu->chan[CHAN_OVNI_TID], tid);
chan_set(&cpu->chan[CHAN_OVNI_PID], pid);
// enabled = (th != NULL && th->state == TH_ST_RUNNING ? 1 : 0);
//
// /* Update all channels that need to follow the running thread */
// for(i=0; i<CHAN_MAX; i++)
// {
// chan = &cpu->chan[i];
//
// if(chan->track == CHAN_TRACK_TH_RUNNING)
// {
// chan_enable(chan, enabled);
// dbg("cpu thread %d: %s chan %d\n",
// tid,
// enabled ? "enable" : "disable",
// i);
// }
// }
} }
struct ovni_cpu * struct ovni_cpu *
@ -102,9 +212,7 @@ emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_et
abort(); abort();
for(j=i; j+1 < cpu->nthreads; j++) for(j=i; j+1 < cpu->nthreads; j++)
{
cpu->thread[i] = cpu->thread[j+1]; cpu->thread[i] = cpu->thread[j+1];
}
cpu->nthreads--; cpu->nthreads--;
@ -158,18 +266,43 @@ pre_thread_execute(struct ovni_emu *emu)
th->cpu = cpu; th->cpu = cpu;
emu_cpu_add_thread(emu, cpu, th); emu_cpu_add_thread(emu, cpu, th);
/* Enable the cpu channel of the thread */
chan_enable(&th->chan[CHAN_OVNI_CPU], 1);
chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1);
/* Enable thread TID and PID */
chan_enable(&th->chan[CHAN_OVNI_TID], 1);
chan_enable(&th->chan[CHAN_OVNI_PID], 1);
/* Enable and set the thread state */
chan_enable(&th->chan[CHAN_OVNI_STATE], 1);
chan_set(&th->chan[CHAN_OVNI_STATE], th->state);
} }
static void static void
pre_thread_end(struct ovni_emu *emu) pre_thread_end(struct ovni_emu *emu)
{ {
assert(emu->cur_thread->state == TH_ST_RUNNING); struct ovni_ethread *th;
assert(emu->cur_thread->cpu);
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); th = emu->cur_thread;
assert(th->state == TH_ST_RUNNING);
assert(th->cpu);
thread_set_state(emu->cur_thread, TH_ST_DEAD); emu_cpu_remove_thread(emu, th->cpu, th);
emu->cur_thread->cpu = NULL;
thread_set_state(th, TH_ST_DEAD);
th->cpu = NULL;
/* Disable the cpu channel of the thread */
chan_enable(&th->chan[CHAN_OVNI_CPU], 0);
/* Disable thread TID and PID */
chan_enable(&th->chan[CHAN_OVNI_TID], 0);
chan_enable(&th->chan[CHAN_OVNI_PID], 0);
/* Disable thread state */
chan_enable(&th->chan[CHAN_OVNI_STATE], 0);
} }
static void static void
@ -181,6 +314,7 @@ pre_thread_pause(struct ovni_emu *emu)
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
thread_set_state(emu->cur_thread, TH_ST_PAUSED); thread_set_state(emu->cur_thread, TH_ST_PAUSED);
chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state);
} }
static void static void
@ -192,6 +326,7 @@ pre_thread_resume(struct ovni_emu *emu)
emu_cpu_add_thread(emu, emu->cur_thread->cpu, emu->cur_thread); emu_cpu_add_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
thread_set_state(emu->cur_thread, TH_ST_RUNNING); thread_set_state(emu->cur_thread, TH_ST_RUNNING);
chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state);
} }
static void static void
@ -243,11 +378,22 @@ pre_affinity_set(struct ovni_emu *emu)
/* Migrate current cpu to the one at cpuid */ /* Migrate current cpu to the one at cpuid */
newcpu = emu_get_cpu(emu->cur_loom, cpuid); newcpu = emu_get_cpu(emu->cur_loom, cpuid);
if(emu->cur_thread->cpu == newcpu)
{
err("warning: thread %d affinity already set to cpu %d\n",
emu->cur_thread->tid,
emu->cur_thread->cpu->gindex);
return;
}
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_cpu_add_thread(emu, newcpu, emu->cur_thread); emu_cpu_add_thread(emu, newcpu, emu->cur_thread);
emu->cur_thread->cpu = newcpu; emu->cur_thread->cpu = newcpu;
chan_set(&emu->cur_thread->chan[CHAN_OVNI_CPU],
newcpu->gindex + 1);
//dbg("cpu %d now runs %d\n", cpuid, emu->cur_thread->tid); //dbg("cpu %d now runs %d\n", cpuid, emu->cur_thread->tid);
} }
@ -291,6 +437,9 @@ pre_affinity_remote(struct ovni_emu *emu)
/* Always set the assigned CPU in the thread */ /* Always set the assigned CPU in the thread */
thread->cpu = newcpu; thread->cpu = newcpu;
chan_set(&thread->chan[CHAN_OVNI_CPU],
newcpu->gindex + 1);
//dbg("thread %d switches to cpu %d by remote petition\n", tid, //dbg("thread %d switches to cpu %d by remote petition\n", tid,
// cpuid); // cpuid);
} }
@ -334,177 +483,9 @@ hook_pre_ovni(struct ovni_emu *emu)
//print_threads_state(emu); //print_threads_state(emu);
} }
/* --------------------------- emit ------------------------------- */
static void
emit_thread_state(struct ovni_emu *emu)
{
int i, row;
struct ovni_ethread *th;
th = emu->cur_thread;
row = th->gindex + 1;
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
emit_thread_count(struct ovni_emu *emu)
{
int i, n, row, pid, tid;
struct ovni_loom *loom;
loom = emu->cur_loom;
/* TODO: Use a table to quickly access the updated elements */
/* Check every CPU looking for a change in nthreads */
for(i=0; i<loom->ncpus; i++)
{
if(loom->cpu[i].last_nthreads != loom->cpu[i].nthreads)
{
/* Start at 1 */
row = loom->offset_ncpus + i + 1;
n = loom->cpu[i].nthreads;
prv_ev_cpu(emu, row, PTC_NTHREADS, n);
pid = n == 1 ? loom->cpu[i].thread[0]->proc->pid : 1;
prv_ev_cpu(emu, row, PTC_PROC_PID, pid);
tid = n == 1 ? loom->cpu[i].thread[0]->tid : 1;
prv_ev_cpu(emu, row, PTC_THREAD_TID, tid);
}
}
/* Same with the virtual CPU */
if(loom->vcpu.last_nthreads != loom->vcpu.nthreads)
{
/* Place the virtual CPU after the physical CPUs */
row = loom->ncpus + 1;
n = loom->vcpu.nthreads;
prv_ev_cpu(emu, row, PTC_NTHREADS, n);
pid = n == 1 ? loom->vcpu.thread[0]->proc->pid : 1;
prv_ev_cpu(emu, row, PTC_PROC_PID, pid);
tid = n == 1 ? loom->vcpu.thread[0]->tid : 1;
prv_ev_cpu(emu, row, PTC_THREAD_TID, tid);
}
}
static void
emit_current_pid(struct ovni_emu *emu)
{
if(emu->cur_thread->cpu == NULL)
return;
prv_ev_autocpu(emu, PTC_PROC_PID, emu->cur_proc->pid);
}
void
hook_emit_ovni(struct ovni_emu *emu)
{
int i;
if(emu->cur_ev->header.model != 'O')
return;
switch(emu->cur_ev->header.class)
{
case 'H':
emit_thread_state(emu);
/* falltrough */
case 'A':
emit_thread_count(emu);
//emit_current_pid(emu);
break;
default:
break;
}
/* Emit all enabled channels */
for(i=0; i<CHAN_MAX; i++)
chan_emit(&emu->cur_thread->chan[i]);
}
/* --------------------------- post ------------------------------- */ /* --------------------------- post ------------------------------- */
/* Reset thread state */
static void
post_virtual_thread(struct ovni_emu *emu)
{
int i;
struct ovni_loom *loom;
loom = emu->cur_loom;
/* Should be executed *before* we reset the CPUs updated flags */
assert(loom->nupdated_cpus > 0);
/* Update last_nthreads in the CPUs */
for(i=0; i<loom->ncpus; i++)
loom->cpu[i].last_nthreads = loom->cpu[i].nthreads;
/* Fix the virtual CPU as well */
loom->vcpu.last_nthreads = loom->vcpu.nthreads;
}
/* Reset CPU state */
static void
post_virtual_cpu(struct ovni_emu *emu)
{
int i;
struct ovni_loom *loom;
loom = emu->cur_loom;
for(i=0; i<loom->nupdated_cpus; i++)
{
/* Remove the update flags */
assert(loom->updated_cpu[i]->updated == 1);
loom->updated_cpu[i]->updated = 0;
}
/* Fix the virtual CPU as well */
loom->vcpu.last_nthreads = loom->vcpu.nthreads;
/* Restore 0 updated CPUs */
loom->nupdated_cpus = 0;
}
static void
post_virtual(struct ovni_emu *emu)
{
switch(emu->cur_ev->header.class)
{
case 'H':
post_virtual_thread(emu);
break;
case 'C':
post_virtual_cpu(emu);
break;
default:
break;
}
}
void void
hook_post_ovni(struct ovni_emu *emu) hook_post_ovni(struct ovni_emu *emu)
{ {
switch(emu->cur_ev->header.model)
{
case '*':
post_virtual(emu);
break;
default:
break;
}
} }