diff --git a/emu.c b/emu.c index 43abf30..1e067f9 100644 --- a/emu.c +++ b/emu.c @@ -82,11 +82,14 @@ hook_pre(struct ovni_emu *emu) switch(emu->cur_ev->header.model) { - case 'O': hook_pre_ovni(emu); break; - case 'V': hook_pre_nosv(emu); break; - default: - //dbg("unknown model %c\n", emu->cur_ev->model); + case 'O': hook_pre_ovni(emu); break; + case 'V': hook_pre_nosv(emu); + break; + case '*': hook_pre_nosv(emu); + break; + default: + break; } } @@ -97,8 +100,12 @@ 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 'O': hook_emit_ovni(emu); + break; + case 'V': hook_emit_nosv(emu); + break; + case '*': hook_emit_nosv(emu); + break; default: //dbg("unknown model %c\n", emu->cur_ev->model); break; @@ -112,8 +119,12 @@ 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 'O': hook_post_ovni(emu); + break; + case 'V': hook_post_nosv(emu); + break; + case '*': hook_post_nosv(emu); + break; default: //dbg("unknown model %c\n", emu->cur_ev->model); break; @@ -143,6 +154,21 @@ next_event(struct ovni_emu *emu) trace = &emu->trace; + /* Look for virtual events first */ + + if(trace->ivirtual < trace->nvirtual) + { + emu->cur_ev = &trace->virtual_events[trace->ivirtual]; + trace->ivirtual++; + return 0; + } + else + { + /* Reset virtual events to 0 */ + trace->ivirtual = 0; + trace->nvirtual = 0; + } + f = -1; minclock = 0; @@ -218,8 +244,9 @@ emulate(struct ovni_emu *emu) hook_emit(emu); hook_post(emu); - /* Read the next event */ - ovni_load_next_event(emu->cur_stream); + /* Read the next event if no virtual events exist */ + if(emu->trace.ivirtual == emu->trace.nvirtual) + ovni_load_next_event(emu->cur_stream); } } @@ -587,6 +614,53 @@ write_row_cpu(struct ovni_emu *emu) fclose(f); } +static int +emu_virtual_init(struct ovni_emu *emu) +{ + struct ovni_trace *trace; + + trace = &emu->trace; + + trace->ivirtual = 0; + trace->nvirtual = 0; + + trace->virtual_events = calloc(MAX_VIRTUAL_EVENTS, + sizeof(struct ovni_ev)); + + if(trace->virtual_events == NULL) + { + perror("calloc"); + exit(EXIT_FAILURE); + } + + return 0; +} + +void +emu_virtual_ev(struct ovni_emu *emu, char *mcv) +{ + struct ovni_trace *trace; + struct ovni_ev *ev; + + trace = &emu->trace; + + if(trace->nvirtual >= MAX_VIRTUAL_EVENTS) + { + err("too many virtual events\n"); + exit(EXIT_FAILURE); + } + + ev = &trace->virtual_events[trace->nvirtual]; + + ev->header.flags = 0; + ev->header.model = mcv[0]; + ev->header.class = mcv[1]; + ev->header.value = mcv[2]; + ev->header.clock = emu->cur_ev->header.clock; + + trace->nvirtual++; +} + static void emu_init(struct ovni_emu *emu, int argc, char *argv[]) { @@ -597,6 +671,9 @@ emu_init(struct ovni_emu *emu, int argc, char *argv[]) if(ovni_load_trace(&emu->trace, emu->tracedir)) abort(); + if(emu_virtual_init(emu)) + abort(); + if(ovni_load_streams(&emu->trace)) abort(); diff --git a/emu.h b/emu.h index 496559a..1a6294c 100644 --- a/emu.h +++ b/emu.h @@ -100,6 +100,9 @@ struct ovni_ethread { /* nosv task */ struct nosv_task *task; + + /* Should we print the subsystem? */ + int show_ss; }; /* State of each emulated process */ @@ -179,9 +182,21 @@ struct ovni_loom { struct ovni_eproc proc[OVNI_MAX_PROC]; }; +#define MAX_VIRTUAL_EVENTS 16 + struct ovni_trace { int nlooms; struct ovni_loom loom[OVNI_MAX_LOOM]; + + /* Index of next virtual event */ + int ivirtual; + + /* Number of virtual events stored */ + int nvirtual; + + /* The virtual events are generated by the emulator */ + struct ovni_ev *virtual_events; + int nstreams; struct ovni_stream *stream; }; @@ -254,4 +269,7 @@ struct ovni_ethread *emu_get_thread(struct ovni_eproc *proc, int tid); void emu_emit_prv(struct ovni_emu *emu, int type, int val); +void +emu_virtual_ev(struct ovni_emu *emu, char *mcv); + #endif /* OVNI_EMU_H */ diff --git a/emu_nosv.c b/emu_nosv.c index 8e62240..a5d36bb 100644 --- a/emu_nosv.c +++ b/emu_nosv.c @@ -146,7 +146,6 @@ pre_task_end(struct ovni_emu *emu) dbg("task id=%d ends\n", task->id); } - static void pre_task(struct ovni_emu *emu) { @@ -221,16 +220,23 @@ pre_type(struct ovni_emu *emu) } } - void hook_pre_nosv(struct ovni_emu *emu) { - switch(emu->cur_ev->header.class) + switch(emu->cur_ev->header.model) { - case 'T': pre_task(emu); break; - case 'Y': pre_type(emu); break; + /* 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; + break; } hook_pre_nosv_ss(emu); diff --git a/emu_nosv_ss.c b/emu_nosv_ss.c index f83955f..1ae889e 100644 --- a/emu_nosv_ss.c +++ b/emu_nosv_ss.c @@ -19,6 +19,7 @@ static void ss_init(struct ovni_ethread *t) { t->nss = 0; + t->show_ss = 0; } static void @@ -134,16 +135,58 @@ pre_memory(struct ovni_emu *emu) } } +/* 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; + } +} + void hook_pre_nosv_ss(struct ovni_emu *emu) { - switch(emu->cur_ev->header.class) + switch(emu->cur_ev->header.model) { - case 'S': pre_sched(emu); break; - case 'U': pre_submit(emu); break; - case 'M': pre_memory(emu); break; + /* Listen for virtual events as well */ + case '*': + switch(emu->cur_ev->header.class) + { + case 'H': pre_thread(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: - break; + break; } } @@ -187,6 +230,12 @@ hook_emit_nosv_ss(struct ovni_emu *emu) 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) { diff --git a/emu_ovni.c b/emu_ovni.c index 8af7c11..32bc1c7 100644 --- a/emu_ovni.c +++ b/emu_ovni.c @@ -174,8 +174,14 @@ ev_thread(struct ovni_emu *emu) case 'p': ev_thread_pause(emu); break; case 'r': ev_thread_resume(emu); break; default: - break; + err("unknown thread event value %c\n", + ev->header.value); + exit(EXIT_FAILURE); } + + /* All events change the thread state: inject a virtual event to + * notify other modules */ + emu_virtual_ev(emu, "*Hc"); } static void