Use one event per blocking type in Nanos6
This commit is contained in:
parent
5c45323354
commit
ac1ae8e69d
@ -37,7 +37,7 @@ window_pixel_size 1
|
||||
window_labels_to_draw 1
|
||||
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||
window_filter_module evt_type 1 40
|
||||
window_filter_module evt_type 1 45
|
||||
window_filter_module evt_type_label 1 "CPU: Context switches of the ACTIVE thread"
|
||||
window_synchronize 1
|
||||
|
||||
|
@ -37,7 +37,7 @@ window_pixel_size 1
|
||||
window_labels_to_draw 1
|
||||
window_selected_functions { 14, { {cpu, Active Thd}, {appl, Adding}, {task, Adding}, {thread, Last Evt Val}, {node, Adding}, {system, Adding}, {workload, Adding}, {from_obj, All}, {to_obj, All}, {tag_msg, All}, {size_msg, All}, {bw_msg, All}, {evt_type, =}, {evt_value, All} } }
|
||||
window_compose_functions { 9, { {compose_cpu, As Is}, {compose_appl, As Is}, {compose_task, As Is}, {compose_thread, As Is}, {compose_node, As Is}, {compose_system, As Is}, {compose_workload, As Is}, {topcompose1, As Is}, {topcompose2, As Is} } }
|
||||
window_filter_module evt_type 1 40
|
||||
window_filter_module evt_type 1 45
|
||||
window_filter_module evt_type_label 1 "Thread: Context switches of the CURRENT thread"
|
||||
window_synchronize 1
|
||||
|
||||
|
@ -162,14 +162,20 @@ KCI Is back in the CPU due to a context switch
|
||||
6Ha Attaches to Nanos6 as external thread
|
||||
6HA Detaches from Nanos6 as external thread
|
||||
|
||||
6s[ Begins to spawn a function via spawnFunction()
|
||||
6s] Ends spawning a function
|
||||
6F[ Begins to spawn a function via spawnFunction()
|
||||
6F] Ends spawning a function
|
||||
|
||||
6Dr Begins the registration of a task's accesses
|
||||
6DR Ends the registration of a task's accesses
|
||||
6Du Begins the unregistration of a task's accesses
|
||||
6DU Ends the unregistration of a task's accesses
|
||||
|
||||
6Bu Begins to unblock the given task
|
||||
6BU Ends unblocking the given task
|
||||
6Bu Begins to unblock a task
|
||||
6BU Ends unblocking a task
|
||||
6Bb Begins to block the current task via blockCurrentTask()
|
||||
6BB Ends blocking the current task via blockCurrentTask()
|
||||
6Bw Enters taskWait()
|
||||
6BW Exits taskWait()
|
||||
6Bf Enters taskFor()
|
||||
6BF Exits taskFor()
|
||||
```
|
||||
|
@ -53,6 +53,10 @@ task. It is only shown when the task is in the running state. This view
|
||||
is specially useful to identify task in a distributed workload, which
|
||||
spans several nodes.
|
||||
|
||||
As the zero value in Paraver gets hidden, we use the rank+1 value
|
||||
instead. Therefore the rank numeric value go from 1 to the number of
|
||||
ranks (inclusive).
|
||||
|
||||
## Subsystem view
|
||||
|
||||
The subsystem view attempts to provide a general overview of what Nanos6
|
||||
@ -95,7 +99,7 @@ Task subsystem
|
||||
: The **Task** subsystem contains the code that controls the life cycle
|
||||
of tasks. It contains the following sections:
|
||||
|
||||
- **Running**: Executing the body of the task (user defined code).
|
||||
- **Body**: Executing the body of the task (user defined code).
|
||||
|
||||
- **Spawning function**: Spawning a function as task (it will be
|
||||
submitted to the scheduler for later execution).
|
||||
|
75
emu.h
75
emu.h
@ -104,40 +104,30 @@ enum nodes_state {
|
||||
* CTF implementation. */
|
||||
enum nanos6_ss_state {
|
||||
ST_NANOS6_NULL = 0, /* IDLE */
|
||||
/* RUNTIME */
|
||||
ST_NANOS6_TASK_BODY = 3, /* TASK */
|
||||
ST_NANOS6_TASK_CREATING = 8, /* TASK_CREATE */
|
||||
ST_NANOS6_TASK_SUBMIT = 10, /* TASK_SUBMIT */
|
||||
ST_NANOS6_TASK_SPAWNING = 18, /* SPAWN_FUNCTION */
|
||||
ST_NANOS6_SCHED_HUNGRY = 2, /* BUSY_WAIT */
|
||||
ST_NANOS6_TASK_RUNNING = 3, /* TASK */
|
||||
ST_NANOS6_SCHED_ADDING = 6, /* SCHEDULER_ADD_TASK */
|
||||
ST_NANOS6_SCHED_SERVING = 20, /* SCHEDULER_LOCK_SERVING */
|
||||
ST_NANOS6_DEP_REG = 4, /* DEPENDENCY_REGISTER */
|
||||
ST_NANOS6_DEP_UNREG = 5, /* DEPENDENCY_UNREGISTER */
|
||||
ST_NANOS6_SCHED_SUBMITTING = 6, /* SCHEDULER_ADD_TASK */
|
||||
/* SCHEDULER_GET_TASK */
|
||||
ST_NANOS6_CREATING = 8, /* TASK_CREATE */
|
||||
/* TASK_ARGS_INIT */
|
||||
ST_NANOS6_SUBMIT = 10, /* TASK_SUBMIT */
|
||||
/* TASKFOR_INIT */
|
||||
ST_NANOS6_TASKWAIT = 12, /* TASK_WAIT */
|
||||
ST_NANOS6_WAITFOR = 13, /* WAIT_FOR */
|
||||
/* LOCK */
|
||||
/* UNLOCK */
|
||||
ST_NANOS6_BLOCKING = 16, /* BLOCKING_API_BLOCK */
|
||||
ST_NANOS6_UNBLOCKING = 17, /* BLOCKING_API_UNBLOCK */
|
||||
ST_NANOS6_SPAWNING = 18, /* SPAWN_FUNCTION */
|
||||
/* SCHEDULER_LOCK_ENTER */
|
||||
ST_NANOS6_SCHED_SERVING = 20, /* SCHEDULER_LOCK_SERVING */
|
||||
ST_NANOS6_ATTACHED,
|
||||
ST_NANOS6_BLK_TASKWAIT = 12, /* TASK_WAIT */
|
||||
ST_NANOS6_BLK_WAITFOR = 13, /* WAIT_FOR */
|
||||
ST_NANOS6_BLK_BLOCKING = 16, /* BLOCKING_API_BLOCK */
|
||||
ST_NANOS6_BLK_UNBLOCKING = 17, /* BLOCKING_API_UNBLOCK */
|
||||
|
||||
EV_NANOS6_SCHED_RECV,
|
||||
EV_NANOS6_SCHED_SEND,
|
||||
EV_NANOS6_SCHED_SELF,
|
||||
EV_NANOS6_SCHED_RECV = 50,
|
||||
EV_NANOS6_SCHED_SEND = 51,
|
||||
EV_NANOS6_SCHED_SELF = 52,
|
||||
};
|
||||
|
||||
/* Possible reasons for Nanos6 tasks becoming running or not running */
|
||||
enum nanos6_task_run_reason
|
||||
{
|
||||
TB_EXEC_OR_END = -1,
|
||||
TB_BLOCKING_API = 0,
|
||||
TB_TASKWAIT = 1,
|
||||
TB_WAITFOR = 2
|
||||
enum nanos6_thread_state {
|
||||
ST_NANOS6_TH_EXTERNAL = 1,
|
||||
ST_NANOS6_TH_WORKER,
|
||||
ST_NANOS6_TH_LEADER,
|
||||
ST_NANOS6_TH_MAIN
|
||||
};
|
||||
|
||||
enum kernel_cs_state {
|
||||
@ -169,6 +159,20 @@ struct task {
|
||||
struct task *prev;
|
||||
};
|
||||
|
||||
struct task_info {
|
||||
/* Both hash maps of all known tasks and types */
|
||||
struct task_type *types;
|
||||
struct task *tasks;
|
||||
};
|
||||
|
||||
struct task_stack {
|
||||
union {
|
||||
struct task *top; /* Synctactic sugar */
|
||||
struct task *tasks;
|
||||
};
|
||||
struct ovni_ethread *thread;
|
||||
};
|
||||
|
||||
#define MAX_CHAN_STACK 128
|
||||
|
||||
enum chan_track {
|
||||
@ -207,6 +211,7 @@ enum chan {
|
||||
CHAN_NANOS6_TYPE,
|
||||
CHAN_NANOS6_SUBSYSTEM,
|
||||
CHAN_NANOS6_RANK,
|
||||
CHAN_NANOS6_THREAD,
|
||||
|
||||
CHAN_KERNEL_CS,
|
||||
|
||||
@ -249,7 +254,8 @@ static const int chan_to_prvtype[CHAN_MAX] = {
|
||||
[CHAN_NANOS6_TYPE] = 36,
|
||||
[CHAN_NANOS6_SUBSYSTEM] = 37,
|
||||
[CHAN_NANOS6_RANK] = 38,
|
||||
[CHAN_KERNEL_CS] = 40,
|
||||
[CHAN_NANOS6_THREAD] = 39,
|
||||
[CHAN_KERNEL_CS] = 45,
|
||||
};
|
||||
|
||||
struct ovni_chan {
|
||||
@ -335,8 +341,8 @@ struct ovni_ethread {
|
||||
* structures */
|
||||
|
||||
/* Task stacks, top ones are the tasks currently runnable. */
|
||||
struct task *nosv_task_stack;
|
||||
struct task *nanos6_task_stack;
|
||||
struct task_stack nosv_task_stack;
|
||||
struct task_stack nanos6_task_stack;
|
||||
|
||||
/* Channels are used to output the emulator state in PRV */
|
||||
struct ovni_chan chan[CHAN_MAX];
|
||||
@ -376,11 +382,8 @@ struct ovni_eproc {
|
||||
/* ------ Subsystem specific data --------*/
|
||||
/* TODO: Use dynamic allocation */
|
||||
|
||||
struct task_type *nosv_types;
|
||||
struct task *nosv_tasks;
|
||||
|
||||
struct task_type *nanos6_types;
|
||||
struct task *nanos6_tasks;
|
||||
struct task_info nosv_task_info;
|
||||
struct task_info nanos6_task_info;
|
||||
};
|
||||
|
||||
|
||||
|
367
emu_nanos6.c
367
emu_nanos6.c
@ -30,7 +30,6 @@ hook_init_nanos6(struct ovni_emu *emu)
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_cpu *cpu;
|
||||
struct ovni_chan **uth, **ucpu;
|
||||
size_t i;
|
||||
int row;
|
||||
FILE *prv_th, *prv_cpu;
|
||||
int64_t *clock;
|
||||
@ -40,7 +39,7 @@ hook_init_nanos6(struct ovni_emu *emu)
|
||||
prv_cpu = emu->prv_cpu;
|
||||
|
||||
/* Init the channels in all threads */
|
||||
for(i=0; i<emu->total_nthreads; i++)
|
||||
for(size_t i=0; i<emu->total_nthreads; i++)
|
||||
{
|
||||
th = emu->global_thread[i];
|
||||
row = th->gindex + 1;
|
||||
@ -51,10 +50,11 @@ hook_init_nanos6(struct ovni_emu *emu)
|
||||
chan_th_init(th, uth, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_ACTIVE, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
chan_th_init(th, uth, CHAN_NANOS6_THREAD, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_th, clock);
|
||||
}
|
||||
|
||||
/* Init the Nanos6 channels in all cpus */
|
||||
for(i=0; i<emu->total_ncpus; i++)
|
||||
for(size_t i=0; i<emu->total_ncpus; i++)
|
||||
{
|
||||
cpu = emu->global_cpu[i];
|
||||
row = cpu->gindex + 1;
|
||||
@ -64,46 +64,38 @@ hook_init_nanos6(struct ovni_emu *emu)
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_TYPE, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NANOS6_THREAD, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
}
|
||||
|
||||
/* Init task stack */
|
||||
for(size_t i=0; i<emu->total_nthreads; i++)
|
||||
{
|
||||
th = emu->global_thread[i];
|
||||
th->nanos6_task_stack.thread = th;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------- pre ------------------------------- */
|
||||
|
||||
static void
|
||||
task_not_running(struct ovni_emu *emu, struct task *task, enum nanos6_task_run_reason reason)
|
||||
chan_task_stopped(struct ovni_emu *emu, char tr)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
th = emu->cur_thread;
|
||||
|
||||
if(task->state == TASK_ST_RUNNING)
|
||||
die("task is still running\n");
|
||||
|
||||
chan_set(&th->chan[CHAN_NANOS6_TASKID], 0);
|
||||
chan_set(&th->chan[CHAN_NANOS6_TYPE], 0);
|
||||
|
||||
if(emu->cur_loom->rank_enabled)
|
||||
chan_set(&th->chan[CHAN_NANOS6_RANK], 0);
|
||||
|
||||
// Check the reason
|
||||
switch (reason)
|
||||
{
|
||||
case TB_EXEC_OR_END:
|
||||
chan_pop(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_TASK_RUNNING);
|
||||
break;
|
||||
case TB_BLOCKING_API:
|
||||
chan_push(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_BLOCKING);
|
||||
break;
|
||||
case TB_TASKWAIT:
|
||||
chan_push(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_TASKWAIT);
|
||||
break;
|
||||
case TB_WAITFOR:
|
||||
chan_push(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_WAITFOR);
|
||||
break;
|
||||
}
|
||||
/* Only exit the task body when finishing */
|
||||
if(tr == 'e')
|
||||
chan_pop(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_TASK_BODY);
|
||||
}
|
||||
|
||||
static void
|
||||
task_running(struct ovni_emu *emu, struct task *task, enum nanos6_task_run_reason reason)
|
||||
chan_task_running(struct ovni_emu *emu, struct task *task, char tr)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_eproc *proc;
|
||||
@ -126,65 +118,150 @@ task_running(struct ovni_emu *emu, struct task *task, enum nanos6_task_run_reaso
|
||||
if(emu->cur_loom->rank_enabled)
|
||||
chan_set(&th->chan[CHAN_NANOS6_RANK], proc->rank + 1);
|
||||
|
||||
// Check the reason
|
||||
switch (reason)
|
||||
{
|
||||
case TB_EXEC_OR_END:
|
||||
chan_push(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_TASK_RUNNING);
|
||||
break;
|
||||
case TB_BLOCKING_API:
|
||||
chan_pop(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_BLOCKING);
|
||||
break;
|
||||
case TB_TASKWAIT:
|
||||
chan_pop(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_TASKWAIT);
|
||||
break;
|
||||
case TB_WAITFOR:
|
||||
chan_pop(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_WAITFOR);
|
||||
break;
|
||||
}
|
||||
/* Only enter the body of the task when we begin the execution */
|
||||
if(tr == 'x')
|
||||
chan_push(&th->chan[CHAN_NANOS6_SUBSYSTEM], ST_NANOS6_TASK_BODY);
|
||||
}
|
||||
|
||||
static void
|
||||
task_switch(struct ovni_emu *emu, struct task *prev_task,
|
||||
struct task *next_task, int newtask)
|
||||
chan_task_switch(struct ovni_emu *emu,
|
||||
struct task *prev, struct task *next)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
|
||||
th = emu->cur_thread;
|
||||
|
||||
if(!prev_task || !next_task)
|
||||
if(!prev || !next)
|
||||
die("cannot switch to or from a NULL task\n");
|
||||
|
||||
if(prev_task == next_task)
|
||||
if(prev == next)
|
||||
die("cannot switch to the same task\n");
|
||||
|
||||
if(newtask && prev_task->state != TASK_ST_RUNNING)
|
||||
die("previous task must not be no longer running\n");
|
||||
|
||||
if(!newtask && prev_task->state != TASK_ST_DEAD)
|
||||
die("previous task must be dead\n");
|
||||
|
||||
if(next_task->state != TASK_ST_RUNNING)
|
||||
die("next task must be running\n");
|
||||
|
||||
if(next_task->id == 0)
|
||||
if(next->id == 0)
|
||||
die("next task id cannot be 0\n");
|
||||
|
||||
if(next_task->type->gid == 0)
|
||||
if(next->type->gid == 0)
|
||||
die("next task type id cannot be 0\n");
|
||||
|
||||
if(prev_task->thread != next_task->thread)
|
||||
if(prev->thread != next->thread)
|
||||
die("cannot switch to a task of another thread\n");
|
||||
|
||||
/* No need to change the rank as we will switch to tasks from same stack */
|
||||
chan_set(&th->chan[CHAN_NANOS6_TASKID], next_task->id);
|
||||
/* No need to change the rank as we will switch to tasks from
|
||||
* same thread */
|
||||
chan_set(&th->chan[CHAN_NANOS6_TASKID], next->id);
|
||||
|
||||
/* FIXME: We should emit a PRV event even if we are switching to
|
||||
* the same type event, to mark the end of the current task. For
|
||||
* now we only emit a new type if we switch to a type with a
|
||||
* different gid. */
|
||||
if(prev_task->type->gid != next_task->type->gid)
|
||||
chan_set(&th->chan[CHAN_NANOS6_TYPE], next_task->type->gid);
|
||||
if(prev->type->gid != next->type->gid)
|
||||
chan_set(&th->chan[CHAN_NANOS6_TYPE], next->type->gid);
|
||||
}
|
||||
|
||||
static void
|
||||
update_task_state(struct ovni_emu *emu)
|
||||
{
|
||||
if(ovni_payload_size(emu->cur_ev) < 4)
|
||||
die("missing task id in payload\n");
|
||||
|
||||
uint32_t task_id = emu->cur_ev->payload.u32[0];
|
||||
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
struct ovni_eproc *proc = emu->cur_proc;
|
||||
|
||||
struct task_info *info = &proc->nanos6_task_info;
|
||||
struct task_stack *stack = &th->nanos6_task_stack;
|
||||
|
||||
struct task *task = task_find(info->tasks, task_id);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %u\n", task_id);
|
||||
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'x': task_execute(stack, task); break;
|
||||
case 'e': task_end(stack, task); break;
|
||||
case 'p': task_pause(stack, task); break;
|
||||
case 'r': task_resume(stack, task); break;
|
||||
default:
|
||||
die("unexpected Nanos6 task event value %c\n",
|
||||
emu->cur_ev->header.value);
|
||||
}
|
||||
}
|
||||
|
||||
static char
|
||||
expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now)
|
||||
{
|
||||
char tr = emu->cur_ev->header.value;
|
||||
|
||||
/* Ensure we don't clobber the value */
|
||||
if(tr == 'X' || tr == 'E')
|
||||
die("unexpected event value %c\n", tr);
|
||||
|
||||
/* Modify the event value to detect nested transitions */
|
||||
if(tr == 'x' && was_running)
|
||||
tr = 'X'; /* Execute a new nested task */
|
||||
else if(tr == 'e' && runs_now)
|
||||
tr = 'E'; /* End a nested task */
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
static void
|
||||
update_task_channels(struct ovni_emu *emu,
|
||||
char tr, struct task *prev, struct task *next)
|
||||
{
|
||||
switch(tr)
|
||||
{
|
||||
case 'x':
|
||||
case 'r':
|
||||
chan_task_running(emu, next, tr);
|
||||
break;
|
||||
case 'e':
|
||||
case 'p':
|
||||
chan_task_stopped(emu, tr);
|
||||
break;
|
||||
/* Additional nested transitions */
|
||||
case 'X':
|
||||
case 'E':
|
||||
chan_task_switch(emu, prev, next);
|
||||
break;
|
||||
default:
|
||||
die("unexpected transition value %c\n", tr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_task(struct ovni_emu *emu)
|
||||
{
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
struct task_stack *stack = &th->nanos6_task_stack;
|
||||
|
||||
struct task *prev = task_get_running(stack);
|
||||
|
||||
/* Update the emulator state, but don't modify the channels */
|
||||
update_task_state(emu);
|
||||
|
||||
struct task *next = task_get_running(stack);
|
||||
|
||||
int was_running = (prev != NULL);
|
||||
int runs_now = (next != NULL);
|
||||
char tr = expand_transition_value(emu, was_running, runs_now);
|
||||
|
||||
/* Update the channels now */
|
||||
update_task_channels(emu, tr, prev, next);
|
||||
}
|
||||
|
||||
static void
|
||||
create_task(struct ovni_emu *emu)
|
||||
{
|
||||
if(ovni_payload_size(emu->cur_ev) != 8)
|
||||
die("cannot create task: unexpected payload size\n");
|
||||
|
||||
uint32_t task_id = emu->cur_ev->payload.u32[0];
|
||||
uint32_t type_id = emu->cur_ev->payload.u32[1];
|
||||
|
||||
struct task_info *info = &emu->cur_proc->nanos6_task_info;
|
||||
|
||||
task_create(info, type_id, task_id);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -192,87 +269,53 @@ pre_task(struct ovni_emu *emu)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_chan *chan_th;
|
||||
struct task **task_map = &emu->cur_proc->nanos6_tasks;
|
||||
struct task_type **type_map = &emu->cur_proc->nanos6_types;
|
||||
struct task **task_stack = &emu->cur_thread->nanos6_task_stack;
|
||||
struct task *prev_running = task_get_running(*task_stack);
|
||||
int was_running_task = (prev_running != NULL);
|
||||
|
||||
th = emu->cur_thread;
|
||||
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
|
||||
|
||||
/* Update the emulator state, but don't modify the channels yet */
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'c': task_create(emu->cur_ev->payload.i32[0], emu->cur_ev->payload.i32[1], task_map, type_map); break;
|
||||
case 'x': task_execute(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'e': task_end(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'b': task_pause(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'u': task_resume(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'C': break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
struct task *next_running = task_get_running(*task_stack);
|
||||
int runs_task_now = (next_running != NULL);
|
||||
|
||||
/* Now that we know if the emulator was running a task before
|
||||
* or if it's running one now, update the channels accordingly. */
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'x': /* Execute: either a nested task or a new one */
|
||||
if(was_running_task)
|
||||
task_switch(emu, prev_running, next_running, 1);
|
||||
else
|
||||
task_running(emu, next_running, TB_EXEC_OR_END);
|
||||
/* We use the 'c' event to create the task and switch
|
||||
* the subsystem all in one step because the timing here
|
||||
* is critical. */
|
||||
case 'c':
|
||||
chan_push(chan_th, ST_NANOS6_TASK_CREATING);
|
||||
create_task(emu);
|
||||
break;
|
||||
case 'e': /* End: either a nested task or the last one */
|
||||
if(runs_task_now)
|
||||
task_switch(emu, prev_running, next_running, 0);
|
||||
else
|
||||
task_not_running(emu, prev_running, TB_EXEC_OR_END);
|
||||
case 'C':
|
||||
chan_pop(chan_th, ST_NANOS6_TASK_CREATING);
|
||||
break;
|
||||
case 'b': /* Block */
|
||||
task_not_running(emu, prev_running, emu->cur_ev->payload.i32[1]);
|
||||
break;
|
||||
case 'u': /* Unblock */
|
||||
task_running(emu, next_running, emu->cur_ev->payload.i32[1]);
|
||||
break;
|
||||
case 'c': /* Create */
|
||||
chan_push(chan_th, ST_NANOS6_CREATING);
|
||||
break;
|
||||
case 'C': /* Create end */
|
||||
chan_pop(chan_th, ST_NANOS6_CREATING);
|
||||
case 'x':
|
||||
case 'e':
|
||||
case 'r':
|
||||
case 'p': /* Wet floor */
|
||||
update_task(emu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
die("unexpected event value %c\n",
|
||||
emu->cur_ev->header.value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pre_type(struct ovni_emu *emu)
|
||||
{
|
||||
uint8_t *data;
|
||||
if(emu->cur_ev->header.value != 'c')
|
||||
die("unexpected event value %c\n",
|
||||
emu->cur_ev->header.value);
|
||||
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'c':
|
||||
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
|
||||
{
|
||||
err("expecting a jumbo event\n");
|
||||
abort();
|
||||
}
|
||||
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
|
||||
die("expecting a jumbo event\n");
|
||||
|
||||
data = &emu->cur_ev->payload.jumbo.data[0];
|
||||
uint32_t *typeid = (uint32_t *) data;
|
||||
data += sizeof(*typeid);
|
||||
const char *label = (const char *) data;
|
||||
task_type_create(*typeid, label, &emu->cur_proc->nanos6_types);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint8_t *data = &emu->cur_ev->payload.jumbo.data[0];
|
||||
uint32_t typeid = *(uint32_t *) data;
|
||||
data += 4;
|
||||
|
||||
const char *label = (const char *) data;
|
||||
|
||||
struct ovni_eproc *proc = emu->cur_proc;
|
||||
|
||||
task_type_create(&proc->nanos6_task_info, typeid, label);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -287,9 +330,9 @@ pre_deps(struct ovni_emu *emu)
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'r': chan_push(chan_th, ST_NANOS6_DEP_REG); break;
|
||||
case 'R': chan_pop(chan_th, ST_NANOS6_DEP_REG); break;
|
||||
case 'R': chan_pop (chan_th, ST_NANOS6_DEP_REG); break;
|
||||
case 'u': chan_push(chan_th, ST_NANOS6_DEP_UNREG); break;
|
||||
case 'U': chan_pop(chan_th, ST_NANOS6_DEP_UNREG); break;
|
||||
case 'U': chan_pop (chan_th, ST_NANOS6_DEP_UNREG); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -305,8 +348,14 @@ pre_blocking(struct ovni_emu *emu)
|
||||
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'u': chan_push(chan_th, ST_NANOS6_UNBLOCKING); break;
|
||||
case 'U': chan_pop(chan_th, ST_NANOS6_UNBLOCKING); break;
|
||||
case 'b': chan_push(chan_th, ST_NANOS6_BLK_BLOCKING); break;
|
||||
case 'B': chan_pop (chan_th, ST_NANOS6_BLK_BLOCKING); break;
|
||||
case 'u': chan_push(chan_th, ST_NANOS6_BLK_UNBLOCKING); break;
|
||||
case 'U': chan_pop (chan_th, ST_NANOS6_BLK_UNBLOCKING); break;
|
||||
case 'w': chan_push(chan_th, ST_NANOS6_BLK_TASKWAIT); break;
|
||||
case 'W': chan_pop (chan_th, ST_NANOS6_BLK_TASKWAIT); break;
|
||||
case 'f': chan_push(chan_th, ST_NANOS6_BLK_WAITFOR); break;
|
||||
case 'F': chan_pop (chan_th, ST_NANOS6_BLK_WAITFOR); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -334,20 +383,24 @@ pre_sched(struct ovni_emu *emu)
|
||||
}
|
||||
|
||||
static void
|
||||
pre_thread_type(struct ovni_emu *emu)
|
||||
pre_thread(struct ovni_emu *emu)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_chan *chan_th;
|
||||
|
||||
th = emu->cur_thread;
|
||||
chan_th = &th->chan[CHAN_NANOS6_SUBSYSTEM];
|
||||
chan_th = &th->chan[CHAN_NANOS6_THREAD];
|
||||
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'a': chan_push(chan_th, ST_NANOS6_ATTACHED); break;
|
||||
case 'A': chan_pop (chan_th, ST_NANOS6_ATTACHED); break;
|
||||
case 's': chan_push(chan_th, ST_NANOS6_SPAWNING); break;
|
||||
case 'S': chan_pop (chan_th, ST_NANOS6_SPAWNING); break;
|
||||
case 'e': chan_push(chan_th, ST_NANOS6_TH_EXTERNAL); break;
|
||||
case 'E': chan_pop (chan_th, ST_NANOS6_TH_EXTERNAL); break;
|
||||
case 'w': chan_push(chan_th, ST_NANOS6_TH_WORKER); break;
|
||||
case 'W': chan_pop (chan_th, ST_NANOS6_TH_WORKER); break;
|
||||
case 'l': chan_push(chan_th, ST_NANOS6_TH_LEADER); break;
|
||||
case 'L': chan_pop (chan_th, ST_NANOS6_TH_LEADER); break;
|
||||
case 'm': chan_push(chan_th, ST_NANOS6_TH_MAIN); break;
|
||||
case 'M': chan_pop (chan_th, ST_NANOS6_TH_MAIN); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
@ -406,8 +459,8 @@ hook_pre_nanos6(struct ovni_emu *emu)
|
||||
case 'T': pre_task(emu); break;
|
||||
case 'Y': pre_type(emu); break;
|
||||
case 'S': pre_sched(emu); break;
|
||||
case 'U': pre_ss(emu, ST_NANOS6_SUBMIT); break;
|
||||
case 'H': pre_thread_type(emu); break;
|
||||
case 'U': pre_ss(emu, ST_NANOS6_TASK_SUBMIT); break;
|
||||
case 'H': pre_thread(emu); break;
|
||||
case 'D': pre_deps(emu); break;
|
||||
case 'B': pre_blocking(emu); break;
|
||||
default:
|
||||
@ -417,27 +470,6 @@ hook_pre_nanos6(struct ovni_emu *emu)
|
||||
check_affinity(emu);
|
||||
}
|
||||
|
||||
char *nanos6_ss_names[] = {
|
||||
[ST_NANOS6_NULL] = "ST_NANOS6_NULL",
|
||||
[ST_NANOS6_SCHED_HUNGRY] = "ST_NANOS6_SCHED_HUNGRY",
|
||||
[ST_NANOS6_TASK_RUNNING] = "ST_NANOS6_TASK_RUNNING",
|
||||
[ST_NANOS6_DEP_REG] = "ST_NANOS6_DEP_REG",
|
||||
[ST_NANOS6_DEP_UNREG] = "ST_NANOS6_DEP_UNREG",
|
||||
[ST_NANOS6_SCHED_SUBMITTING] = "ST_NANOS6_SCHED_SUBMITTING",
|
||||
[ST_NANOS6_CREATING] = "ST_NANOS6_CREATING",
|
||||
[ST_NANOS6_SUBMIT] = "ST_NANOS6_SUBMIT",
|
||||
[ST_NANOS6_TASKWAIT] = "ST_NANOS6_TASKWAIT",
|
||||
[ST_NANOS6_WAITFOR] = "ST_NANOS6_WAITFOR",
|
||||
[ST_NANOS6_BLOCKING] = "ST_NANOS6_BLOCKING",
|
||||
[ST_NANOS6_UNBLOCKING] = "ST_NANOS6_UNBLOCKING",
|
||||
[ST_NANOS6_SPAWNING] = "ST_NANOS6_SPAWNING",
|
||||
[ST_NANOS6_SCHED_SERVING] = "ST_NANOS6_SCHED_SERVING",
|
||||
[ST_NANOS6_ATTACHED] = "ST_NANOS6_ATTACHED",
|
||||
[EV_NANOS6_SCHED_RECV] = "EV_NANOS6_SCHED_RECV",
|
||||
[EV_NANOS6_SCHED_SEND] = "EV_NANOS6_SCHED_SEND",
|
||||
[EV_NANOS6_SCHED_SELF] = "EV_NANOS6_SCHED_SELF",
|
||||
};
|
||||
|
||||
static void
|
||||
end_lint(struct ovni_emu *emu)
|
||||
{
|
||||
@ -449,8 +481,19 @@ end_lint(struct ovni_emu *emu)
|
||||
if(ch->n != 1)
|
||||
{
|
||||
int top = ch->stack[ch->n - 1];
|
||||
char *name = nanos6_ss_names[top];
|
||||
die("thread %d ended with %d extra stacked nanos6 subsystems, top=%s\n",
|
||||
|
||||
struct pcf_value_label *pv;
|
||||
char *name = "(unknown)";
|
||||
for(pv = &nanos6_ss_values[0]; pv->label; pv++)
|
||||
{
|
||||
if(pv->value == top)
|
||||
{
|
||||
name = pv->label;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
die("thread %d ended with %d extra stacked nanos6 subsystems, top=\"%s\"\n",
|
||||
th->tid, ch->n - 1, name);
|
||||
}
|
||||
}
|
||||
@ -472,7 +515,7 @@ hook_end_nanos6(struct ovni_emu *emu)
|
||||
for(size_t j = 0; j < loom->nprocs; j++)
|
||||
{
|
||||
struct ovni_eproc *proc = &loom->proc[j];
|
||||
task_create_pcf_types(pcftype, proc->nanos6_types);
|
||||
task_create_pcf_types(pcftype, proc->nanos6_task_info.types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
236
emu_nosv.c
236
emu_nosv.c
@ -74,18 +74,21 @@ hook_init_nosv(struct ovni_emu *emu)
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_RANK, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
chan_cpu_init(cpu, ucpu, CHAN_NOSV_SUBSYSTEM, CHAN_TRACK_TH_RUNNING, 0, 0, 1, row, prv_cpu, clock);
|
||||
}
|
||||
|
||||
/* Init task stack */
|
||||
for(i=0; i<emu->total_nthreads; i++)
|
||||
{
|
||||
th = emu->global_thread[i];
|
||||
th->nosv_task_stack.thread = th;
|
||||
}
|
||||
}
|
||||
|
||||
/* --------------------------- pre ------------------------------- */
|
||||
|
||||
static void
|
||||
task_not_running(struct ovni_emu *emu, struct task *task)
|
||||
chan_task_stopped(struct ovni_emu *emu)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
th = emu->cur_thread;
|
||||
|
||||
if(task->state == TASK_ST_RUNNING)
|
||||
die("task is still running\n");
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
|
||||
chan_set(&th->chan[CHAN_NOSV_TASKID], 0);
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPE], 0);
|
||||
@ -94,11 +97,12 @@ task_not_running(struct ovni_emu *emu, struct task *task)
|
||||
if(emu->cur_loom->rank_enabled)
|
||||
chan_set(&th->chan[CHAN_NOSV_RANK], 0);
|
||||
|
||||
/* XXX: Do we need this transition? */
|
||||
chan_pop(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_NOSV_TASK_RUNNING);
|
||||
}
|
||||
|
||||
static void
|
||||
task_running(struct ovni_emu *emu, struct task *task)
|
||||
chan_task_running(struct ovni_emu *emu, struct task *task)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_eproc *proc;
|
||||
@ -126,123 +130,179 @@ task_running(struct ovni_emu *emu, struct task *task)
|
||||
}
|
||||
|
||||
static void
|
||||
task_switch(struct ovni_emu *emu, struct task *prev_task,
|
||||
struct task *next_task, int newtask)
|
||||
chan_task_switch(struct ovni_emu *emu,
|
||||
struct task *prev, struct task *next)
|
||||
{
|
||||
struct ovni_ethread *th;
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
|
||||
th = emu->cur_thread;
|
||||
|
||||
if(!prev_task || !next_task)
|
||||
if(!prev || !next)
|
||||
die("cannot switch to or from a NULL task\n");
|
||||
|
||||
if(prev_task == next_task)
|
||||
if(prev == next)
|
||||
die("cannot switch to the same task\n");
|
||||
|
||||
if(newtask && prev_task->state != TASK_ST_RUNNING)
|
||||
die("previous task must not be no longer running\n");
|
||||
|
||||
if(!newtask && prev_task->state != TASK_ST_DEAD)
|
||||
die("previous task must be dead\n");
|
||||
|
||||
if(next_task->state != TASK_ST_RUNNING)
|
||||
die("next task must be running\n");
|
||||
|
||||
if(next_task->id == 0)
|
||||
if(next->id == 0)
|
||||
die("next task id cannot be 0\n");
|
||||
|
||||
if(next_task->type->gid == 0)
|
||||
if(next->type->gid == 0)
|
||||
die("next task type id cannot be 0\n");
|
||||
|
||||
if(prev_task->thread != next_task->thread)
|
||||
if(prev->thread != next->thread)
|
||||
die("cannot switch to a task of another thread\n");
|
||||
|
||||
/* No need to change the rank or app ID, as we can only switch
|
||||
* to tasks of the same thread */
|
||||
chan_set(&th->chan[CHAN_NOSV_TASKID], next_task->id);
|
||||
chan_set(&th->chan[CHAN_NOSV_TASKID], next->id);
|
||||
|
||||
/* FIXME: We should emit a PRV event even if we are switching to
|
||||
* the same type event, to mark the end of the current task. For
|
||||
* now we only emit a new type if we switch to a type with a
|
||||
* different gid. */
|
||||
if(prev_task->type->gid != next_task->type->gid)
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPE], next_task->type->gid);
|
||||
if(prev->type->gid != next->type->gid)
|
||||
chan_set(&th->chan[CHAN_NOSV_TYPE], next->type->gid);
|
||||
}
|
||||
|
||||
static void
|
||||
update_task_state(struct ovni_emu *emu)
|
||||
{
|
||||
if(ovni_payload_size(emu->cur_ev) < 4)
|
||||
die("missing task id in payload\n");
|
||||
|
||||
uint32_t task_id = emu->cur_ev->payload.u32[0];
|
||||
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
struct ovni_eproc *proc = emu->cur_proc;
|
||||
|
||||
struct task_info *info = &proc->nosv_task_info;
|
||||
struct task_stack *stack = &th->nosv_task_stack;
|
||||
|
||||
struct task *task = task_find(info->tasks, task_id);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %u\n", task_id);
|
||||
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'x': task_execute(stack, task); break;
|
||||
case 'e': task_end(stack, task); break;
|
||||
case 'p': task_pause(stack, task); break;
|
||||
case 'r': task_resume(stack, task); break;
|
||||
default:
|
||||
die("unexpected Nanos6 task event value %c\n",
|
||||
emu->cur_ev->header.value);
|
||||
}
|
||||
}
|
||||
|
||||
static char
|
||||
expand_transition_value(struct ovni_emu *emu, int was_running, int runs_now)
|
||||
{
|
||||
char tr = emu->cur_ev->header.value;
|
||||
|
||||
/* Ensure we don't clobber the value */
|
||||
if(tr == 'X' || tr == 'E')
|
||||
die("unexpected event value %c\n", tr);
|
||||
|
||||
/* Modify the event value to detect nested transitions */
|
||||
if(tr == 'x' && was_running)
|
||||
tr = 'X'; /* Execute a new nested task */
|
||||
else if(tr == 'e' && runs_now)
|
||||
tr = 'E'; /* End a nested task */
|
||||
|
||||
return tr;
|
||||
}
|
||||
|
||||
static void
|
||||
update_task_channels(struct ovni_emu *emu,
|
||||
char tr, struct task *prev, struct task *next)
|
||||
{
|
||||
switch(tr)
|
||||
{
|
||||
case 'x': chan_task_running(emu, next); break;
|
||||
case 'r': chan_task_running(emu, next); break;
|
||||
case 'e': chan_task_stopped(emu); break;
|
||||
case 'p': chan_task_stopped(emu); break;
|
||||
/* Additional nested transitions */
|
||||
case 'X': chan_task_switch(emu, prev, next); break;
|
||||
case 'E': chan_task_switch(emu, prev, next); break;
|
||||
default:
|
||||
die("unexpected transition value %c\n", tr);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
update_task(struct ovni_emu *emu)
|
||||
{
|
||||
struct ovni_ethread *th = emu->cur_thread;
|
||||
struct task_stack *stack = &th->nosv_task_stack;
|
||||
|
||||
struct task *prev = task_get_running(stack);
|
||||
|
||||
/* Update the emulator state, but don't modify the channels */
|
||||
update_task_state(emu);
|
||||
|
||||
struct task *next = task_get_running(stack);
|
||||
|
||||
int was_running = (prev != NULL);
|
||||
int runs_now = (next != NULL);
|
||||
char tr = expand_transition_value(emu, was_running, runs_now);
|
||||
|
||||
/* Update the channels now */
|
||||
update_task_channels(emu, tr, prev, next);
|
||||
}
|
||||
|
||||
static void
|
||||
create_task(struct ovni_emu *emu)
|
||||
{
|
||||
if(ovni_payload_size(emu->cur_ev) != 8)
|
||||
die("cannot create task: unexpected payload size\n");
|
||||
|
||||
uint32_t task_id = emu->cur_ev->payload.u32[0];
|
||||
uint32_t type_id = emu->cur_ev->payload.u32[1];
|
||||
|
||||
struct task_info *info = &emu->cur_proc->nosv_task_info;
|
||||
|
||||
task_create(info, type_id, task_id);
|
||||
}
|
||||
|
||||
static void
|
||||
pre_task(struct ovni_emu *emu)
|
||||
{
|
||||
struct task **task_map = &emu->cur_proc->nosv_tasks;
|
||||
struct task_type **type_map = &emu->cur_proc->nosv_types;
|
||||
struct task **task_stack = &emu->cur_thread->nosv_task_stack;
|
||||
struct task *prev_running = task_get_running(*task_stack);
|
||||
int was_running_task = (prev_running != NULL);
|
||||
|
||||
/* Update the emulator state, but don't modify the channels yet */
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'c': task_create(emu->cur_ev->payload.i32[0], emu->cur_ev->payload.i32[1], task_map, type_map); break;
|
||||
case 'x': task_execute(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'e': task_end(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'p': task_pause(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
case 'r': task_resume(emu->cur_ev->payload.i32[0], emu->cur_thread, task_map, task_stack); break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
struct task *next_running = task_get_running(*task_stack);
|
||||
int runs_task_now = (next_running != NULL);
|
||||
|
||||
/* Now that we know if the emulator was running a task before
|
||||
* or if it's running one now, update the channels accordingly. */
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'x': /* Execute: either a nested task or a new one */
|
||||
if(was_running_task)
|
||||
task_switch(emu, prev_running, next_running, 1);
|
||||
else
|
||||
task_running(emu, next_running);
|
||||
case 'c':
|
||||
create_task(emu);
|
||||
break;
|
||||
case 'e': /* End: either a nested task or the last one */
|
||||
if(runs_task_now)
|
||||
task_switch(emu, prev_running, next_running, 0);
|
||||
else
|
||||
task_not_running(emu, prev_running);
|
||||
break;
|
||||
case 'p': /* Pause */
|
||||
task_not_running(emu, prev_running);
|
||||
break;
|
||||
case 'r': /* Resume */
|
||||
task_running(emu, next_running);
|
||||
case 'x':
|
||||
case 'e':
|
||||
case 'r':
|
||||
case 'p': /* Wet floor */
|
||||
update_task(emu);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
die("unexpected event value %c\n",
|
||||
emu->cur_ev->header.value);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
pre_type(struct ovni_emu *emu)
|
||||
{
|
||||
uint8_t *data;
|
||||
if(emu->cur_ev->header.value != 'c')
|
||||
die("unexpected event value %c\n",
|
||||
emu->cur_ev->header.value);
|
||||
|
||||
switch(emu->cur_ev->header.value)
|
||||
{
|
||||
case 'c':
|
||||
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
|
||||
{
|
||||
err("expecting a jumbo event\n");
|
||||
abort();
|
||||
}
|
||||
if((emu->cur_ev->header.flags & OVNI_EV_JUMBO) == 0)
|
||||
die("expecting a jumbo event\n");
|
||||
|
||||
data = &emu->cur_ev->payload.jumbo.data[0];
|
||||
uint32_t *typeid = (uint32_t *) data;
|
||||
data += sizeof(*typeid);
|
||||
const char *label = (const char *) data;
|
||||
task_type_create(*typeid, label, &emu->cur_proc->nosv_types);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
uint8_t *data = &emu->cur_ev->payload.jumbo.data[0];
|
||||
uint32_t typeid = *(uint32_t *) data;
|
||||
data += 4;
|
||||
|
||||
const char *label = (const char *) data;
|
||||
|
||||
struct ovni_eproc *proc = emu->cur_proc;
|
||||
|
||||
task_type_create(&proc->nosv_task_info, typeid, label);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -437,7 +497,7 @@ hook_end_nosv(struct ovni_emu *emu)
|
||||
for(size_t j = 0; j < loom->nprocs; j++)
|
||||
{
|
||||
struct ovni_eproc *proc = &loom->proc[j];
|
||||
task_create_pcf_types(pcftype, proc->nosv_types);
|
||||
task_create_pcf_types(pcftype, proc->nosv_task_info.types);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
146
emu_task.c
146
emu_task.c
@ -24,24 +24,39 @@
|
||||
#include "prv.h"
|
||||
#include "chan.h"
|
||||
|
||||
struct task *
|
||||
task_find(struct task *tasks, uint32_t task_id)
|
||||
{
|
||||
struct task *task = NULL;
|
||||
HASH_FIND_INT(tasks, &task_id, task);
|
||||
|
||||
return task;
|
||||
}
|
||||
|
||||
struct task_type *
|
||||
task_type_find(struct task_type *types, uint32_t type_id)
|
||||
{
|
||||
struct task_type *type = NULL;
|
||||
HASH_FIND_INT(types, &type_id, type);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
void
|
||||
task_create(uint32_t task_id, uint32_t type_id, struct task **task_map, struct task_type **type_map)
|
||||
task_create(struct task_info *info,
|
||||
uint32_t type_id, uint32_t task_id)
|
||||
{
|
||||
/* Ensure the task id is new */
|
||||
struct task *task = NULL;
|
||||
HASH_FIND_INT(*task_map, &task_id, task);
|
||||
|
||||
if(task != NULL)
|
||||
die("cannot create a task with id %u: already exists\n", task_id);
|
||||
if(task_find(info->tasks, task_id) != NULL)
|
||||
die("cannot create task: task_id %u already exists\n",
|
||||
task_id);
|
||||
|
||||
/* Ensure the type exists */
|
||||
struct task_type *type = NULL;
|
||||
HASH_FIND_INT(*type_map, &type_id, type);
|
||||
|
||||
struct task_type *type = task_type_find(info->types, type_id);
|
||||
if(type == NULL)
|
||||
die("cannot create task: unknown type id %u\n", type_id);
|
||||
|
||||
task = calloc(1, sizeof(*task));
|
||||
struct task *task = calloc(1, sizeof(struct task));
|
||||
|
||||
if(task == NULL)
|
||||
die("calloc failed\n");
|
||||
@ -52,64 +67,59 @@ task_create(uint32_t task_id, uint32_t type_id, struct task **task_map, struct t
|
||||
task->thread = NULL;
|
||||
|
||||
/* Add the new task to the hash table */
|
||||
HASH_ADD_INT(*task_map, id, task);
|
||||
HASH_ADD_INT(info->tasks, id, task);
|
||||
|
||||
dbg("new task created id=%d\n", task->id);
|
||||
}
|
||||
|
||||
void
|
||||
task_execute(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack)
|
||||
task_execute(struct task_stack *stack, struct task *task)
|
||||
{
|
||||
struct task *top = *thread_task_stack;
|
||||
struct task *task = NULL;
|
||||
HASH_FIND_INT(*task_map, &task_id, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %u\n", task_id);
|
||||
die("cannot execute: task is NULL\n");
|
||||
|
||||
if(task->state != TASK_ST_CREATED)
|
||||
die("cannot execute task %u: state is not created\n", task_id);
|
||||
die("cannot execute task %u: state is not created\n", task->id);
|
||||
|
||||
if(task->thread != NULL)
|
||||
die("task already has a thread assigned\n");
|
||||
|
||||
if(cur_thread->state != TH_ST_RUNNING)
|
||||
if(stack->thread->state != TH_ST_RUNNING)
|
||||
die("thread state is not running\n");
|
||||
|
||||
if(top == task)
|
||||
die("thread already has assigned task %u\n", task_id);
|
||||
if(stack->top == task)
|
||||
die("thread already has assigned task %u\n", task->id);
|
||||
|
||||
if(top && top->state != TASK_ST_RUNNING)
|
||||
if(stack->top && stack->top->state != TASK_ST_RUNNING)
|
||||
die("cannot execute a nested task from a non-running task\n");
|
||||
|
||||
task->state = TASK_ST_RUNNING;
|
||||
task->thread = cur_thread;
|
||||
task->thread = stack->thread;
|
||||
|
||||
DL_PREPEND(*thread_task_stack, task);
|
||||
DL_PREPEND(stack->tasks, task);
|
||||
|
||||
dbg("task id=%u runs now\n", task->id);
|
||||
}
|
||||
|
||||
void
|
||||
task_pause(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack)
|
||||
task_pause(struct task_stack *stack, struct task *task)
|
||||
{
|
||||
struct task *top = *thread_task_stack;
|
||||
struct task *task = NULL;
|
||||
HASH_FIND_INT(*task_map, &task_id, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %u\n", task_id);
|
||||
die("cannot pause: task is NULL\n");
|
||||
|
||||
if(task->state != TASK_ST_RUNNING)
|
||||
die("task state is not running\n");
|
||||
die("cannot pause: task state is not running\n");
|
||||
|
||||
if(cur_thread->state != TH_ST_RUNNING)
|
||||
die("thread state is not running\n");
|
||||
if(task->thread == NULL)
|
||||
die("cannot pause: task has no thread assigned\n");
|
||||
|
||||
if(top != task)
|
||||
if(stack->thread->state != TH_ST_RUNNING)
|
||||
die("cannot pause: thread state is not running\n");
|
||||
|
||||
if(stack->top != task)
|
||||
die("thread has assigned a different task\n");
|
||||
|
||||
if(cur_thread != task->thread)
|
||||
if(stack->thread != task->thread)
|
||||
die("task is assigned to a different thread\n");
|
||||
|
||||
task->state = TASK_ST_PAUSED;
|
||||
@ -118,25 +128,24 @@ task_pause(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task
|
||||
}
|
||||
|
||||
void
|
||||
task_resume(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack)
|
||||
task_resume(struct task_stack *stack, struct task *task)
|
||||
{
|
||||
struct task *top = *thread_task_stack;
|
||||
struct task *task = NULL;
|
||||
HASH_FIND_INT(*task_map, &task_id, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %u\n", task_id);
|
||||
die("cannot resume: task is NULL\n");
|
||||
|
||||
if(task->state != TASK_ST_PAUSED)
|
||||
die("task state is not paused\n");
|
||||
|
||||
if(cur_thread->state != TH_ST_RUNNING)
|
||||
if(task->thread == NULL)
|
||||
die("cannot resume: task has no thread assigned\n");
|
||||
|
||||
if(stack->thread->state != TH_ST_RUNNING)
|
||||
die("thread is not running\n");
|
||||
|
||||
if(top != task)
|
||||
if(stack->top != task)
|
||||
die("thread has assigned a different task\n");
|
||||
|
||||
if(cur_thread != task->thread)
|
||||
if(stack->thread != task->thread)
|
||||
die("task is assigned to a different thread\n");
|
||||
|
||||
task->state = TASK_ST_RUNNING;
|
||||
@ -145,25 +154,24 @@ task_resume(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **tas
|
||||
}
|
||||
|
||||
void
|
||||
task_end(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack)
|
||||
task_end(struct task_stack *stack, struct task *task)
|
||||
{
|
||||
struct task *top = *thread_task_stack;
|
||||
struct task *task = NULL;
|
||||
HASH_FIND_INT(*task_map, &task_id, task);
|
||||
|
||||
if(task == NULL)
|
||||
die("cannot find task with id %u\n", task_id);
|
||||
die("cannot end: task is NULL\n");
|
||||
|
||||
if(task->state != TASK_ST_RUNNING)
|
||||
die("task state is not running\n");
|
||||
|
||||
if(cur_thread->state != TH_ST_RUNNING)
|
||||
die("thread is not running\n");
|
||||
if(task->thread == NULL)
|
||||
die("cannot end: task has no thread assigned\n");
|
||||
|
||||
if(top != task)
|
||||
if(stack->thread->state != TH_ST_RUNNING)
|
||||
die("cannot end task: thread is not running\n");
|
||||
|
||||
if(stack->top != task)
|
||||
die("thread has assigned a different task\n");
|
||||
|
||||
if(cur_thread != task->thread)
|
||||
if(stack->thread != task->thread)
|
||||
die("task is assigned to a different thread\n");
|
||||
|
||||
task->state = TASK_ST_DEAD;
|
||||
@ -171,7 +179,7 @@ task_end(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_m
|
||||
/* Don't unset the thread from the task, as it will be used
|
||||
* later to ensure we switch to tasks of the same thread. */
|
||||
|
||||
DL_DELETE(*thread_task_stack, task);
|
||||
DL_DELETE(stack->tasks, task);
|
||||
|
||||
dbg("task id=%d ends\n", task->id);
|
||||
}
|
||||
@ -193,27 +201,21 @@ get_task_type_gid(const char *label)
|
||||
}
|
||||
|
||||
void
|
||||
task_type_create(uint32_t typeid, const char *label, struct task_type **type_map)
|
||||
task_type_create(struct task_info *info, uint32_t type_id, const char *label)
|
||||
{
|
||||
struct task_type *type;
|
||||
/* Ensure the type id is new */
|
||||
HASH_FIND_INT(*type_map, &typeid, type);
|
||||
HASH_FIND_INT(info->types, &type_id, type);
|
||||
|
||||
if(type != NULL)
|
||||
{
|
||||
err("A task type with id %d already exists\n", typeid);
|
||||
abort();
|
||||
}
|
||||
die("a task type with id %u already exists\n", type_id);
|
||||
|
||||
type = calloc(1, sizeof(*type));
|
||||
|
||||
if(type == NULL)
|
||||
{
|
||||
perror("calloc");
|
||||
abort();
|
||||
}
|
||||
die("calloc failed");
|
||||
|
||||
type->id = typeid;
|
||||
type->id = type_id;
|
||||
|
||||
if(type->id == 0)
|
||||
die("invalid task type id %d\n", type->id);
|
||||
@ -221,21 +223,21 @@ task_type_create(uint32_t typeid, const char *label, struct task_type **type_map
|
||||
type->gid = get_task_type_gid(label);
|
||||
int n = snprintf(type->label, MAX_PCF_LABEL, "%s", label);
|
||||
if(n >= MAX_PCF_LABEL)
|
||||
die("task label too long: %s\n", label);
|
||||
die("task type label too long: %s\n", label);
|
||||
|
||||
/* Add the new task type to the hash table */
|
||||
HASH_ADD_INT(*type_map, id, type);
|
||||
HASH_ADD_INT(info->types, id, type);
|
||||
|
||||
dbg("new task type created id=%d label=%s\n", type->id,
|
||||
type->label);
|
||||
}
|
||||
|
||||
void
|
||||
task_create_pcf_types(struct pcf_type *pcftype, struct task_type *type_map)
|
||||
task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types)
|
||||
{
|
||||
/* Emit types for all task types */
|
||||
struct task_type *tt;
|
||||
for(tt = type_map; tt != NULL; tt = tt->hh.next)
|
||||
for(tt = types; tt != NULL; tt = tt->hh.next)
|
||||
{
|
||||
struct pcf_value *pcfvalue = pcf_find_value(pcftype, tt->gid);
|
||||
if(pcfvalue != NULL)
|
||||
@ -253,9 +255,9 @@ task_create_pcf_types(struct pcf_type *pcftype, struct task_type *type_map)
|
||||
}
|
||||
|
||||
struct task *
|
||||
task_get_running(struct task *task_stack)
|
||||
task_get_running(struct task_stack *stack)
|
||||
{
|
||||
struct task *task = task_stack;
|
||||
struct task *task = stack->top;
|
||||
if(task && task->state == TASK_ST_RUNNING)
|
||||
return task;
|
||||
|
||||
|
21
emu_task.h
21
emu_task.h
@ -20,13 +20,18 @@
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
void task_create(uint32_t task_id, uint32_t type_id, struct task **task_map, struct task_type **type_map);
|
||||
void task_execute(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack);
|
||||
void task_pause(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack);
|
||||
void task_resume(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack);
|
||||
void task_end(uint32_t task_id, struct ovni_ethread *cur_thread, struct task **task_map, struct task **thread_task_stack);
|
||||
void task_type_create(uint32_t typeid, const char *label, struct task_type **type_map);
|
||||
void task_create_pcf_types(struct pcf_type *pcftype, struct task_type *type_map);
|
||||
struct task *task_get_running(struct task *task_stack);
|
||||
struct task *task_find(struct task *tasks, uint32_t task_id);
|
||||
|
||||
void task_create(struct task_info *info, uint32_t type_id, uint32_t task_id);
|
||||
void task_execute(struct task_stack *stack, struct task *task);
|
||||
void task_pause(struct task_stack *stack, struct task *task);
|
||||
void task_resume(struct task_stack *stack, struct task *task);
|
||||
void task_end(struct task_stack *stack, struct task *task);
|
||||
|
||||
struct task_type *task_type_find(struct task_type *types, uint32_t type_id);
|
||||
void task_type_create(struct task_info *info, uint32_t type_id, const char *label);
|
||||
|
||||
void task_create_pcf_types(struct pcf_type *pcftype, struct task_type *types);
|
||||
struct task *task_get_running(struct task_stack *stack);
|
||||
|
||||
#endif /* OVNI_EMU_TASK_H */
|
||||
|
@ -11,13 +11,22 @@ let
|
||||
mpi = last.impi;
|
||||
#mpi = last.openmpi;
|
||||
|
||||
nanos6 = (prev.nanos6Git.override {
|
||||
gitUrl = "ssh://git@bscpm03.bsc.es/nanos6/forks/nanos6-extern-001.git";
|
||||
gitBranch = "ovni_instr";
|
||||
extrae = null;
|
||||
}).overrideAttrs (old: {
|
||||
#nanos6 = (prev.nanos6Git.override {
|
||||
# gitUrl = "ssh://git@bscpm03.bsc.es/nanos6/forks/nanos6-extern-001.git";
|
||||
# gitBranch = "ovni_instr";
|
||||
# extrae = null;
|
||||
#}).overrideAttrs (old: {
|
||||
# buildInputs = old.buildInputs ++ [ last.ovni ];
|
||||
# patches = [ ./0001-Emit-a-fill-event-at-shutdown.patch ];
|
||||
# configureFlags = old.configureFlags ++ [
|
||||
# "--with-ovni=${last.ovni}"
|
||||
# ];
|
||||
#});
|
||||
|
||||
nanos6 = prev.nanos6Git.overrideAttrs (old: {
|
||||
src = ~/bsc/nanos6;
|
||||
version = "local";
|
||||
buildInputs = old.buildInputs ++ [ last.ovni ];
|
||||
patches = [ ./0001-Emit-a-fill-event-at-shutdown.patch ];
|
||||
configureFlags = old.configureFlags ++ [
|
||||
"--with-ovni=${last.ovni}"
|
||||
];
|
||||
@ -30,7 +39,7 @@ let
|
||||
clangUnwrapped = prev.clangOmpss2Unwrapped.overrideAttrs (
|
||||
old:
|
||||
rec {
|
||||
src = ../kk/llvm-mono-d3d4f2bf231b9461a5881c5bf56659516d45e670.tar.bz2;
|
||||
src = ../../ovni-misc/kk2/llvm-mono-d3d4f2bf231b9461a5881c5bf56659516d45e670.tar.bz2;
|
||||
#src = fetchTarball {
|
||||
# url = ../kk/llvm-mono-d3d4f2bf231b9461a5881c5bf56659516d45e670.tar.bz2;
|
||||
#};
|
||||
@ -89,5 +98,5 @@ let
|
||||
});
|
||||
|
||||
in
|
||||
bsc.ovni-rt
|
||||
#bsc.ompss2.clang
|
||||
#bsc.ovni-rt
|
||||
bsc.ompss2.clang
|
||||
|
16
ovni.c
16
ovni.c
@ -54,7 +54,7 @@ create_trace_stream(void)
|
||||
int written = snprintf(path, PATH_MAX, "%s/thread.%d",
|
||||
rproc.procdir, rthread.tid);
|
||||
|
||||
if(written >= PATH_MAX)
|
||||
if(written >= PATH_MAX)
|
||||
die("thread trace path too long: %s/thread.%d\n",
|
||||
rproc.procdir, rthread.tid);
|
||||
|
||||
@ -80,7 +80,7 @@ proc_metadata_store(JSON_Value *meta, const char *procdir)
|
||||
|
||||
if(meta == NULL)
|
||||
die("process metadata not initialized\n");
|
||||
|
||||
|
||||
if(snprintf(path, PATH_MAX, "%s/metadata.json", procdir) >= PATH_MAX)
|
||||
die("metadata path too long: %s/metadata.json\n",
|
||||
procdir);
|
||||
@ -111,7 +111,7 @@ ovni_add_cpu(int index, int phyid)
|
||||
|
||||
int first_time = 0;
|
||||
|
||||
/* Find the CPU array and create it if needed */
|
||||
/* Find the CPU array and create it if needed */
|
||||
JSON_Array *cpuarray = json_object_dotget_array(meta, "cpus");
|
||||
|
||||
if(cpuarray == NULL)
|
||||
@ -289,7 +289,7 @@ move_thread_to_final(const char *src, const char *dst)
|
||||
}
|
||||
|
||||
while((bytes = fread(buffer, 1, sizeof(buffer), infile)) > 0)
|
||||
fwrite(buffer, 1, bytes, outfile);
|
||||
fwrite(buffer, 1, bytes, outfile);
|
||||
|
||||
fclose(outfile);
|
||||
fclose(infile);
|
||||
@ -466,11 +466,11 @@ ovni_thread_isready(void)
|
||||
static inline
|
||||
uint64_t clock_tsc_now(void)
|
||||
{
|
||||
uint32_t lo, hi;
|
||||
uint32_t lo, hi;
|
||||
|
||||
/* RDTSC copies contents of 64-bit TSC into EDX:EAX */
|
||||
__asm__ volatile("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
return (uint64_t) hi << 32 | lo;
|
||||
/* RDTSC copies contents of 64-bit TSC into EDX:EAX */
|
||||
__asm__ volatile("rdtsc" : "=a" (lo), "=d" (hi));
|
||||
return (uint64_t) hi << 32 | lo;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
27
pcf.c
27
pcf.c
@ -81,12 +81,6 @@ const uint32_t pcf_def_palette[] = {
|
||||
const uint32_t *pcf_palette = pcf_def_palette;
|
||||
const int pcf_palette_len = ARRAY_LEN(pcf_def_palette);
|
||||
|
||||
/* Only used to generate tables */
|
||||
struct pcf_value_label {
|
||||
int value;
|
||||
char *label;
|
||||
};
|
||||
|
||||
/* ------------------ Value labels --------------------- */
|
||||
|
||||
struct pcf_value_label default_values[] = {
|
||||
@ -181,20 +175,19 @@ struct pcf_value_label kernel_cs_values[] = {
|
||||
struct pcf_value_label nanos6_ss_values[] = {
|
||||
{ ST_NULL, "No subsystem" },
|
||||
{ ST_TOO_MANY_TH, "Unknown: multiple threads running" },
|
||||
{ ST_NANOS6_TASK_RUNNING, "Task: Running" },
|
||||
{ ST_NANOS6_SPAWNING, "Task: Spawning function" },
|
||||
{ ST_NANOS6_CREATING, "Task: Creating" },
|
||||
{ ST_NANOS6_SUBMIT, "Task: Submitting" },
|
||||
{ ST_NANOS6_SCHED_HUNGRY, "Scheduler: Waiting for tasks" },
|
||||
{ ST_NANOS6_TASK_BODY, "Task: Running body" },
|
||||
{ ST_NANOS6_TASK_CREATING, "Task: Creating" },
|
||||
{ ST_NANOS6_TASK_SUBMIT, "Task: Submitting" },
|
||||
{ ST_NANOS6_TASK_SPAWNING, "Task: Spawning function" },
|
||||
{ ST_NANOS6_SCHED_HUNGRY, "Scheduler: Waiting for ready tasks" },
|
||||
{ ST_NANOS6_SCHED_SERVING, "Scheduler: Serving tasks" },
|
||||
{ ST_NANOS6_SCHED_SUBMITTING, "Scheduler: Adding ready tasks" },
|
||||
{ ST_NANOS6_ATTACHED, "Threading: Attached as external thread" },
|
||||
{ ST_NANOS6_SCHED_ADDING, "Scheduler: Adding ready tasks" },
|
||||
{ ST_NANOS6_DEP_REG, "Dependency: Registering" },
|
||||
{ ST_NANOS6_DEP_UNREG, "Dependency: Unregistering" },
|
||||
{ ST_NANOS6_TASKWAIT, "Blocking: Taskwait" },
|
||||
{ ST_NANOS6_BLOCKING, "Blocking: Blocking current task" },
|
||||
{ ST_NANOS6_UNBLOCKING, "Blocking: Unblocking remote task" },
|
||||
{ ST_NANOS6_WAITFOR, "Blocking: Wait For" },
|
||||
{ ST_NANOS6_BLK_TASKWAIT, "Blocking: Taskwait" },
|
||||
{ ST_NANOS6_BLK_BLOCKING, "Blocking: Blocking current task" },
|
||||
{ ST_NANOS6_BLK_UNBLOCKING, "Blocking: Unblocking remote task" },
|
||||
{ ST_NANOS6_BLK_WAITFOR, "Blocking: Wait For" },
|
||||
{ EV_NANOS6_SCHED_SEND, "EV Scheduler: Send task" },
|
||||
{ EV_NANOS6_SCHED_RECV, "EV Scheduler: Recv task" },
|
||||
{ EV_NANOS6_SCHED_SELF, "EV Scheduler: Self-assign task" },
|
||||
|
8
pcf.h
8
pcf.h
@ -50,6 +50,14 @@ struct pcf_file {
|
||||
struct pcf_type *types;
|
||||
};
|
||||
|
||||
/* Only used to generate tables */
|
||||
struct pcf_value_label {
|
||||
int value;
|
||||
char *label;
|
||||
};
|
||||
|
||||
extern struct pcf_value_label nanos6_ss_values[];
|
||||
|
||||
void pcf_open(struct pcf_file *pcf, char *path, int chantype);
|
||||
|
||||
void pcf_write(struct pcf_file *pcf);
|
||||
|
@ -21,4 +21,4 @@ ovni_test(task-types.c MP)
|
||||
ovni_test(blocking.c MP)
|
||||
ovni_test(subsystems.c MP)
|
||||
ovni_test(ss-mismatch.c SHOULD_FAIL
|
||||
REGEX "thread [0-9]\\+ ended with 1 extra stacked nanos6 subsystems, top=ST_NANOS6_SCHED_HUNGRY")
|
||||
REGEX "thread [0-9]\\+ ended with 1 extra stacked nanos6 subsystems, top=\"Scheduler: Waiting for ready tasks\"")
|
||||
|
@ -26,16 +26,19 @@ main(void)
|
||||
|
||||
int us = 500;
|
||||
uint32_t typeid = 1;
|
||||
uint32_t taskid = 1;
|
||||
|
||||
instr_nanos6_type_create(typeid);
|
||||
|
||||
instr_nanos6_task_create_and_execute(1, typeid);
|
||||
instr_nanos6_task_create_and_execute(taskid, typeid);
|
||||
usleep(us);
|
||||
instr_nanos6_block_enter(1);
|
||||
instr_nanos6_block_enter();
|
||||
instr_nanos6_task_pause(taskid);
|
||||
usleep(us);
|
||||
instr_nanos6_block_exit(1);
|
||||
instr_nanos6_task_resume(taskid);
|
||||
instr_nanos6_block_exit();
|
||||
usleep(us);
|
||||
instr_nanos6_task_end(1);
|
||||
instr_nanos6_task_end(taskid);
|
||||
|
||||
instr_end();
|
||||
|
||||
|
@ -45,6 +45,9 @@ instr_nanos6_type_create(int32_t typeid)
|
||||
INSTR_2ARG(instr_nanos6_task_create, "6Tc", int32_t, id, uint32_t, typeid)
|
||||
INSTR_0ARG(instr_nanos6_task_create_end, "6TC")
|
||||
INSTR_1ARG(instr_nanos6_task_execute, "6Tx", int32_t, id)
|
||||
INSTR_1ARG(instr_nanos6_task_pause, "6Tp", int32_t, id)
|
||||
INSTR_1ARG(instr_nanos6_task_resume, "6Tr", int32_t, id)
|
||||
INSTR_1ARG(instr_nanos6_task_end, "6Te", int32_t, id)
|
||||
|
||||
static inline void
|
||||
instr_nanos6_task_create_and_execute(int32_t id, uint32_t typeid)
|
||||
@ -54,46 +57,14 @@ instr_nanos6_task_create_and_execute(int32_t id, uint32_t typeid)
|
||||
instr_nanos6_task_execute(id);
|
||||
}
|
||||
|
||||
INSTR_2ARG(instr_nanos6_task_block, "6Tb", int32_t, id, int32_t, reason)
|
||||
INSTR_2ARG(instr_nanos6_task_unblock, "6Tu", int32_t, id, int32_t, reason)
|
||||
|
||||
static inline void
|
||||
instr_nanos6_block_enter(int32_t id)
|
||||
{
|
||||
instr_nanos6_task_block(id, 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_nanos6_block_exit(int32_t id)
|
||||
{
|
||||
instr_nanos6_task_unblock(id, 0);
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_nanos6_task_wait_enter(int32_t id)
|
||||
{
|
||||
instr_nanos6_task_block(id, 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_nanos6_task_wait_exit(int32_t id)
|
||||
{
|
||||
instr_nanos6_task_unblock(id, 1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_nanos6_waitfor_enter(int32_t id)
|
||||
{
|
||||
instr_nanos6_task_block(id, 2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
instr_nanos6_waitfor_exit(int32_t id)
|
||||
{
|
||||
instr_nanos6_task_unblock(id, 2);
|
||||
}
|
||||
|
||||
INSTR_1ARG(instr_nanos6_task_end, "6Te", int32_t, id)
|
||||
INSTR_0ARG(instr_nanos6_block_enter, "6Bb")
|
||||
INSTR_0ARG(instr_nanos6_block_exit, "6BB")
|
||||
INSTR_0ARG(instr_nanos6_unblock_enter, "6Bb")
|
||||
INSTR_0ARG(instr_nanos6_unblock_exit, "6BB")
|
||||
INSTR_0ARG(instr_nanos6_taskwait_enter, "6Bw")
|
||||
INSTR_0ARG(instr_nanos6_taskwait_exit, "6BW")
|
||||
INSTR_0ARG(instr_nanos6_waitfor_enter, "6Bf")
|
||||
INSTR_0ARG(instr_nanos6_waitfor_exit, "6BF")
|
||||
|
||||
INSTR_0ARG(instr_nanos6_sched_receive_task, "6Sr")
|
||||
INSTR_0ARG(instr_nanos6_sched_assign_task, "6Ss")
|
||||
|
@ -43,16 +43,16 @@ main(void)
|
||||
instr_nanos6_sched_submit_exit(); usleep(us);
|
||||
instr_nanos6_enter_submit_task(); usleep(us);
|
||||
instr_nanos6_exit_submit_task(); usleep(us);
|
||||
instr_nanos6_block_enter(taskid); usleep(us);
|
||||
instr_nanos6_block_exit(taskid); usleep(us);
|
||||
instr_nanos6_waitfor_enter(taskid); usleep(us);
|
||||
instr_nanos6_waitfor_exit(taskid); usleep(us);
|
||||
instr_nanos6_block_enter(); usleep(us);
|
||||
instr_nanos6_block_exit(); usleep(us);
|
||||
instr_nanos6_waitfor_enter(); usleep(us);
|
||||
instr_nanos6_waitfor_exit(); usleep(us);
|
||||
instr_nanos6_register_accesses_enter(); usleep(us);
|
||||
instr_nanos6_register_accesses_exit(); usleep(us);
|
||||
instr_nanos6_unregister_accesses_enter(); usleep(us);
|
||||
instr_nanos6_unregister_accesses_exit(); usleep(us);
|
||||
instr_nanos6_task_wait_enter(taskid); usleep(us);
|
||||
instr_nanos6_task_wait_exit(taskid); usleep(us);
|
||||
instr_nanos6_taskwait_enter(); usleep(us);
|
||||
instr_nanos6_taskwait_exit(); usleep(us);
|
||||
instr_nanos6_spawn_function_enter(); usleep(us);
|
||||
instr_nanos6_spawn_function_exit(); usleep(us);
|
||||
|
||||
|
3
test/rt/nanos6/external-thread.c
Normal file
3
test/rt/nanos6/external-thread.c
Normal file
@ -0,0 +1,3 @@
|
||||
/* Create a test which unblocks a task from an external thread. This
|
||||
* should break currently, as the instrumentation attempts to call
|
||||
* ovni_ev_emit from a thread without initialization. */
|
Loading…
Reference in New Issue
Block a user