From 3f22afc4b356de91ffd25b5ad88e433ce8e49afd Mon Sep 17 00:00:00 2001 From: Rodrigo Arias Date: Thu, 21 Oct 2021 16:46:42 +0200 Subject: [PATCH] Handle all events with CPU and thread channels --- emu.c | 26 ++-- emu.h | 3 + emu_nosv.c | 229 +++++++++++++++++++++------------ emu_nosv_ss.c | 32 ++++- emu_ovni.c | 345 ++++++++++++++++++++++++-------------------------- 5 files changed, 354 insertions(+), 281 deletions(-) diff --git a/emu.c b/emu.c index d313a15..4c7aad6 100644 --- a/emu.c +++ b/emu.c @@ -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 hook_pre(struct ovni_emu *emu) { @@ -160,9 +167,6 @@ hook_pre(struct ovni_emu *emu) break; case 'V': hook_pre_nosv(emu); break; - case '*': hook_pre_nosv(emu); - hook_pre_ovni(emu); - break; default: break; } @@ -177,13 +181,6 @@ hook_emit(struct ovni_emu *emu) 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: //dbg("unknown model %c\n", emu->cur_ev->model); break; @@ -197,13 +194,6 @@ hook_post(struct ovni_emu *emu) 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: //dbg("unknown model %c\n", emu->cur_ev->model); break; @@ -315,6 +305,8 @@ emulate(struct ovni_emu *emu) emu->lastclock = 0; + hook_init(emu); + /* Then process all events */ while(next_event(emu) == 0) { diff --git a/emu.h b/emu.h index 9aaaa4b..21b0ea8 100644 --- a/emu.h +++ b/emu.h @@ -353,14 +353,17 @@ struct ovni_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_emit_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_emit_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_emit_nosv_ss(struct ovni_emu *emu); void hook_post_nosv_ss(struct ovni_emu *emu); diff --git a/emu_nosv.c b/emu_nosv.c index 260381f..c72ab4e 100644 --- a/emu_nosv.c +++ b/emu_nosv.c @@ -7,34 +7,53 @@ #include "prv.h" #include "chan.h" -enum nosv_prv_type { - PRV_TYPE_PROCID -}; - -struct hook_entry { - char id[4]; - void (*hook)(struct ovni_emu *); -}; - /* --------------------------- init ------------------------------- */ void -hook_nosv_init(struct ovni_emu *emu) +hook_init_nosv(struct ovni_emu *emu) { struct ovni_ethread *th; + struct ovni_cpu *cpu; + struct ovni_trace *trace; int i, row, type; - FILE *prv; + 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 channels in all threads */ 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_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, - clock); + chan_th_init(th, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, row, prv_th, 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; itotal_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); } +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 pre_task(struct ovni_emu *emu) { - emu_emit(emu); + struct nosv_task *task; + + task = emu->cur_task; + switch(emu->cur_ev->header.value) { 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 'r': pre_task_resume(emu); break; default: - emu->cur_task = NULL; - break; + abort(); + } + + 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 -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); - prv_ev_autocpu(emu, PTC_TASK_TYPE_ID, task->type_id + 1); - prv_ev_autocpu(emu, PTC_APP_ID, emu->cur_proc->appid + 1); -} + struct ovni_ethread *th; + struct ovni_chan *chan_th; -static void -emit_task_not_running(struct ovni_emu *emu, struct nosv_task *task) -{ - 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; + th = emu->cur_thread; + chan_th = &th->chan[CHAN_NOSV_SUBSYSTEM]; 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': - emit_task_running(emu, task); + chan_ev(chan_th, EV_SCHED_RECV); break; - case 'p': - case 'e': - emit_task_not_running(emu, task); + case 's': + chan_ev(chan_th, EV_SCHED_SEND); break; - case 'c': default: break; } } -void -hook_emit_nosv(struct ovni_emu *emu) +static void +pre_submit(struct ovni_emu *emu) { struct ovni_ethread *th; - int i; + 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_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) { - 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: break; } - - hook_emit_nosv_ss(emu); -} - -void -hook_post_nosv(struct ovni_emu *emu) -{ - hook_post_nosv_ss(emu); } diff --git a/emu_nosv_ss.c b/emu_nosv_ss.c index 5ca4481..e0714f0 100644 --- a/emu_nosv_ss.c +++ b/emu_nosv_ss.c @@ -13,6 +13,30 @@ * execution. Events such as task received by a thread are emitted as * 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; itotal_nthreads; i++) + { + th = emu->global_thread[i]; + row = th->gindex + 1; + + chan_th_init(th, CHAN_NOSV_SUBSYSTEM, track, row, prv, clock); + } +} + /* --------------------------- pre ------------------------------- */ static void @@ -22,7 +46,7 @@ pre_sched(struct ovni_emu *emu) struct ovni_chan *chan; th = emu->cur_thread; - chan = &th->chan[CHAN_NOSV_SS]; + chan = &th->chan[CHAN_NOSV_SUBSYSTEM]; switch(emu->cur_ev->header.value) { @@ -53,7 +77,7 @@ pre_submit(struct ovni_emu *emu) struct ovni_chan *chan; th = emu->cur_thread; - chan = &th->chan[CHAN_NOSV_SS]; + chan = &th->chan[CHAN_NOSV_SUBSYSTEM]; switch(emu->cur_ev->header.value) { @@ -71,7 +95,7 @@ pre_memory(struct ovni_emu *emu) struct ovni_chan *chan; th = emu->cur_thread; - chan = &th->chan[CHAN_NOSV_SS]; + chan = &th->chan[CHAN_NOSV_SUBSYSTEM]; switch(emu->cur_ev->header.value) { @@ -107,7 +131,7 @@ hook_emit_nosv_ss(struct ovni_emu *emu) th = emu->cur_thread; - chan_emit(&th->chan[CHAN_NOSV_SS]); + chan_emit(&th->chan[CHAN_NOSV_SUBSYSTEM]); } /* --------------------------- post ------------------------------- */ diff --git a/emu_ovni.c b/emu_ovni.c index d287cd6..ecd1fef 100644 --- a/emu_ovni.c +++ b/emu_ovni.c @@ -8,14 +8,88 @@ /* The emulator ovni module provides the execution model by tracking the thread * 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; itotal_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; itotal_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 ------------------------------- */ static void thread_set_channel_enabled(struct ovni_ethread *th, int enabled) { + struct ovni_chan *chan; int i; + for(i=0; ichan[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 @@ -33,18 +107,54 @@ thread_set_state(struct ovni_ethread *th, int state) void update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu) { + int i, tid, pid, enabled; struct ovni_loom *loom; + struct ovni_ethread *th; + struct ovni_chan *chan; loom = emu->cur_loom; - if(loom->nupdated_cpus >= OVNI_MAX_CPU) - abort(); + chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], cpu->nthreads); - if(cpu->updated) - return; + th = NULL; - cpu->updated = 1; - loom->updated_cpu[loom->nupdated_cpus++] = cpu; + if(cpu->nthreads == 0) + { + /* 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; ichan[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 * @@ -102,9 +212,7 @@ emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_et abort(); for(j=i; j+1 < cpu->nthreads; j++) - { cpu->thread[i] = cpu->thread[j+1]; - } cpu->nthreads--; @@ -158,18 +266,43 @@ pre_thread_execute(struct ovni_emu *emu) th->cpu = cpu; 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 pre_thread_end(struct ovni_emu *emu) { - assert(emu->cur_thread->state == TH_ST_RUNNING); - assert(emu->cur_thread->cpu); + struct ovni_ethread *th; - 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->cur_thread->cpu = NULL; + emu_cpu_remove_thread(emu, th->cpu, th); + + 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 @@ -181,6 +314,7 @@ pre_thread_pause(struct ovni_emu *emu) emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); thread_set_state(emu->cur_thread, TH_ST_PAUSED); + chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state); } 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); thread_set_state(emu->cur_thread, TH_ST_RUNNING); + chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state); } static void @@ -243,11 +378,22 @@ pre_affinity_set(struct ovni_emu *emu) /* Migrate current cpu to the one at 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_add_thread(emu, newcpu, emu->cur_thread); 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); } @@ -291,6 +437,9 @@ pre_affinity_remote(struct ovni_emu *emu) /* Always set the assigned CPU in the thread */ 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, // cpuid); } @@ -334,177 +483,9 @@ hook_pre_ovni(struct ovni_emu *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; incpus; 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; icur_thread->chan[i]); -} - /* --------------------------- 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; incpus; 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; inupdated_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 hook_post_ovni(struct ovni_emu *emu) { - switch(emu->cur_ev->header.model) - { - case '*': - post_virtual(emu); - break; - default: - break; - } }