Support for nested tasks

This commit is contained in:
David Alvarez 2021-12-07 18:56:05 +01:00 committed by Rodrigo Arias
parent ce9a68fc7e
commit a8b1256375
4 changed files with 55 additions and 45 deletions

7
chan.c
View File

@ -209,13 +209,6 @@ chan_set(struct ovni_chan *chan, int st)
}
}
void
chan_enable_and_set(struct ovni_chan *chan, int st)
{
chan_enable(chan, 1);
chan_set(chan, st);
}
void
chan_push(struct ovni_chan *chan, int st)
{

3
chan.h
View File

@ -56,9 +56,6 @@ chan_is_enabled(struct ovni_chan *chan);
void
chan_set(struct ovni_chan *chan, int st);
void
chan_enable_and_set(struct ovni_chan *chan, int st);
void
chan_push(struct ovni_chan *chan, int st);

6
emu.h
View File

@ -112,6 +112,10 @@ struct nosv_task {
struct ovni_ethread *thread;
enum nosv_task_state state;
UT_hash_handle hh;
/* List handle for nested task support */
struct nosv_task *next;
struct nosv_task *prev;
};
struct nosv_task_type {
@ -284,6 +288,8 @@ struct ovni_ethread {
/* nosv task */
struct nosv_task *task;
/* nosv effective task, which is what is currently executing */
struct nosv_task *running_task;
/* Channels are used to output the emulator state in PRV */
struct ovni_chan chan[CHAN_MAX];

View File

@ -16,6 +16,7 @@
*/
#include "uthash.h"
#include "utlist.h"
#include "ovni.h"
#include "emu.h"
@ -80,7 +81,7 @@ static void
pre_task_create(struct ovni_emu *emu)
{
struct nosv_task *task, *p = NULL;
task = calloc(1, sizeof(*task));
if(task == NULL)
@ -106,8 +107,6 @@ pre_task_create(struct ovni_emu *emu)
/* Add the new task to the hash table */
HASH_ADD_INT(emu->cur_proc->tasks, id, task);
emu->cur_task = task;
dbg("new task created id=%d\n", task->id);
}
@ -138,9 +137,8 @@ pre_task_execute(struct ovni_emu *emu)
task->state = TASK_ST_RUNNING;
task->thread = emu->cur_thread;
emu->cur_thread->task = task;
emu->cur_task = task;
DL_PREPEND(emu->cur_thread->task, task);
emu->cur_thread->running_task = task;
dbg("task id=%d runs now\n", task->id);
}
@ -170,9 +168,9 @@ pre_task_pause(struct ovni_emu *emu)
if(emu->cur_thread != task->thread)
die("task is assigned to a different thread\n");
task->state = TASK_ST_PAUSED;
emu->cur_thread->running_task = NULL;
emu->cur_task = task;
task->state = TASK_ST_PAUSED;
dbg("task id=%d pauses\n", task->id);
}
@ -202,9 +200,9 @@ pre_task_resume(struct ovni_emu *emu)
if(emu->cur_thread != task->thread)
die("task is assigned to a different thread\n");
task->state = TASK_ST_RUNNING;
emu->cur_thread->running_task = task;
emu->cur_task = task;
task->state = TASK_ST_RUNNING;
dbg("task id=%d resumes\n", task->id);
}
@ -237,13 +235,25 @@ pre_task_end(struct ovni_emu *emu)
task->state = TASK_ST_DEAD;
task->thread = NULL;
emu->cur_thread->task = NULL;
emu->cur_task = task;
DL_DELETE(emu->cur_thread->task, task);
emu->cur_thread->running_task = emu->cur_thread->task;
dbg("task id=%d ends\n", task->id);
}
static void
pre_task_not_running(struct ovni_emu *emu)
{
struct ovni_ethread *th;
th = emu->cur_thread;
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_NOSV_TASK_RUNNING);
}
static void
pre_task_running(struct ovni_emu *emu, struct nosv_task *task)
{
@ -273,28 +283,35 @@ pre_task_running(struct ovni_emu *emu, struct nosv_task *task)
}
static void
pre_task_not_running(struct ovni_emu *emu)
pre_task_switch(struct ovni_emu *emu, struct nosv_task *prev_task, struct nosv_task *next_task)
{
struct ovni_ethread *th;
struct ovni_eproc *proc;
assert(prev_task);
assert(next_task);
assert(prev_task != next_task);
th = emu->cur_thread;
proc = emu->cur_proc;
chan_set(&th->chan[CHAN_NOSV_TASKID], 0);
chan_set(&th->chan[CHAN_NOSV_TYPEID], 0);
chan_set(&th->chan[CHAN_NOSV_APPID], 0);
assert(next_task->id > 0);
assert(next_task->type_id > 0);
assert(proc->appid > 0);
if(emu->cur_loom->rank_enabled)
chan_set(&th->chan[CHAN_NOSV_RANK], 0);
chan_set(&th->chan[CHAN_NOSV_TASKID], next_task->id);
chan_pop(&th->chan[CHAN_NOSV_SUBSYSTEM], ST_NOSV_TASK_RUNNING);
if (prev_task->type_id != next_task->type_id)
chan_set(&th->chan[CHAN_NOSV_TYPEID], next_task->type_id);
}
static void
pre_task(struct ovni_emu *emu)
{
struct nosv_task *task;
struct nosv_task *prev_task, *next_task;
task = emu->cur_task;
assert(emu->cur_thread);
prev_task = emu->cur_thread->running_task;
switch(emu->cur_ev->header.value)
{
@ -307,19 +324,16 @@ pre_task(struct ovni_emu *emu)
abort();
}
switch(emu->cur_ev->header.value)
{
case 'x':
case 'r':
pre_task_running(emu, task);
break;
case 'p':
case 'e':
next_task = emu->cur_thread->running_task;
// Unless we're creating a task, register the switch
if (emu->cur_ev->header.value != 'c') {
if(!next_task)
pre_task_not_running(emu);
break;
case 'c':
default:
break;
else if(!prev_task)
pre_task_running(emu, next_task);
else
pre_task_switch(emu, prev_task, next_task);
}
}
@ -350,7 +364,7 @@ pre_type_create(struct ovni_emu *emu)
err("A task type with id %d already exists\n", *typeid);
abort();
}
type = calloc(1, sizeof(*type));
if(type == NULL)