Add cooling and warming states
This commit is contained in:
parent
c822f70e6f
commit
1d4796521b
44
emu.c
44
emu.c
@ -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
20
emu.h
@ -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 */
|
||||||
|
34
emu_nosv.c
34
emu_nosv.c
@ -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;
|
||||||
}
|
}
|
||||||
|
301
emu_ovni.c
301
emu_ovni.c
@ -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
32
pcf.c
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user