Add cooling and warming states

This commit is contained in:
Rodrigo Arias 2021-10-11 11:12:26 +02:00
parent c822f70e6f
commit 1d4796521b
6 changed files with 299 additions and 137 deletions

44
emu.c
View File

@ -92,6 +92,9 @@ emit_channels(struct ovni_emu *emu)
cpu = emu->global_cpu[j]; cpu = emu->global_cpu[j];
chan_cpu = &cpu->chan[i]; chan_cpu = &cpu->chan[i];
/* Not implemented */
assert(chan_cpu->track != CHAN_TRACK_TH_UNPAUSED);
if(chan_cpu->track != CHAN_TRACK_TH_RUNNING) if(chan_cpu->track != CHAN_TRACK_TH_RUNNING)
{ {
//dbg("cpu chan %d not tracking threads\n", i); //dbg("cpu chan %d not tracking threads\n", i);
@ -120,19 +123,25 @@ emit_channels(struct ovni_emu *emu)
//dbg("cpu chan %d bad: multiple threads\n", i); //dbg("cpu chan %d bad: multiple threads\n", i);
if(!chan_is_enabled(chan_cpu)) if(!chan_is_enabled(chan_cpu))
chan_enable(chan_cpu, 1); chan_enable(chan_cpu, 1);
chan_set(chan_cpu, -1); chan_set(chan_cpu, ST_BAD);
} }
else else
{ {
th = last_th;
chan_th = &th->chan[i]; chan_th = &th->chan[i];
//dbg("cpu chan %d good: one thread\n", i); //dbg("cpu chan %d good: one thread\n", i);
if(!chan_is_enabled(chan_cpu)) if(!chan_is_enabled(chan_cpu))
chan_enable(chan_cpu, 1); chan_enable(chan_cpu, 1);
if(chan_is_enabled(chan_th)) if(chan_is_enabled(chan_th))
chan_set(chan_cpu, chan_get_st(&last_th->chan[i])); st = chan_get_st(&last_th->chan[i]);
else else
chan_set(chan_cpu, ST_BAD); st = ST_BAD;
/* Only update the CPU chan if needed */
if(chan_get_st(chan_cpu) != st)
chan_set(chan_cpu, st);
} }
} }
} }
@ -667,7 +676,6 @@ write_row_cpu(struct ovni_emu *emu)
FILE *f; FILE *f;
int i, j; int i, j;
char path[PATH_MAX]; char path[PATH_MAX];
struct ovni_loom *loom;
struct ovni_cpu *cpu; struct ovni_cpu *cpu;
sprintf(path, "%s/%s", emu->tracedir, "cpu.row"); sprintf(path, "%s/%s", emu->tracedir, "cpu.row");
@ -686,18 +694,11 @@ write_row_cpu(struct ovni_emu *emu)
fprintf(f, "LEVEL THREAD SIZE %d\n", emu->total_ncpus); fprintf(f, "LEVEL THREAD SIZE %d\n", emu->total_ncpus);
/* TODO: Use a cpu name per CPU */ for(i=0; i<emu->total_ncpus; i++)
for(i=0; i<emu->trace.nlooms; i++)
{ {
loom = &emu->trace.loom[i]; cpu = emu->global_cpu[i];
for(j=0; j<loom->ncpus; j++) fprintf(f, "%s\n", cpu->name);
{
cpu = &loom->cpu[j];
fprintf(f, "CPU %d.%d\n", i, cpu->i);
} }
}
fprintf(f, "UNSET\n");
fclose(f); fclose(f);
} }
@ -861,9 +862,20 @@ init_cpus(struct ovni_emu *emu)
{ {
cpu = &loom->cpu[j]; cpu = &loom->cpu[j];
emu->global_cpu[cpu->gindex] = cpu; emu->global_cpu[cpu->gindex] = cpu;
if(snprintf(cpu->name, MAX_CPU_NAME, "CPU %d.%d",
i, j) >= MAX_CPU_NAME)
{
abort();
}
} }
emu->global_cpu[loom->vcpu.gindex] = &loom->vcpu; emu->global_cpu[loom->vcpu.gindex] = &loom->vcpu;
if(snprintf(loom->vcpu.name, MAX_CPU_NAME, "CPU %d.*",
i) >= MAX_CPU_NAME)
{
abort();
}
} }
} }
@ -904,8 +916,8 @@ static void
emu_post(struct ovni_emu *emu) emu_post(struct ovni_emu *emu)
{ {
/* Write the PCF files */ /* Write the PCF files */
pcf_write(emu->pcf_thread); pcf_write(emu->pcf_thread, emu);
pcf_write(emu->pcf_cpu); pcf_write(emu->pcf_cpu, emu);
write_row_cpu(emu); write_row_cpu(emu);
write_row_thread(emu); write_row_thread(emu);

20
emu.h
View File

@ -22,6 +22,8 @@ enum ethread_state {
TH_ST_RUNNING, TH_ST_RUNNING,
TH_ST_PAUSED, TH_ST_PAUSED,
TH_ST_DEAD, TH_ST_DEAD,
TH_ST_COOLING,
TH_ST_WARMING,
}; };
enum nosv_task_state { enum nosv_task_state {
@ -33,11 +35,13 @@ enum nosv_task_state {
enum nosv_thread_ss_state { enum nosv_thread_ss_state {
ST_NULL = 0, ST_NULL = 0,
ST_BAD = 3,
ST_SCHED_HUNGRY = 6, ST_SCHED_HUNGRY = 6,
ST_SCHED_SERVING = 7, ST_SCHED_SERVING = 7,
ST_SCHED_SUBMITTING = 8, ST_SCHED_SUBMITTING = 8,
ST_MEM_ALLOCATING = 9, ST_MEM_ALLOCATING = 9,
ST_TASK_RUNNING = 10,
ST_NOSV_CODE = 11,
ST_BAD = 666,
}; };
enum nosv_thread_ss_event { enum nosv_thread_ss_event {
@ -69,6 +73,7 @@ struct nosv_task_type {
enum chan_track { enum chan_track {
CHAN_TRACK_NONE = 0, CHAN_TRACK_NONE = 0,
CHAN_TRACK_TH_RUNNING, CHAN_TRACK_TH_RUNNING,
CHAN_TRACK_TH_UNPAUSED,
}; };
struct ovni_chan { struct ovni_chan {
@ -125,7 +130,7 @@ enum chan {
}; };
/* Same order as `enum chan` */ /* Same order as `enum chan` */
static int chan_to_prvtype[CHAN_MAX][3] = { const static int chan_to_prvtype[CHAN_MAX][3] = {
/* Channel TH CPU */ /* Channel TH CPU */
{ CHAN_OVNI_PID, 10, 60 }, { CHAN_OVNI_PID, 10, 60 },
{ CHAN_OVNI_TID, 11, 61 }, { CHAN_OVNI_TID, 11, 61 },
@ -230,6 +235,8 @@ enum ovni_cpu_state {
CPU_ST_READY, CPU_ST_READY,
}; };
#define MAX_CPU_NAME 32
struct ovni_cpu { struct ovni_cpu {
/* Logical index: 0 to ncpus - 1 */ /* Logical index: 0 to ncpus - 1 */
int i; int i;
@ -253,6 +260,9 @@ struct ovni_cpu {
/* The threads the cpu is currently running */ /* The threads the cpu is currently running */
size_t nthreads; size_t nthreads;
struct ovni_ethread *thread[OVNI_MAX_THR]; struct ovni_ethread *thread[OVNI_MAX_THR];
/* Cpu name as shown in paraver row */
char name[MAX_CPU_NAME];
}; };
/* ----------------------- trace ------------------------ */ /* ----------------------- trace ------------------------ */
@ -315,6 +325,8 @@ struct ovni_stream {
int64_t clock_offset; int64_t clock_offset;
}; };
#define MAX_BURSTS 100
struct ovni_emu { struct ovni_emu {
struct ovni_trace trace; struct ovni_trace trace;
@ -347,6 +359,10 @@ struct ovni_emu {
int total_nthreads; int total_nthreads;
int total_proc; int total_proc;
int total_ncpus; int total_ncpus;
/* Burst times */
int nbursts;
int64_t burst_time[MAX_BURSTS];
}; };
/* Emulator function declaration */ /* Emulator function declaration */

View File

@ -37,7 +37,12 @@ hook_init_nosv(struct ovni_emu *emu)
chan_th_init(th, CHAN_NOSV_TYPEID, CHAN_TRACK_TH_RUNNING, row, prv_th, 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_APPID, CHAN_TRACK_TH_RUNNING, row, prv_th, clock);
chan_th_init(th, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, row, prv_th, clock);
/* We allow threads to emit subsystem events in cooling and
* warming states as well, as they may be allocating memory.
* However, these information won't be presented in the CPU
* channel, as it only shows the thread in the running state */
chan_th_init(th, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_UNPAUSED, row, prv_th, clock);
} }
/* Init the nosv channels in all cpus */ /* Init the nosv channels in all cpus */
@ -200,6 +205,8 @@ pre_task_running(struct ovni_emu *emu, struct nosv_task *task)
chan_set(&th->chan[CHAN_NOSV_TASKID], task->id + 1); 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_TYPEID], task->type_id + 1);
chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid + 1); chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid + 1);
chan_push(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_TASK_RUNNING);
} }
static void static void
@ -212,6 +219,8 @@ pre_task_not_running(struct ovni_emu *emu, struct nosv_task *task)
chan_set(&th->chan[CHAN_NOSV_TASKID], 0); chan_set(&th->chan[CHAN_NOSV_TASKID], 0);
chan_set(&th->chan[CHAN_NOSV_TYPEID], 0); chan_set(&th->chan[CHAN_NOSV_TYPEID], 0);
chan_set(&th->chan[CHAN_NOSV_APPID], 0); chan_set(&th->chan[CHAN_NOSV_APPID], 0);
chan_pop(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_TASK_RUNNING);
} }
static void static void
@ -386,6 +395,28 @@ pre_memory(struct ovni_emu *emu)
} }
} }
static void
pre_code(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_NOSV_CODE);
break;
case ']':
chan_pop(chan_th, ST_NOSV_CODE);
break;
default:
break;
}
}
void void
hook_pre_nosv(struct ovni_emu *emu) hook_pre_nosv(struct ovni_emu *emu)
{ {
@ -398,6 +429,7 @@ hook_pre_nosv(struct ovni_emu *emu)
case 'S': pre_sched(emu); break; case 'S': pre_sched(emu); break;
case 'U': pre_submit(emu); break; case 'U': pre_submit(emu); break;
case 'M': pre_memory(emu); break; case 'M': pre_memory(emu); break;
case 'C': pre_code(emu); break;
default: default:
break; break;
} }

View File

@ -43,6 +43,10 @@ hook_init_ovni(struct ovni_emu *emu)
chan_enable(&th->chan[CHAN_OVNI_PID], 1); chan_enable(&th->chan[CHAN_OVNI_PID], 1);
chan_set(&th->chan[CHAN_OVNI_PID], th->proc->pid); chan_set(&th->chan[CHAN_OVNI_PID], th->proc->pid);
chan_enable(&th->chan[CHAN_OVNI_PID], 0); chan_enable(&th->chan[CHAN_OVNI_PID], 0);
/* All threads begin in unknown state */
chan_enable(&th->chan[CHAN_OVNI_STATE], 1);
chan_set(&th->chan[CHAN_OVNI_STATE], TH_ST_UNKNOWN);
} }
/* Init the ovni channels in all cpus */ /* Init the ovni channels in all cpus */
@ -72,23 +76,40 @@ hook_init_ovni(struct ovni_emu *emu)
/* --------------------------- pre ------------------------------- */ /* --------------------------- pre ------------------------------- */
static void static void
thread_set_channel_enabled(struct ovni_ethread *th, int enabled) thread_update_channels(struct ovni_ethread *th)
{ {
struct ovni_chan *chan; struct ovni_chan *chan;
int i; int i, st, enabled, is_running, is_unpaused;
st = th->state;
is_running = (st == TH_ST_RUNNING);
is_unpaused = (st == TH_ST_RUNNING
|| st == TH_ST_COOLING
|| st == TH_ST_WARMING);
for(i=0; i<CHAN_MAX; i++) for(i=0; i<CHAN_MAX; i++)
{ {
chan = &th->chan[i]; chan = &th->chan[i];
if(chan->track == CHAN_TRACK_TH_RUNNING) switch (chan->track)
{ {
chan_enable(chan, enabled); case CHAN_TRACK_TH_RUNNING:
dbg("thread %d: %s chan %d\n", enabled = is_running ? 1 : 0;
th->tid, break;
enabled ? "enable" : "disable", case CHAN_TRACK_TH_UNPAUSED:
i); enabled = is_unpaused ? 1 : 0;
break;
default:
continue;
} }
/* The channel is already in the proper state */
if(chan_is_enabled(chan) == enabled)
continue;
dbg("thread %d changes state to %d: chan %d enabled=%d\n",
th->tid, th->state, i, enabled);
chan_enable(chan, enabled);
} }
} }
@ -99,36 +120,48 @@ thread_set_state(struct ovni_ethread *th, int state)
th->state = state; th->state = state;
enabled = (state == TH_ST_RUNNING ? 1 : 0); chan_set(&th->chan[CHAN_OVNI_STATE], th->state);
thread_set_channel_enabled(th, enabled); /* Enable or disable the thread channels that track the thread state */
thread_update_channels(th);
} }
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; int i, tid, pid, enabled, nrunning;
struct ovni_loom *loom; struct ovni_loom *loom;
struct ovni_ethread *th; struct ovni_ethread *th, *last_th;
struct ovni_chan *chan; struct ovni_chan *chan;
loom = emu->cur_loom; loom = emu->cur_loom;
chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], cpu->nthreads); /* Count running threads */
for(i=0, nrunning=0; i<cpu->nthreads; i++)
{
th = cpu->thread[i];
if(th->state == TH_ST_RUNNING)
{
last_th = th;
nrunning++;
}
}
chan_set(&cpu->chan[CHAN_OVNI_NTHREADS], nrunning);
th = NULL; th = NULL;
if(cpu->nthreads == 0) if(nrunning == 0)
{ {
/* No thread running */ /* No thread running */
tid = pid = 0; tid = pid = 0;
} }
else if(cpu->nthreads == 1) else if(nrunning == 1)
{ {
/* Take the info from the unique thread */ /* Take the info from the running thread */
tid = cpu->thread[0]->tid; tid = last_th->tid;
pid = cpu->thread[0]->proc->pid; pid = last_th->proc->pid;
th = cpu->thread[0]; th = last_th;
} }
else else
{ {
@ -186,8 +219,8 @@ emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
return i; return i;
} }
void static void
emu_cpu_add_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread) cpu_add_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
{ {
/* Found, abort */ /* Found, abort */
if(emu_cpu_find_thread(cpu, thread) >= 0) if(emu_cpu_find_thread(cpu, thread) >= 0)
@ -200,8 +233,8 @@ emu_cpu_add_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethre
update_cpu(emu, cpu); update_cpu(emu, cpu);
} }
void static void
emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread) cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
{ {
int i, j; int i, j;
@ -219,6 +252,52 @@ emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_et
update_cpu(emu, cpu); update_cpu(emu, cpu);
} }
void
cpu_migrate_thread(struct ovni_emu *emu,
struct ovni_cpu *cpu,
struct ovni_ethread *thread,
struct ovni_cpu *newcpu)
{
cpu_remove_thread(emu, cpu, thread);
cpu_add_thread(emu, newcpu, thread);
}
/* Sets the thread assigned CPU to the given one.
* Precondition: the thread CPU must be null */
void
thread_set_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu)
{
assert(th->cpu == NULL);
th->cpu = cpu;
chan_enable(&th->chan[CHAN_OVNI_CPU], 1);
chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1);
}
/* Unsets the thread assigned CPU.
* Precondition: the thread CPU must be not null */
void
thread_unset_cpu(struct ovni_ethread *th)
{
assert(th->cpu != NULL);
th->cpu = NULL;
chan_enable(&th->chan[CHAN_OVNI_CPU], 0);
}
/* Migrates the thread assigned CPU to the given one.
* Precondition: the thread CPU must be not null */
void
thread_migrate_cpu(struct ovni_ethread *th, struct ovni_cpu *cpu)
{
assert(th->cpu != NULL);
th->cpu = cpu;
assert(chan_is_enabled(&th->chan[CHAN_OVNI_CPU]));
chan_set(&th->chan[CHAN_OVNI_CPU], cpu->gindex + 1);
}
static void static void
print_threads_state(struct ovni_loom *loom) print_threads_state(struct ovni_loom *loom)
{ {
@ -246,14 +325,11 @@ print_threads_state(struct ovni_loom *loom)
} }
static void static void
pre_thread_execute(struct ovni_emu *emu) pre_thread_execute(struct ovni_emu *emu, struct ovni_ethread *th)
{ {
struct ovni_cpu *cpu; struct ovni_cpu *cpu;
struct ovni_ethread *th;
int cpuid; int cpuid;
th = emu->cur_thread;
/* The thread cannot be already running */ /* The thread cannot be already running */
assert(th->state != TH_ST_RUNNING); assert(th->state != TH_ST_RUNNING);
@ -263,70 +339,65 @@ pre_thread_execute(struct ovni_emu *emu)
cpu = emu_get_cpu(emu->cur_loom, cpuid); cpu = emu_get_cpu(emu->cur_loom, cpuid);
thread_set_state(th, TH_ST_RUNNING); thread_set_state(th, TH_ST_RUNNING);
th->cpu = cpu; thread_set_cpu(th, cpu);
emu_cpu_add_thread(emu, cpu, th); 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 */ /* Enable thread TID and PID */
chan_enable(&th->chan[CHAN_OVNI_TID], 1); chan_enable(&th->chan[CHAN_OVNI_TID], 1);
chan_enable(&th->chan[CHAN_OVNI_PID], 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, struct ovni_ethread *th)
{ {
struct ovni_ethread *th;
th = emu->cur_thread;
assert(th->state == TH_ST_RUNNING); assert(th->state == TH_ST_RUNNING);
assert(th->cpu); assert(th->cpu);
emu_cpu_remove_thread(emu, th->cpu, th); cpu_remove_thread(emu, th->cpu, th);
thread_set_state(th, TH_ST_DEAD); thread_set_state(th, TH_ST_DEAD);
th->cpu = NULL; thread_unset_cpu(th);
/* Disable the cpu channel of the thread */
chan_enable(&th->chan[CHAN_OVNI_CPU], 0);
/* Disable thread TID and PID */ /* Disable thread TID and PID */
chan_enable(&th->chan[CHAN_OVNI_TID], 0); chan_enable(&th->chan[CHAN_OVNI_TID], 0);
chan_enable(&th->chan[CHAN_OVNI_PID], 0); chan_enable(&th->chan[CHAN_OVNI_PID], 0);
/* Disable thread state */
chan_enable(&th->chan[CHAN_OVNI_STATE], 0);
} }
static void static void
pre_thread_pause(struct ovni_emu *emu) pre_thread_pause(struct ovni_emu *emu, struct ovni_ethread *th)
{ {
assert(emu->cur_thread->state == TH_ST_RUNNING); assert(th->state == TH_ST_RUNNING || th->state == TH_ST_COOLING);
assert(emu->cur_thread->cpu); assert(th->cpu);
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); thread_set_state(th, 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
pre_thread_resume(struct ovni_emu *emu) pre_thread_resume(struct ovni_emu *emu, struct ovni_ethread *th)
{ {
assert(emu->cur_thread->state == TH_ST_PAUSED); assert(th->state == TH_ST_PAUSED || th->state == TH_ST_WARMING);
assert(emu->cur_thread->cpu); assert(th->cpu);
emu_cpu_add_thread(emu, emu->cur_thread->cpu, emu->cur_thread); thread_set_state(th, TH_ST_RUNNING);
}
thread_set_state(emu->cur_thread, TH_ST_RUNNING); static void
chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state); pre_thread_cool(struct ovni_emu *emu, struct ovni_ethread *th)
{
assert(th->state == TH_ST_RUNNING);
assert(th->cpu);
thread_set_state(th, TH_ST_COOLING);
}
static void
pre_thread_warm(struct ovni_emu *emu, struct ovni_ethread *th)
{
assert(th->state == TH_ST_PAUSED);
assert(th->cpu);
thread_set_state(th, TH_ST_WARMING);
} }
static void static void
@ -334,29 +405,31 @@ pre_thread(struct ovni_emu *emu)
{ {
struct ovni_ev *ev; struct ovni_ev *ev;
struct ovni_cpu *cpu; struct ovni_cpu *cpu;
struct ovni_ethread *thread, *remote_thread; struct ovni_ethread *th, *remote_thread;
int i; int i;
//emu_emit(emu); //emu_emit(emu);
thread = emu->cur_thread; th = emu->cur_thread;
cpu = thread->cpu; cpu = th->cpu;
ev = emu->cur_ev; ev = emu->cur_ev;
switch(ev->header.value) switch(ev->header.value)
{ {
case 'c': /* create */ case 'C': /* create */
dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n", dbg("thread %d creates a new thread at cpu=%d with args=%x %x\n",
thread->tid, th->tid,
ev->payload.u32[0], ev->payload.u32[0],
ev->payload.u32[1], ev->payload.u32[1],
ev->payload.u32[2]); ev->payload.u32[2]);
break; break;
case 'x': pre_thread_execute(emu); break; case 'x': pre_thread_execute(emu, th); break;
case 'e': pre_thread_end(emu); break; case 'e': pre_thread_end(emu, th); break;
case 'p': pre_thread_pause(emu); break; case 'p': pre_thread_pause(emu, th); break;
case 'r': pre_thread_resume(emu); break; case 'r': pre_thread_resume(emu, th); break;
case 'c': pre_thread_cool(emu, th); break;
case 'w': pre_thread_warm(emu, th); break;
default: default:
err("unknown thread event value %c\n", err("unknown thread event value %c\n",
ev->header.value); ev->header.value);
@ -369,32 +442,31 @@ pre_affinity_set(struct ovni_emu *emu)
{ {
int cpuid; int cpuid;
struct ovni_cpu *newcpu; struct ovni_cpu *newcpu;
struct ovni_ethread *th;
th = emu->cur_thread;
cpuid = emu->cur_ev->payload.i32[0]; cpuid = emu->cur_ev->payload.i32[0];
assert(emu->cur_thread->state == TH_ST_RUNNING); assert(th->cpu);
assert(emu->cur_thread->cpu); assert(th->state == TH_ST_RUNNING
|| th->state == TH_ST_COOLING
|| th->state == TH_ST_WARMING);
/* 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) if(th->cpu == newcpu)
{ {
err("warning: thread %d affinity already set to cpu %d\n", err("warning: thread %d affinity already set to cpu %d\n",
emu->cur_thread->tid, th->tid,
emu->cur_thread->cpu->gindex); th->cpu->gindex);
return; return;
} }
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread); cpu_migrate_thread(emu, th->cpu, th, newcpu);
emu_cpu_add_thread(emu, newcpu, emu->cur_thread); thread_migrate_cpu(th, newcpu);
emu->cur_thread->cpu = newcpu; //dbg("cpu %d now runs %d\n", cpuid, th->tid);
chan_set(&emu->cur_thread->chan[CHAN_OVNI_CPU],
newcpu->gindex + 1);
//dbg("cpu %d now runs %d\n", cpuid, emu->cur_thread->tid);
} }
static void static void
@ -402,45 +474,29 @@ pre_affinity_remote(struct ovni_emu *emu)
{ {
int cpuid, tid; int cpuid, tid;
struct ovni_cpu *newcpu; struct ovni_cpu *newcpu;
struct ovni_ethread *thread; struct ovni_ethread *remote_th;
cpuid = emu->cur_ev->payload.i32[0]; cpuid = emu->cur_ev->payload.i32[0];
tid = emu->cur_ev->payload.i32[1]; tid = emu->cur_ev->payload.i32[1];
thread = emu_get_thread(emu->cur_proc, tid); remote_th = emu_get_thread(emu->cur_proc, tid);
assert(thread); assert(remote_th);
/* The thread may still be running */ /* The remote_th cannot be in states dead or unknown */
assert(thread->state == TH_ST_RUNNING || assert(remote_th->state != TH_ST_DEAD
thread->state == TH_ST_PAUSED); && remote_th->state != TH_ST_UNKNOWN);
/* It must have an assigned CPU */ /* It must have an assigned CPU */
assert(thread->cpu); assert(remote_th->cpu);
/* 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 running, update the CPU thread lists */ cpu_migrate_thread(emu, remote_th->cpu, remote_th, newcpu);
if(thread->state == TH_ST_RUNNING) thread_migrate_cpu(remote_th, newcpu);
{
emu_cpu_remove_thread(emu, thread->cpu, thread);
emu_cpu_add_thread(emu, newcpu, thread);
}
else
{
/* Otherwise, ensure that it is not in any CPU list */
assert(emu_cpu_find_thread(thread->cpu, thread) == -1);
assert(emu_cpu_find_thread(newcpu, thread) == -1);
}
/* Always set the assigned CPU in the thread */ //dbg("remote_th %d switches to cpu %d by remote petition\n", tid,
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); // cpuid);
} }
@ -459,6 +515,27 @@ pre_affinity(struct ovni_emu *emu)
} }
} }
void
pre_burst(struct ovni_emu *emu)
{
int64_t dt;
if(emu->nbursts >= MAX_BURSTS)
{
err("too many bursts\n");
abort();
}
emu->burst_time[emu->nbursts] = emu->delta_time;
if(emu->nbursts > 0)
{
dt = emu->burst_time[emu->nbursts] -
emu->burst_time[emu->nbursts - 1];
err("burst delta time %ld ns\n", dt);
}
emu->nbursts++;
}
void void
hook_pre_ovni(struct ovni_emu *emu) hook_pre_ovni(struct ovni_emu *emu)
{ {
@ -471,9 +548,7 @@ hook_pre_ovni(struct ovni_emu *emu)
{ {
case 'H': pre_thread(emu); break; case 'H': pre_thread(emu); break;
case 'A': pre_affinity(emu); break; case 'A': pre_affinity(emu); break;
case 'B': case 'B': pre_burst(emu); break;
//dbg("burst %c\n", emu->cur_ev->header.value);
break;
default: default:
dbg("unknown ovni event class %c\n", dbg("unknown ovni event class %c\n",
emu->cur_ev->header.class); emu->cur_ev->header.class);

32
pcf.c
View File

@ -95,6 +95,8 @@ struct event_value thread_state_values[] = {
{ TH_ST_RUNNING, "Running" }, { TH_ST_RUNNING, "Running" },
{ TH_ST_PAUSED, "Paused" }, { TH_ST_PAUSED, "Paused" },
{ TH_ST_DEAD, "Dead" }, { TH_ST_DEAD, "Dead" },
{ TH_ST_COOLING, "Cooling" },
{ TH_ST_WARMING, "Warming" },
{ -1, NULL }, { -1, NULL },
}; };
@ -121,6 +123,8 @@ struct event_value ss_values[] = {
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" }, { ST_SCHED_HUNGRY, "Scheduler: Hungry" },
{ ST_SCHED_SERVING, "Scheduler: Serving" }, { ST_SCHED_SERVING, "Scheduler: Serving" },
{ ST_SCHED_SUBMITTING, "Scheduler: Submitting" }, { ST_SCHED_SUBMITTING, "Scheduler: Submitting" },
{ ST_TASK_RUNNING, "Task: Running" },
{ ST_NOSV_CODE, "nOS-V code" },
{ EV_SCHED_SEND, "EV Scheduler: Send task" }, { EV_SCHED_SEND, "EV Scheduler: Send task" },
{ EV_SCHED_RECV, "EV Scheduler: Recv task" }, { EV_SCHED_RECV, "EV Scheduler: Recv task" },
{ EV_SCHED_SELF, "EV Scheduler: Self-assign task" }, { EV_SCHED_SELF, "EV Scheduler: Self-assign task" },
@ -138,6 +142,11 @@ struct event_type cpu_ss = {
ss_values ss_values
}; };
struct event_type thread_cpu_affinity = {
0, chan_to_prvtype[CHAN_OVNI_CPU][1], "Thread: current CPU affinity",
/* Ignored */ NULL
};
static void static void
decompose_rgb(uint32_t col, uint8_t *r, uint8_t *g, uint8_t *b) decompose_rgb(uint32_t col, uint8_t *r, uint8_t *g, uint8_t *b)
{ {
@ -196,20 +205,37 @@ write_event_type(FILE *f, struct event_type *ev)
} }
static void static void
write_events(FILE *f) write_cpu_type(FILE *f, struct event_type *ev, struct ovni_emu *emu)
{
int i;
write_event_type_header(f, ev->index, ev->type, ev->label);
fprintf(f, "VALUES\n");
for(i=0; i<emu->total_ncpus; i++)
{
fprintf(f, "%-4d %s\n", i+1, emu->global_cpu[i]->name);
}
}
static void
write_events(FILE *f, struct ovni_emu *emu)
{ {
write_event_type(f, &thread_state); write_event_type(f, &thread_state);
write_event_type(f, &thread_tid); write_event_type(f, &thread_tid);
write_event_type(f, &thread_ss); write_event_type(f, &thread_ss);
write_event_type(f, &cpu_ss); write_event_type(f, &cpu_ss);
write_cpu_type(f, &thread_cpu_affinity, emu);
} }
int int
pcf_write(FILE *f) pcf_write(FILE *f, struct ovni_emu *emu)
{ {
write_header(f); write_header(f);
write_colors(f, pcf_palette, pcf_palette_len); write_colors(f, pcf_palette, pcf_palette_len);
write_events(f); write_events(f, emu);
return 0; return 0;
} }

3
pcf.h
View File

@ -2,8 +2,9 @@
#define OVNI_PCF_H #define OVNI_PCF_H
#include <stdio.h> #include <stdio.h>
#include "emu.h"
int int
pcf_write(FILE *f); pcf_write(FILE *f, struct ovni_emu *emu);
#endif /* OVNI_PCF_H */ #endif /* OVNI_PCF_H */