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];
chan_cpu = &cpu->chan[i];
/* Not implemented */
assert(chan_cpu->track != CHAN_TRACK_TH_UNPAUSED);
if(chan_cpu->track != CHAN_TRACK_TH_RUNNING)
{
//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);
if(!chan_is_enabled(chan_cpu))
chan_enable(chan_cpu, 1);
chan_set(chan_cpu, -1);
chan_set(chan_cpu, ST_BAD);
}
else
{
th = last_th;
chan_th = &th->chan[i];
//dbg("cpu chan %d good: one thread\n", i);
if(!chan_is_enabled(chan_cpu))
chan_enable(chan_cpu, 1);
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
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;
int i, j;
char path[PATH_MAX];
struct ovni_loom *loom;
struct ovni_cpu *cpu;
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);
/* TODO: Use a cpu name per CPU */
for(i=0; i<emu->trace.nlooms; i++)
for(i=0; i<emu->total_ncpus; i++)
{
loom = &emu->trace.loom[i];
for(j=0; j<loom->ncpus; j++)
{
cpu = &loom->cpu[j];
fprintf(f, "CPU %d.%d\n", i, cpu->i);
cpu = emu->global_cpu[i];
fprintf(f, "%s\n", cpu->name);
}
}
fprintf(f, "UNSET\n");
fclose(f);
}
@ -861,9 +862,20 @@ init_cpus(struct ovni_emu *emu)
{
cpu = &loom->cpu[j];
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;
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)
{
/* Write the PCF files */
pcf_write(emu->pcf_thread);
pcf_write(emu->pcf_cpu);
pcf_write(emu->pcf_thread, emu);
pcf_write(emu->pcf_cpu, emu);
write_row_cpu(emu);
write_row_thread(emu);

20
emu.h
View File

@ -22,6 +22,8 @@ enum ethread_state {
TH_ST_RUNNING,
TH_ST_PAUSED,
TH_ST_DEAD,
TH_ST_COOLING,
TH_ST_WARMING,
};
enum nosv_task_state {
@ -33,11 +35,13 @@ 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,
ST_MEM_ALLOCATING = 9,
ST_TASK_RUNNING = 10,
ST_NOSV_CODE = 11,
ST_BAD = 666,
};
enum nosv_thread_ss_event {
@ -69,6 +73,7 @@ struct nosv_task_type {
enum chan_track {
CHAN_TRACK_NONE = 0,
CHAN_TRACK_TH_RUNNING,
CHAN_TRACK_TH_UNPAUSED,
};
struct ovni_chan {
@ -125,7 +130,7 @@ 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 */
{ CHAN_OVNI_PID, 10, 60 },
{ CHAN_OVNI_TID, 11, 61 },
@ -230,6 +235,8 @@ enum ovni_cpu_state {
CPU_ST_READY,
};
#define MAX_CPU_NAME 32
struct ovni_cpu {
/* Logical index: 0 to ncpus - 1 */
int i;
@ -253,6 +260,9 @@ struct ovni_cpu {
/* The threads the cpu is currently running */
size_t nthreads;
struct ovni_ethread *thread[OVNI_MAX_THR];
/* Cpu name as shown in paraver row */
char name[MAX_CPU_NAME];
};
/* ----------------------- trace ------------------------ */
@ -315,6 +325,8 @@ struct ovni_stream {
int64_t clock_offset;
};
#define MAX_BURSTS 100
struct ovni_emu {
struct ovni_trace trace;
@ -347,6 +359,10 @@ struct ovni_emu {
int total_nthreads;
int total_proc;
int total_ncpus;
/* Burst times */
int nbursts;
int64_t burst_time[MAX_BURSTS];
};
/* 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_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 */
@ -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_TYPEID], task->type_id + 1);
chan_set(&th->chan[CHAN_NOSV_APPID], proc->appid + 1);
chan_push(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_TASK_RUNNING);
}
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_TYPEID], 0);
chan_set(&th->chan[CHAN_NOSV_APPID], 0);
chan_pop(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_TASK_RUNNING);
}
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
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 'U': pre_submit(emu); break;
case 'M': pre_memory(emu); break;
case 'C': pre_code(emu); break;
default:
break;
}

View File

@ -43,6 +43,10 @@ hook_init_ovni(struct ovni_emu *emu)
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);
/* 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 */
@ -72,23 +76,40 @@ hook_init_ovni(struct ovni_emu *emu)
/* --------------------------- pre ------------------------------- */
static void
thread_set_channel_enabled(struct ovni_ethread *th, int enabled)
thread_update_channels(struct ovni_ethread *th)
{
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++)
{
chan = &th->chan[i];
if(chan->track == CHAN_TRACK_TH_RUNNING)
switch (chan->track)
{
chan_enable(chan, enabled);
dbg("thread %d: %s chan %d\n",
th->tid,
enabled ? "enable" : "disable",
i);
case CHAN_TRACK_TH_RUNNING:
enabled = is_running ? 1 : 0;
break;
case CHAN_TRACK_TH_UNPAUSED:
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;
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
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_ethread *th;
struct ovni_ethread *th, *last_th;
struct ovni_chan *chan;
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;
if(cpu->nthreads == 0)
if(nrunning == 0)
{
/* No thread running */
tid = pid = 0;
}
else if(cpu->nthreads == 1)
else if(nrunning == 1)
{
/* Take the info from the unique thread */
tid = cpu->thread[0]->tid;
pid = cpu->thread[0]->proc->pid;
th = cpu->thread[0];
/* Take the info from the running thread */
tid = last_th->tid;
pid = last_th->proc->pid;
th = last_th;
}
else
{
@ -186,8 +219,8 @@ emu_cpu_find_thread(struct ovni_cpu *cpu, struct ovni_ethread *thread)
return i;
}
void
emu_cpu_add_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
static void
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)
@ -200,8 +233,8 @@ emu_cpu_add_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethre
update_cpu(emu, cpu);
}
void
emu_cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
static void
cpu_remove_thread(struct ovni_emu *emu, struct ovni_cpu *cpu, struct ovni_ethread *thread)
{
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);
}
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
print_threads_state(struct ovni_loom *loom)
{
@ -246,14 +325,11 @@ print_threads_state(struct ovni_loom *loom)
}
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_ethread *th;
int cpuid;
th = emu->cur_thread;
/* The thread cannot be already 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);
thread_set_state(th, TH_ST_RUNNING);
th->cpu = cpu;
thread_set_cpu(th, 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);
cpu_add_thread(emu, cpu, th);
/* 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)
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->cpu);
emu_cpu_remove_thread(emu, th->cpu, th);
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);
thread_unset_cpu(th);
/* 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
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(emu->cur_thread->cpu);
assert(th->state == TH_ST_RUNNING || th->state == TH_ST_COOLING);
assert(th->cpu);
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);
thread_set_state(th, TH_ST_PAUSED);
}
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(emu->cur_thread->cpu);
assert(th->state == TH_ST_PAUSED || th->state == TH_ST_WARMING);
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);
chan_set(&emu->cur_thread->chan[CHAN_OVNI_STATE], emu->cur_thread->state);
static void
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
@ -334,29 +405,31 @@ pre_thread(struct ovni_emu *emu)
{
struct ovni_ev *ev;
struct ovni_cpu *cpu;
struct ovni_ethread *thread, *remote_thread;
struct ovni_ethread *th, *remote_thread;
int i;
//emu_emit(emu);
thread = emu->cur_thread;
cpu = thread->cpu;
th = emu->cur_thread;
cpu = th->cpu;
ev = emu->cur_ev;
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",
thread->tid,
th->tid,
ev->payload.u32[0],
ev->payload.u32[1],
ev->payload.u32[2]);
break;
case 'x': pre_thread_execute(emu); break;
case 'e': pre_thread_end(emu); break;
case 'p': pre_thread_pause(emu); break;
case 'r': pre_thread_resume(emu); break;
case 'x': pre_thread_execute(emu, th); break;
case 'e': pre_thread_end(emu, th); break;
case 'p': pre_thread_pause(emu, th); 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:
err("unknown thread event value %c\n",
ev->header.value);
@ -369,32 +442,31 @@ pre_affinity_set(struct ovni_emu *emu)
{
int cpuid;
struct ovni_cpu *newcpu;
struct ovni_ethread *th;
th = emu->cur_thread;
cpuid = emu->cur_ev->payload.i32[0];
assert(emu->cur_thread->state == TH_ST_RUNNING);
assert(emu->cur_thread->cpu);
assert(th->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 */
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",
emu->cur_thread->tid,
emu->cur_thread->cpu->gindex);
th->tid,
th->cpu->gindex);
return;
}
emu_cpu_remove_thread(emu, emu->cur_thread->cpu, emu->cur_thread);
emu_cpu_add_thread(emu, newcpu, emu->cur_thread);
cpu_migrate_thread(emu, th->cpu, th, newcpu);
thread_migrate_cpu(th, newcpu);
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);
//dbg("cpu %d now runs %d\n", cpuid, th->tid);
}
static void
@ -402,45 +474,29 @@ pre_affinity_remote(struct ovni_emu *emu)
{
int cpuid, tid;
struct ovni_cpu *newcpu;
struct ovni_ethread *thread;
struct ovni_ethread *remote_th;
cpuid = emu->cur_ev->payload.i32[0];
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 */
assert(thread->state == TH_ST_RUNNING ||
thread->state == TH_ST_PAUSED);
/* The remote_th cannot be in states dead or unknown */
assert(remote_th->state != TH_ST_DEAD
&& remote_th->state != TH_ST_UNKNOWN);
/* It must have an assigned CPU */
assert(thread->cpu);
assert(remote_th->cpu);
/* Migrate current cpu to the one at cpuid */
newcpu = emu_get_cpu(emu->cur_loom, cpuid);
/* If running, update the CPU thread lists */
if(thread->state == TH_ST_RUNNING)
{
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);
}
cpu_migrate_thread(emu, remote_th->cpu, remote_th, newcpu);
thread_migrate_cpu(remote_th, newcpu);
/* 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,
//dbg("remote_th %d switches to cpu %d by remote petition\n", tid,
// 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
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 'A': pre_affinity(emu); break;
case 'B':
//dbg("burst %c\n", emu->cur_ev->header.value);
break;
case 'B': pre_burst(emu); break;
default:
dbg("unknown ovni event class %c\n",
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_PAUSED, "Paused" },
{ TH_ST_DEAD, "Dead" },
{ TH_ST_COOLING, "Cooling" },
{ TH_ST_WARMING, "Warming" },
{ -1, NULL },
};
@ -121,6 +123,8 @@ struct event_value ss_values[] = {
{ ST_SCHED_HUNGRY, "Scheduler: Hungry" },
{ ST_SCHED_SERVING, "Scheduler: Serving" },
{ 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_RECV, "EV Scheduler: Recv task" },
{ EV_SCHED_SELF, "EV Scheduler: Self-assign task" },
@ -138,6 +142,11 @@ struct event_type cpu_ss = {
ss_values
};
struct event_type thread_cpu_affinity = {
0, chan_to_prvtype[CHAN_OVNI_CPU][1], "Thread: current CPU affinity",
/* Ignored */ NULL
};
static void
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
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_tid);
write_event_type(f, &thread_ss);
write_event_type(f, &cpu_ss);
write_cpu_type(f, &thread_cpu_affinity, emu);
}
int
pcf_write(FILE *f)
pcf_write(FILE *f, struct ovni_emu *emu)
{
write_header(f);
write_colors(f, pcf_palette, pcf_palette_len);
write_events(f);
write_events(f, emu);
return 0;
}

3
pcf.h
View File

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