Add preliminar nosv CPU subsystem support

This commit is contained in:
Rodrigo Arias 2021-10-21 16:05:01 +02:00
parent e8f4060370
commit 28fa152169
6 changed files with 276 additions and 22 deletions

6
emu.c
View File

@ -39,7 +39,7 @@ emit_ev(struct ovni_stream *stream, struct ovni_ev *ev)
delta = clock - stream->lastclock;
dbg("%d.%d.%d %c %c %c % 20lu % 15ld ",
dbg("%d.%d.%d %c %c %c % 20ld % 15ld ",
stream->loom, stream->proc, stream->tid,
ev->header.model, ev->header.class, ev->header.value, clock, delta);
@ -87,6 +87,7 @@ hook_pre(struct ovni_emu *emu)
case 'V': hook_pre_nosv(emu);
break;
case '*': hook_pre_nosv(emu);
hook_pre_ovni(emu);
break;
default:
break;
@ -105,6 +106,7 @@ hook_emit(struct ovni_emu *emu)
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);
@ -124,6 +126,7 @@ hook_post(struct ovni_emu *emu)
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);
@ -240,6 +243,7 @@ emulate(struct ovni_emu *emu)
while(next_event(emu) == 0)
{
//fprintf(stdout, "step %i\n", i);
emu_emit(emu);
hook_pre(emu);
hook_emit(emu);
hook_post(emu);

14
emu.h
View File

@ -14,7 +14,7 @@
# define dbg(...)
#endif
#define err(...) fprintf(stderr, "error: " __VA_ARGS__);
#define err(...) fprintf(stderr, __VA_ARGS__);
/* Emulated thread runtime status */
enum ethread_state {
@ -33,6 +33,7 @@ enum nosv_task_state {
enum nosv_thread_ss_state {
ST_NULL = 0,
ST_BAD = 3,
ST_SCHED_HUNGRY = 6,
ST_SCHED_SERVING = 7,
ST_SCHED_SUBMITTING = 8,
@ -156,9 +157,16 @@ struct ovni_cpu {
size_t last_nthreads;
/* 1 if the cpu has updated is threads, 0 if not */
int updated;
/* 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 ------------------------ */
@ -180,6 +188,10 @@ struct ovni_loom {
struct ovni_cpu vcpu;
struct ovni_eproc proc[OVNI_MAX_PROC];
/* Keep a list of updated cpus */
int nupdated_cpus;
struct ovni_cpu *updated_cpu[OVNI_MAX_CPU];
};
#define MAX_VIRTUAL_EVENTS 16

View File

@ -161,6 +161,32 @@ pre_thread(struct ovni_emu *emu)
}
}
/* 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)
{
@ -171,6 +197,7 @@ hook_pre_nosv_ss(struct ovni_emu *emu)
switch(emu->cur_ev->header.class)
{
case 'H': pre_thread(emu); break;
case 'C': pre_cpu(emu); break;
default:
break;
}
@ -203,6 +230,17 @@ emit_thread_state(struct ovni_emu *emu, struct ovni_ethread *th,
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)
@ -223,9 +261,108 @@ emit_thread_event(struct ovni_emu *emu, struct ovni_ethread *th,
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
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;
th = emu->cur_thread;
@ -241,11 +378,14 @@ hook_emit_nosv_ss(struct ovni_emu *emu)
{
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 ------------------------------- */

View File

@ -4,6 +4,26 @@
#include <assert.h>
/* The emulator ovni module provides the execution model by tracking the thread
* state and which threads run in each CPU */
void
update_cpu(struct ovni_emu *emu, struct ovni_cpu *cpu)
{
struct ovni_loom *loom;
loom = emu->cur_loom;
if(loom->nupdated_cpus >= OVNI_MAX_CPU)
abort();
if(cpu->updated)
return;
cpu->updated = 1;
loom->updated_cpu[loom->nupdated_cpus++] = cpu;
}
struct ovni_cpu *
emu_get_cpu(struct ovni_loom *loom, int cpuid)
{
@ -34,7 +54,7 @@ emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
}
void
emu_cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
emu_cpu_add_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
{
/* Found, abort */
if(emu_cpu_find_thread(cpu, thread) >= 0)
@ -43,10 +63,12 @@ emu_cpu_add_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
assert(cpu->nthreads < OVNI_MAX_THR);
cpu->thread[cpu->nthreads++] = thread;
update_cpu(emu, cpu);
}
void
emu_cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
{
int i, j;
@ -62,6 +84,8 @@ emu_cpu_remove_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
}
cpu->nthreads--;
update_cpu(emu, cpu);
}
@ -75,7 +99,7 @@ print_threads_state(struct ovni_loom *loom)
{
cpu = &loom->cpu[i];
dbg("-- cpu %d runs %d threads:", i, cpu->nthreads);
dbg("-- cpu %d runs %lu threads:", i, cpu->nthreads);
for(j=0; j<cpu->nthreads; j++)
{
dbg(" %d", cpu->thread[j]->tid);
@ -83,7 +107,7 @@ print_threads_state(struct ovni_loom *loom)
dbg("\n");
}
dbg("-- vcpu runs %d threads:", loom->vcpu.nthreads);
dbg("-- vcpu runs %lu threads:", loom->vcpu.nthreads);
for(j=0; j<loom->vcpu.nthreads; j++)
{
dbg(" %d", loom->vcpu.thread[j]->tid);
@ -108,7 +132,7 @@ ev_thread_execute(struct ovni_emu *emu)
emu->cur_thread->state = TH_ST_RUNNING;
emu->cur_thread->cpu = cpu;
emu_cpu_add_thread(cpu, emu->cur_thread);
emu_cpu_add_thread(emu, cpu, emu->cur_thread);
}
static void
@ -117,7 +141,7 @@ ev_thread_end(struct ovni_emu *emu)
assert(emu->cur_thread->state == TH_ST_RUNNING);
assert(emu->cur_thread->cpu);
emu_cpu_remove_thread(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;
emu->cur_thread->cpu = NULL;
@ -129,7 +153,7 @@ ev_thread_pause(struct ovni_emu *emu)
assert(emu->cur_thread->state == TH_ST_RUNNING);
assert(emu->cur_thread->cpu);
emu_cpu_remove_thread(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;
}
@ -140,7 +164,7 @@ ev_thread_resume(struct ovni_emu *emu)
assert(emu->cur_thread->state == TH_ST_PAUSED);
assert(emu->cur_thread->cpu);
emu_cpu_add_thread(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;
}
@ -179,9 +203,13 @@ ev_thread(struct ovni_emu *emu)
exit(EXIT_FAILURE);
}
/* All events change the thread state: inject a virtual event to
* notify other modules */
emu_virtual_ev(emu, "*Hc");
/* 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
@ -198,8 +226,8 @@ ev_affinity_set(struct ovni_emu *emu)
/* Migrate current cpu to the one at cpuid */
newcpu = emu_get_cpu(emu->cur_loom, cpuid);
emu_cpu_remove_thread(emu->cur_thread->cpu, emu->cur_thread);
emu_cpu_add_thread(newcpu, 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->cur_thread->cpu = newcpu;
@ -233,8 +261,8 @@ ev_affinity_remote(struct ovni_emu *emu)
/* If running, update the CPU thread lists */
if(thread->state == TH_ST_RUNNING)
{
emu_cpu_remove_thread(thread->cpu, thread);
emu_cpu_add_thread(newcpu, thread);
emu_cpu_remove_thread(emu, thread->cpu, thread);
emu_cpu_add_thread(emu, newcpu, thread);
}
else
{
@ -270,6 +298,9 @@ hook_pre_ovni(struct ovni_emu *emu)
{
//emu_emit(emu);
if(emu->cur_ev->header.model != 'O')
return;
switch(emu->cur_ev->header.class)
{
case 'H': ev_thread(emu); break;
@ -359,6 +390,9 @@ emit_current_pid(struct ovni_emu *emu)
void
hook_emit_ovni(struct ovni_emu *emu)
{
if(emu->cur_ev->header.model != 'O')
return;
switch(emu->cur_ev->header.class)
{
case 'H':
@ -373,18 +407,74 @@ hook_emit_ovni(struct ovni_emu *emu)
}
}
void
hook_post_ovni(struct ovni_emu *emu)
/* Reset thread state */
static void
post_virtual_thread(struct ovni_emu *emu)
{
int i;
struct ovni_loom *loom;
loom = emu->cur_loom;
/* Update last_nthreads in the CPUs */
/* 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
hook_post_ovni(struct ovni_emu *emu)
{
switch(emu->cur_ev->header.model)
{
case '*':
post_virtual(emu);
break;
default:
break;
}
}

11
pcf.c
View File

@ -114,8 +114,9 @@ struct event_type thread_tid = {
thread_tid_values
};
struct event_value thread_ss_values[] = {
struct event_value ss_values[] = {
{ ST_NULL, "NULL" },
{ ST_BAD, "Unknown subsystem: multiple threads" },
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" },
{ ST_SCHED_SERVING, "Scheduler: Serving" },
{ ST_SCHED_SUBMITTING, "Scheduler: Submitting" },
@ -128,7 +129,12 @@ struct event_value thread_ss_values[] = {
struct event_type thread_ss = {
0, PTT_SUBSYSTEM, "Thread: Subsystem",
thread_ss_values
ss_values
};
struct event_type cpu_ss = {
0, PTC_SUBSYSTEM, "CPU: Current thread subsystem",
ss_values
};
static void
@ -194,6 +200,7 @@ write_events(FILE *f)
write_event_type(f, &thread_state);
write_event_type(f, &thread_tid);
write_event_type(f, &thread_ss);
write_event_type(f, &cpu_ss);
}
int

1
prv.h
View File

@ -14,6 +14,7 @@ enum prv_type {
PTC_TASK_ID = 20,
PTC_TASK_TYPE_ID = 21,
PTC_APP_ID = 30,
PTC_SUBSYSTEM = 31,
/* Rows are threads */
PTT_THREAD_STATE = 60,