Use only a stack of tasks for nosv

The running task is inferred from the task on top of the stack. Also,
allow a nested task to execute when there are others in the stack.
This commit is contained in:
Rodrigo Arias 2022-05-30 19:27:59 +02:00
parent 26a29d3eda
commit 70891355ec
2 changed files with 24 additions and 23 deletions

6
emu.h
View File

@ -286,10 +286,8 @@ struct ovni_ethread {
/* FIXME: Use a table with registrable pointers to custom data /* FIXME: Use a table with registrable pointers to custom data
* structures */ * structures */
/* nosv task */ /* nOS-V stack of tasks: points to the runnable task. */
struct nosv_task *task; struct nosv_task *task_stack;
/* nosv effective task, which is what is currently executing */
struct nosv_task *running_task;
/* Channels are used to output the emulator state in PRV */ /* Channels are used to output the emulator state in PRV */
struct ovni_chan chan[CHAN_MAX]; struct ovni_chan chan[CHAN_MAX];

View File

@ -113,9 +113,10 @@ pre_task_create(struct ovni_emu *emu)
static void static void
pre_task_execute(struct ovni_emu *emu) pre_task_execute(struct ovni_emu *emu)
{ {
struct nosv_task *task; struct nosv_task *task, *top;
int taskid; int taskid;
top = emu->cur_thread->task_stack;
taskid = emu->cur_ev->payload.i32[0]; taskid = emu->cur_ev->payload.i32[0];
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task); HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
@ -132,13 +133,16 @@ pre_task_execute(struct ovni_emu *emu)
if(emu->cur_thread->state != TH_ST_RUNNING) if(emu->cur_thread->state != TH_ST_RUNNING)
die("thread state is not running\n"); die("thread state is not running\n");
if(emu->cur_thread->task != NULL) if(top == task)
die("thread already has a task\n"); die("thread already has assigned task %d\n", taskid);
if(top && top->state != TASK_ST_RUNNING)
die("cannot execute a nested task from a non-running task\n");
task->state = TASK_ST_RUNNING; task->state = TASK_ST_RUNNING;
task->thread = emu->cur_thread; task->thread = emu->cur_thread;
DL_PREPEND(emu->cur_thread->task, task);
emu->cur_thread->running_task = task; DL_PREPEND(emu->cur_thread->task_stack, task);
dbg("task id=%d runs now\n", task->id); dbg("task id=%d runs now\n", task->id);
} }
@ -146,9 +150,10 @@ pre_task_execute(struct ovni_emu *emu)
static void static void
pre_task_pause(struct ovni_emu *emu) pre_task_pause(struct ovni_emu *emu)
{ {
struct nosv_task *task; struct nosv_task *task, *top;
int taskid; int taskid;
top = emu->cur_thread->task_stack;
taskid = emu->cur_ev->payload.i32[0]; taskid = emu->cur_ev->payload.i32[0];
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task); HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
@ -162,14 +167,12 @@ pre_task_pause(struct ovni_emu *emu)
if(emu->cur_thread->state != TH_ST_RUNNING) if(emu->cur_thread->state != TH_ST_RUNNING)
die("thread state is not running\n"); die("thread state is not running\n");
if(emu->cur_thread->task != task) if(top != task)
die("thread has assigned a different task\n"); die("thread has assigned a different task\n");
if(emu->cur_thread != task->thread) if(emu->cur_thread != task->thread)
die("task is assigned to a different thread\n"); die("task is assigned to a different thread\n");
emu->cur_thread->running_task = NULL;
task->state = TASK_ST_PAUSED; task->state = TASK_ST_PAUSED;
dbg("task id=%d pauses\n", task->id); dbg("task id=%d pauses\n", task->id);
@ -178,9 +181,10 @@ pre_task_pause(struct ovni_emu *emu)
static void static void
pre_task_resume(struct ovni_emu *emu) pre_task_resume(struct ovni_emu *emu)
{ {
struct nosv_task *task; struct nosv_task *task, *top;
int taskid; int taskid;
top = emu->cur_thread->task_stack;
taskid = emu->cur_ev->payload.i32[0]; taskid = emu->cur_ev->payload.i32[0];
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task); HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
@ -194,14 +198,12 @@ pre_task_resume(struct ovni_emu *emu)
if(emu->cur_thread->state != TH_ST_RUNNING) if(emu->cur_thread->state != TH_ST_RUNNING)
die("thread is not running\n"); die("thread is not running\n");
if(emu->cur_thread->task != task) if(top != task)
die("thread has assigned a different task\n"); die("thread has assigned a different task\n");
if(emu->cur_thread != task->thread) if(emu->cur_thread != task->thread)
die("task is assigned to a different thread\n"); die("task is assigned to a different thread\n");
emu->cur_thread->running_task = task;
task->state = TASK_ST_RUNNING; task->state = TASK_ST_RUNNING;
dbg("task id=%d resumes\n", task->id); dbg("task id=%d resumes\n", task->id);
@ -211,9 +213,10 @@ pre_task_resume(struct ovni_emu *emu)
static void static void
pre_task_end(struct ovni_emu *emu) pre_task_end(struct ovni_emu *emu)
{ {
struct nosv_task *task; struct nosv_task *task, *top;
int taskid; int taskid;
top = emu->cur_thread->task_stack;
taskid = emu->cur_ev->payload.i32[0]; taskid = emu->cur_ev->payload.i32[0];
HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task); HASH_FIND_INT(emu->cur_proc->tasks, &taskid, task);
@ -227,7 +230,7 @@ pre_task_end(struct ovni_emu *emu)
if(emu->cur_thread->state != TH_ST_RUNNING) if(emu->cur_thread->state != TH_ST_RUNNING)
die("thread is not running\n"); die("thread is not running\n");
if(emu->cur_thread->task != task) if(top != task)
die("thread has assigned a different task\n"); die("thread has assigned a different task\n");
if(emu->cur_thread != task->thread) if(emu->cur_thread != task->thread)
@ -235,8 +238,8 @@ pre_task_end(struct ovni_emu *emu)
task->state = TASK_ST_DEAD; task->state = TASK_ST_DEAD;
task->thread = NULL; task->thread = NULL;
DL_DELETE(emu->cur_thread->task, task);
emu->cur_thread->running_task = emu->cur_thread->task; DL_DELETE(emu->cur_thread->task_stack, task);
dbg("task id=%d ends\n", task->id); dbg("task id=%d ends\n", task->id);
} }
@ -320,7 +323,7 @@ pre_task(struct ovni_emu *emu)
{ {
struct nosv_task *prev_task, *next_task; struct nosv_task *prev_task, *next_task;
prev_task = emu->cur_thread->running_task; prev_task = emu->cur_thread->task_stack;
switch(emu->cur_ev->header.value) switch(emu->cur_ev->header.value)
{ {
@ -333,7 +336,7 @@ pre_task(struct ovni_emu *emu)
abort(); abort();
} }
next_task = emu->cur_thread->running_task; next_task = emu->cur_thread->task_stack;
/* Unless we're creating a task, register the switch */ /* Unless we're creating a task, register the switch */
if(emu->cur_ev->header.value != 'c') if(emu->cur_ev->header.value != 'c')