Port nOS-V model to task bodies

The nOS-V events are modified in two ways: 1) to create a parallel task
the new VTC event must be used and 2) all task events for both normal
(VTc) and parallel (VTC) tasks require an extra argument in the payload
to indicate the body id. As a consequence, the nOS-V model version is
now increased to 2.0.0.

Additionally, all the channel PRV flags are set to PRV_SKIPDUPNULL, so
duplicates are only emitted if they are not null. It solves the problem
when a task switches to another task with the same body id.

A new Paraver configuration is added for the body id.
This commit is contained in:
Rodrigo Arias 2023-10-23 11:59:45 +02:00 committed by Rodrigo Arias
parent 27a23f25ca
commit 815633221d
13 changed files with 485 additions and 59 deletions

View File

@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
### Added
- Add new body model to support parallel tasks in nOS-V (used in taskfor).
- Add the ability to restrict transitions in the task model states.
- Add nOS-V support for parallel tasks reading the body id from the
event payload.
### Changed ### Changed
- The task model now requires the previous task body to be paused before nesting - The task model now requires the previous task body to be paused before nesting

42
cfg/cpu/nosv/body-id.cfg Normal file
View File

@ -0,0 +1,42 @@
#ParaverCFG
ConfigFile.Version: 3.4
ConfigFile.NumWindows: 1
################################################################################
< NEW DISPLAYING WINDOW CPU: nOS-V task body ID of the RUNNING thread >
################################################################################
window_name CPU: nOS-V task body ID of the RUNNING thread
window_type single
window_id 1
window_position_x 0
window_position_y 0
window_width 600
window_height 150
window_comm_lines_enabled true
window_flags_enabled false
window_noncolor_mode true
window_color_mode window_in_null_gradient_mode
window_logical_filtered true
window_physical_filtered false
window_comm_fromto true
window_comm_tagsize true
window_comm_typeval true
window_units Microseconds
window_maximum_y 1000.0
window_minimum_y 1.0
window_compute_y_max true
window_level thread
window_scale_relative 1.000000000000
window_end_time_relative 1.000000000000
window_object appl { 1, { All } }
window_begin_time_relative 0.000000000000
window_open true
window_drawmode draw_randnotzero
window_drawmode_rows draw_randnotzero
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 15
window_filter_module evt_type_label 1 "CPU: nOS-V task body ID of the RUNNING thread"

View File

@ -0,0 +1,42 @@
#ParaverCFG
ConfigFile.Version: 3.4
ConfigFile.NumWindows: 1
################################################################################
< NEW DISPLAYING WINDOW Thread: nOS-V task body ID of the RUNNING thread >
################################################################################
window_name Thread: nOS-V task body ID of the RUNNING thread
window_type single
window_id 1
window_position_x 0
window_position_y 0
window_width 600
window_height 150
window_comm_lines_enabled true
window_flags_enabled false
window_noncolor_mode true
window_color_mode window_in_null_gradient_mode
window_logical_filtered true
window_physical_filtered false
window_comm_fromto true
window_comm_tagsize true
window_comm_typeval true
window_units Microseconds
window_maximum_y 1000.0
window_minimum_y 1.0
window_compute_y_max true
window_level thread
window_scale_relative 1.000000000000
window_end_time_relative 1.000000000000
window_object appl { 1, { All } }
window_begin_time_relative 0.000000000000
window_open true
window_drawmode draw_randnotzero
window_drawmode_rows draw_randnotzero
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 15
window_filter_module evt_type_label 1 "Thread: nOS-V task body ID of the RUNNING thread"

View File

@ -1,7 +1,7 @@
# Emulator events # Emulator events
This is a exhaustive list of the events recognized by the emulator. This is a exhaustive list of the events recognized by the emulator.
Built on Feb 15 2024. Built on Mar 13 2024.
## Model nanos6 ## Model nanos6
@ -615,18 +615,20 @@ List of events for the model *tampi* with identifier **`T`** at version `1.0.0`:
## Model nosv ## Model nosv
List of events for the model *nosv* with identifier **`V`** at version `1.1.0`: List of events for the model *nosv* with identifier **`V`** at version `2.0.0`:
<dl> <dl>
<dt><a id="VTc" href="#VTc"><pre>VTc(u32 taskid, u32 typeid)</pre></a></dt> <dt><a id="VTc" href="#VTc"><pre>VTc(u32 taskid, u32 typeid)</pre></a></dt>
<dd>creates task %{taskid} with type %{typeid}</dd> <dd>creates task %{taskid} with type %{typeid}</dd>
<dt><a id="VTx" href="#VTx"><pre>VTx(u32 taskid)</pre></a></dt> <dt><a id="VTC" href="#VTC"><pre>VTC(u32 taskid, u32 typeid)</pre></a></dt>
<dd>executes the task %{taskid}</dd> <dd>creates parallel task %{taskid} with type %{typeid}</dd>
<dt><a id="VTe" href="#VTe"><pre>VTe(u32 taskid)</pre></a></dt> <dt><a id="VTx" href="#VTx"><pre>VTx(u32 taskid, u32 bodyid)</pre></a></dt>
<dd>ends the task %{taskid}</dd> <dd>executes the task %{taskid} with bodyid %{bodyid}</dd>
<dt><a id="VTp" href="#VTp"><pre>VTp(u32 taskid)</pre></a></dt> <dt><a id="VTe" href="#VTe"><pre>VTe(u32 taskid, u32 bodyid)</pre></a></dt>
<dd>pauses the task %{taskid}</dd> <dd>ends the task %{taskid} with bodyid %{bodyid}</dd>
<dt><a id="VTr" href="#VTr"><pre>VTr(u32 taskid)</pre></a></dt> <dt><a id="VTp" href="#VTp"><pre>VTp(u32 taskid, u32 bodyid)</pre></a></dt>
<dd>resumes the task %{taskid}</dd> <dd>pauses the task %{taskid} with bodyid %{bodyid}</dd>
<dt><a id="VTr" href="#VTr"><pre>VTr(u32 taskid, u32 bodyid)</pre></a></dt>
<dd>resumes the task %{taskid} with bodyid %{bodyid}</dd>
<dt><a id="VYc" href="#VYc"><pre>VYc+(u32 typeid, str label)</pre></a></dt> <dt><a id="VYc" href="#VYc"><pre>VYc+(u32 typeid, str label)</pre></a></dt>
<dd>creates task type %{typeid} with label &quot;%{label}&quot;</dd> <dd>creates task type %{typeid} with label &quot;%{label}&quot;</dd>
<dt><a id="VSr" href="#VSr"><pre>VSr</pre></a></dt> <dt><a id="VSr" href="#VSr"><pre>VSr</pre></a></dt>

View File

@ -0,0 +1,9 @@
digraph {
graph [size="6!", ranksep="0.7", nodesep="1"];
Created -> Running;
Running -> Paused [label=BODY_FLAG_PAUSE];
Paused -> Running;
Running -> Dead;
Dead -> Running [label="BODY_FLAG_RESURRECT\niteration++"];
}

View File

@ -0,0 +1,69 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<!-- Generated by graphviz version 8.1.0 (0)
-->
<!-- Pages: 1 -->
<svg width="432pt" height="202pt"
viewBox="0.00 0.00 432.00 202.47" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(0.805048 0.805048) rotate(0) translate(4 247.5)">
<polygon fill="white" stroke="none" points="-4,4 -4,-247.5 532.61,-247.5 532.61,4 -4,4"/>
<!-- Created -->
<g id="node1" class="node">
<title>Created</title>
<ellipse fill="none" stroke="black" cx="246.61" cy="-225.5" rx="51.21" ry="18"/>
<text text-anchor="middle" x="246.61" y="-220.82" font-family="Times,serif" font-size="14.00">Created</text>
</g>
<!-- Running -->
<g id="node2" class="node">
<title>Running</title>
<ellipse fill="none" stroke="black" cx="246.61" cy="-138.5" rx="53.31" ry="18"/>
<text text-anchor="middle" x="246.61" y="-133.82" font-family="Times,serif" font-size="14.00">Running</text>
</g>
<!-- Created&#45;&gt;Running -->
<g id="edge1" class="edge">
<title>Created&#45;&gt;Running</title>
<path fill="none" stroke="black" d="M246.61,-207.3C246.61,-195.97 246.61,-180.86 246.61,-167.79"/>
<polygon fill="black" stroke="black" points="250.11,-167.97 246.61,-157.97 243.11,-167.97 250.11,-167.97"/>
</g>
<!-- Paused -->
<g id="node3" class="node">
<title>Paused</title>
<ellipse fill="none" stroke="black" cx="132.61" cy="-18" rx="47" ry="18"/>
<text text-anchor="middle" x="132.61" y="-13.32" font-family="Times,serif" font-size="14.00">Paused</text>
</g>
<!-- Running&#45;&gt;Paused -->
<g id="edge2" class="edge">
<title>Running&#45;&gt;Paused</title>
<path fill="none" stroke="black" d="M193.44,-135.87C130.26,-132.68 30.43,-123.26 7.11,-95.5 -2.75,-83.76 -1.84,-73.44 7.11,-61 22.79,-39.22 50.29,-28.57 75.56,-23.43"/>
<polygon fill="black" stroke="black" points="75.98,-26.73 85.22,-21.55 74.76,-19.84 75.98,-26.73"/>
<text text-anchor="middle" x="80.36" y="-73.58" font-family="Times,serif" font-size="14.00">BODY_FLAG_PAUSE</text>
</g>
<!-- Dead -->
<g id="node4" class="node">
<title>Dead</title>
<ellipse fill="none" stroke="black" cx="343.61" cy="-18" rx="37" ry="18"/>
<text text-anchor="middle" x="343.61" y="-13.32" font-family="Times,serif" font-size="14.00">Dead</text>
</g>
<!-- Running&#45;&gt;Dead -->
<g id="edge4" class="edge">
<title>Running&#45;&gt;Dead</title>
<path fill="none" stroke="black" d="M260.31,-120.77C276.79,-100.63 304.62,-66.64 323.53,-43.53"/>
<polygon fill="black" stroke="black" points="326.68,-46.22 330.3,-36.26 321.26,-41.78 326.68,-46.22"/>
</g>
<!-- Paused&#45;&gt;Running -->
<g id="edge3" class="edge">
<title>Paused&#45;&gt;Running</title>
<path fill="none" stroke="black" d="M148.33,-35.34C167.75,-55.52 200.96,-90.04 223.34,-113.31"/>
<polygon fill="black" stroke="black" points="220.31,-115.24 229.76,-120.02 225.35,-110.39 220.31,-115.24"/>
</g>
<!-- Dead&#45;&gt;Running -->
<g id="edge5" class="edge">
<title>Dead&#45;&gt;Running</title>
<path fill="none" stroke="black" d="M343.24,-36.22C342.05,-52.96 337.96,-78.31 324.61,-95.5 316.51,-105.94 305.06,-114.1 293.42,-120.34"/>
<polygon fill="black" stroke="black" points="292.09,-117.59 284.66,-125.14 295.18,-123.87 292.09,-117.59"/>
<text text-anchor="middle" x="434.11" y="-82.2" font-family="Times,serif" font-size="14.00">BODY_FLAG_RESURRECT</text>
<text text-anchor="middle" x="434.11" y="-64.95" font-family="Times,serif" font-size="14.00">iteration++</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@ -0,0 +1,176 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="117.73958mm"
height="26.458332mm"
viewBox="0 0 117.73958 26.458332"
version="1.1"
id="svg1"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
sodipodi:docname="parallel-tasks.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
showgrid="true"
inkscape:zoom="1.4289282"
inkscape:cx="335.21629"
inkscape:cy="58.085495"
inkscape:window-width="1914"
inkscape:window-height="1025"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:window-maximized="1"
inkscape:current-layer="layer1">
<inkscape:grid
id="grid1"
units="px"
originx="-9.9999997"
originy="-9.9999997"
spacingx="0.26458333"
spacingy="0.26458334"
empcolor="#3f3fff"
empopacity="0.25098039"
color="#3f3fff"
opacity="0.1254902"
empspacing="5"
dotted="false"
gridanglex="30"
gridanglez="30"
visible="true" />
</sodipodi:namedview>
<defs
id="defs1" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(-2.6458333,-2.6458333)">
<rect
style="fill:none;stroke:none;stroke-width:0.3;stroke-linecap:round"
id="rect9"
width="117.73958"
height="26.458332"
x="2.6458333"
y="2.6458333" />
<rect
style="fill:#f2f2f2;stroke:#000000;stroke-width:0.3;stroke-linecap:round"
id="rect1"
width="44.979168"
height="23.8125"
x="3.96875"
y="3.9687502" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="6.6805291"
y="9.5720644"
id="text1"><tspan
sodipodi:role="line"
id="tspan1"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans';stroke-width:0.264583"
x="6.6805291"
y="9.5720644">Normal task</tspan></text>
<rect
style="fill:#d5ffd5;stroke:#000000;stroke-width:0.3;stroke-linecap:round"
id="rect3"
width="39.6875"
height="10.583333"
x="6.614583"
y="14.552083" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="18.784389"
y="21.011637"
id="text3"><tspan
sodipodi:role="line"
id="tspan3"
style="stroke-width:0.264583"
x="18.784389"
y="21.011637">Body 1</tspan></text>
<rect
style="fill:#f2f2f2;stroke:#000000;stroke-width:0.3;stroke-linecap:round"
id="rect4"
width="67.46875"
height="23.8125"
x="51.59375"
y="3.9687502" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="54.704952"
y="9.4792204"
id="text4"><tspan
sodipodi:role="line"
id="tspan4"
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Droid Sans';-inkscape-font-specification:'Droid Sans';stroke-width:0.264583"
x="54.704952"
y="9.4792204">Parallel task</tspan></text>
<rect
style="fill:#d5ffd5;stroke:#000000;stroke-width:0.3;stroke-linecap:round"
id="rect6"
width="21.166662"
height="10.583335"
x="54.239586"
y="14.552083" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="57.148972"
y="21.011637"
id="text6"><tspan
sodipodi:role="line"
id="tspan6"
style="stroke-width:0.264583"
x="57.148972"
y="21.011637">Body 1</tspan></text>
<rect
style="fill:#d5ffd5;stroke:#000000;stroke-width:0.3;stroke-linecap:round"
id="rect7"
width="21.166662"
height="10.583335"
x="78.052078"
y="14.552084" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="80.997643"
y="21.011639"
id="text7"><tspan
sodipodi:role="line"
id="tspan7"
style="stroke-width:0.264583"
x="80.997643"
y="21.011639">Body 2</tspan></text>
<rect
style="fill:#d5ffd5;stroke:#000000;stroke-width:0.3;stroke-linecap:round"
id="rect8"
width="14.552085"
height="10.583334"
x="101.86458"
y="14.552084" />
<text
xml:space="preserve"
style="font-size:4.23333px;line-height:1.25;font-family:monospace;-inkscape-font-specification:monospace;letter-spacing:0px;word-spacing:0px;stroke-width:0.264583"
x="105.3207"
y="20.895952"
id="text8"><tspan
sodipodi:role="line"
id="tspan8"
style="stroke-width:0.264583"
x="105.3207"
y="20.895952">...</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.9 KiB

View File

@ -1,9 +1,42 @@
# nOS-V model # nOS-V model
The [nOS-V library][nosv] implements a user space runtime that can schedule
tasks to run in multiple CPUs. The nOS-V library is instrumented to
track the internal state of the runtime as well as emit information
about the tasks that are running.
[nosv]: https://github.com/bsc-pm/nos-v
## Task model
The nOS-V runtime is composed of tasks that can be scheduled to run in The nOS-V runtime is composed of tasks that can be scheduled to run in
threads. Tasks can be paused and resumed, leaving the CPUs free to threads. Tasks can be paused and resumed, leaving the CPUs free to
execute other tasks. The nOS-V model tracks the state of each task as execute other tasks.
well as the state of the runtime internal state.
In nOS-V, parallel tasks can also be scheduled multiple times and the
same task may run concurrently in several CPUs. To model this scenario,
we introduce the concept of *body*, which maps to each execution of the
same task, with a unique body id.
![Parallel tasks](fig/parallel-tasks.svg)
A normal task only has one body, while a parallel task (created with
`TASK_FLAG_PARALLEL`) can have more than one body. Each body holds the
execution state, and can transition to different execution states
following this state diagram:
![Body model](fig/body-model.svg)
Bodies begin in the Created state and transition to Running when they
begin the execution. Bodies that can be paused (created with the flag
`BODY_FLAG_PAUSE` can transition to the Paused state.
Additionally, bodies can run multiple times if they are created with the
`BODY_FLAG_RESURRECT`, and transition from Dead to Running. This
transition is required to model the tasks that implement the taskiter in
NODES, which will be submitted multiple times for execution reusing the
same task id and body id. Every time a body runs again, the iteration
number is increased.
## Task type colors ## Task type colors

View File

@ -18,6 +18,7 @@ enum emu_prv_types {
PRV_NOSV_APPID = 12, PRV_NOSV_APPID = 12,
PRV_NOSV_SUBSYSTEM = 13, PRV_NOSV_SUBSYSTEM = 13,
PRV_NOSV_RANK = 14, PRV_NOSV_RANK = 14,
PRV_NOSV_BODYID = 15,
PRV_TAMPI_SUBSYSTEM = 20, PRV_TAMPI_SUBSYSTEM = 20,
PRV_MPI_FUNCTION = 25, PRV_MPI_FUNCTION = 25,
PRV_NODES_SUBSYSTEM = 30, PRV_NODES_SUBSYSTEM = 30,

View File

@ -97,12 +97,16 @@ simple(struct emu *emu)
} }
static int static int
chan_task_stopped(struct emu *emu) chan_body_stopped(struct emu *emu)
{ {
struct nosv_thread *th = EXT(emu->thread, 'V'); struct nosv_thread *th = EXT(emu->thread, 'V');
struct chan *ch = th->m.ch; struct chan *ch = th->m.ch;
struct value null = value_null(); struct value null = value_null();
if (chan_set(&ch[CH_BODYID], null) != 0) {
err("chan_set taskid failed");
return -1;
}
if (chan_set(&ch[CH_TASKID], null) != 0) { if (chan_set(&ch[CH_TASKID], null) != 0) {
err("chan_set taskid failed"); err("chan_set taskid failed");
return -1; return -1;
@ -128,8 +132,9 @@ chan_task_stopped(struct emu *emu)
} }
static int static int
chan_task_running(struct emu *emu, struct task *task) chan_body_running(struct emu *emu, struct body *body)
{ {
struct task *task = body_get_task(body);
struct nosv_thread *th = EXT(emu->thread, 'V'); struct nosv_thread *th = EXT(emu->thread, 'V');
struct proc *proc = emu->proc; struct proc *proc = emu->proc;
struct chan *ch = th->m.ch; struct chan *ch = th->m.ch;
@ -147,6 +152,10 @@ chan_task_running(struct emu *emu, struct task *task)
return -1; return -1;
} }
if (chan_set(&ch[CH_BODYID], value_int64(body_get_id(body))) != 0) {
err("chan_set bodyid failed");
return -1;
}
if (chan_set(&ch[CH_TASKID], value_int64(task->id)) != 0) { if (chan_set(&ch[CH_TASKID], value_int64(task->id)) != 0) {
err("chan_set taskid failed"); err("chan_set taskid failed");
return -1; return -1;
@ -171,22 +180,24 @@ chan_task_running(struct emu *emu, struct task *task)
} }
static int static int
chan_task_switch(struct emu *emu, struct task *prev, struct task *next) chan_body_switch(struct emu *emu, struct body *bprev, struct body *bnext)
{ {
struct nosv_thread *th = EXT(emu->thread, 'V'); struct nosv_thread *th = EXT(emu->thread, 'V');
struct chan *ch = th->m.ch; struct chan *ch = th->m.ch;
struct proc *proc = emu->proc; struct proc *proc = emu->proc;
if (!prev || !next) { if (!bprev || !bnext) {
err("cannot switch to or from a NULL task"); err("cannot switch to or from a NULL body");
return -1; return -1;
} }
if (prev == next) { if (bprev == bnext) {
err("cannot switch to the same task"); err("cannot switch to the same body");
return -1; return -1;
} }
struct task *next = body_get_task(bnext);
if (next->id == 0) { if (next->id == 0) {
err("next task id cannot be 0"); err("next task id cannot be 0");
return -1; return -1;
@ -197,11 +208,10 @@ chan_task_switch(struct emu *emu, struct task *prev, struct task *next)
return -1; return -1;
} }
if (prev->thread != next->thread) { if (chan_set(&ch[CH_BODYID], value_int64(body_get_id(bnext))) != 0) {
err("cannot switch to a task of another thread"); err("chan_set taskid failed");
return -1; return -1;
} }
if (chan_set(&ch[CH_TASKID], value_int64(next->id)) != 0) { if (chan_set(&ch[CH_TASKID], value_int64(next->id)) != 0) {
err("chan_set taskid failed"); err("chan_set taskid failed");
return -1; return -1;
@ -235,12 +245,15 @@ update_task_state(struct emu *emu)
uint32_t task_id = emu->ev->payload->u32[0]; uint32_t task_id = emu->ev->payload->u32[0];
if (emu->ev->payload_size < 8) {
err("missing body id in payload");
return -1;
}
struct nosv_thread *th = EXT(emu->thread, 'V'); struct nosv_thread *th = EXT(emu->thread, 'V');
struct nosv_proc *proc = EXT(emu->proc, 'V'); struct nosv_proc *proc = EXT(emu->proc, 'V');
struct task_info *info = &proc->task_info; struct task_info *info = &proc->task_info;
struct task_stack *stack = &th->task_stack; struct task_stack *stack = &th->task_stack;
struct task *task = task_find(info->tasks, task_id); struct task *task = task_find(info->tasks, task_id);
if (task == NULL) { if (task == NULL) {
@ -248,19 +261,37 @@ update_task_state(struct emu *emu)
return -1; return -1;
} }
uint32_t body_id = emu->ev->payload->u32[1];
if (task_is_parallel(task)) {
if (body_id == 0) {
err("the body_id must be > 0 for parallel task %u",
task_get_id(task));
return -1;
}
} else {
if (body_id != 0) {
err("the body_id must be 0 for non-parallel task %u",
task_get_id(task));
return -1;
}
/* We use body_id = 1 internally, as they cannot be zero. */
body_id = 1;
}
int ret = 0; int ret = 0;
switch (emu->ev->v) { switch (emu->ev->v) {
case 'x': case 'x':
ret = task_execute(stack, task); ret = task_execute(stack, task, body_id);
break; break;
case 'e': case 'e':
ret = task_end(stack, task); ret = task_end(stack, task, body_id);
break; break;
case 'p': case 'p':
ret = task_pause(stack, task); ret = task_pause(stack, task, body_id);
break; break;
case 'r': case 'r':
ret = task_resume(stack, task); ret = task_resume(stack, task, body_id);
break; break;
default: default:
err("unexpected nOS-V task event"); err("unexpected nOS-V task event");
@ -297,22 +328,22 @@ expand_transition_value(struct emu *emu, int was_running, int runs_now, char *tr
} }
static int static int
update_task_channels(struct emu *emu, char tr, struct task *prev, struct task *next) update_task_channels(struct emu *emu, char tr, struct body *bprev, struct body *bnext)
{ {
int ret = 0; int ret = 0;
switch (tr) { switch (tr) {
case 'x': case 'x':
case 'r': case 'r':
ret = chan_task_running(emu, next); ret = chan_body_running(emu, bnext);
break; break;
case 'e': case 'e':
case 'p': case 'p':
ret = chan_task_stopped(emu); ret = chan_body_stopped(emu);
break; break;
/* Additional nested transitions */ /* Additional nested transitions */
case 'X': case 'X':
case 'E': case 'E':
ret = chan_task_switch(emu, prev, next); ret = chan_body_switch(emu, bprev, bnext);
break; break;
default: default:
err("unexpected transition value %c", tr); err("unexpected transition value %c", tr);
@ -328,7 +359,7 @@ update_task_channels(struct emu *emu, char tr, struct task *prev, struct task *n
} }
static int static int
enforce_task_rules(struct emu *emu, char tr, struct task *next) enforce_task_rules(struct emu *emu, char tr, struct body *next)
{ {
if (tr != 'x' && tr != 'X') if (tr != 'x' && tr != 'X')
return 0; return 0;
@ -336,8 +367,8 @@ enforce_task_rules(struct emu *emu, char tr, struct task *next)
/* If a task has just entered the running state, it must show /* If a task has just entered the running state, it must show
* the running task body subsystem */ * the running task body subsystem */
if (next->state != TASK_ST_RUNNING) { if (body_get_state(next) != BODY_ST_RUNNING) {
err("task not in running state on begin"); err("body not in running state on begin");
return -1; return -1;
} }
@ -384,7 +415,7 @@ update_task(struct emu *emu)
struct nosv_thread *th = EXT(emu->thread, 'V'); struct nosv_thread *th = EXT(emu->thread, 'V');
struct task_stack *stack = &th->task_stack; struct task_stack *stack = &th->task_stack;
struct task *prev = task_get_running(stack); struct body *prev = task_get_running(stack);
/* Update the emulator state, but don't modify the channels */ /* Update the emulator state, but don't modify the channels */
if (update_task_state(emu) != 0) { if (update_task_state(emu) != 0) {
@ -392,7 +423,7 @@ update_task(struct emu *emu)
return -1; return -1;
} }
struct task *next = task_get_running(stack); struct body *next = task_get_running(stack);
/* Update the subsystem channel */ /* Update the subsystem channel */
if (update_task_ss_channel(emu, emu->ev->v) != 0) { if (update_task_ss_channel(emu, emu->ev->v) != 0) {
@ -423,9 +454,9 @@ update_task(struct emu *emu)
} }
static int static int
create_task(struct emu *emu) create_task(struct emu *emu, char value)
{ {
if (emu->ev->payload_size != 8) { if (emu->ev->payload_size < 8) {
err("unexpected payload size"); err("unexpected payload size");
return -1; return -1;
} }
@ -433,10 +464,20 @@ create_task(struct emu *emu)
uint32_t task_id = emu->ev->payload->u32[0]; uint32_t task_id = emu->ev->payload->u32[0];
uint32_t type_id = emu->ev->payload->u32[1]; uint32_t type_id = emu->ev->payload->u32[1];
int is_parallel = (value == 'C');
uint32_t flags;
/* Parallel tasks cannot pause or resurrect */
if (is_parallel)
flags = TASK_FLAG_PARALLEL;
else
flags = TASK_FLAG_RESURRECT | TASK_FLAG_PAUSE;
struct nosv_proc *proc = EXT(emu->proc, 'V'); struct nosv_proc *proc = EXT(emu->proc, 'V');
struct task_info *info = &proc->task_info; struct task_info *info = &proc->task_info;
if (task_create(info, type_id, task_id) != 0) { if (task_create(info, type_id, task_id, flags) != 0) {
err("task_create failed"); err("task_create failed");
return -1; return -1;
} }
@ -451,8 +492,9 @@ pre_task(struct emu *emu)
{ {
int ret = 0; int ret = 0;
switch (emu->ev->v) { switch (emu->ev->v) {
case 'C':
case 'c': case 'c':
ret = create_task(emu); ret = create_task(emu, emu->ev->v);
break; break;
case 'x': case 'x':
case 'e': case 'e':

View File

@ -12,7 +12,8 @@
/* Private enums */ /* Private enums */
enum nosv_chan { enum nosv_chan {
CH_TASKID = 0, CH_BODYID = 0,
CH_TASKID,
CH_TYPE, CH_TYPE,
CH_APPID, CH_APPID,
CH_SUBSYSTEM, CH_SUBSYSTEM,

View File

@ -32,10 +32,11 @@ enum { model_id = 'V' };
static struct ev_decl model_evlist[] = { static struct ev_decl model_evlist[] = {
{ "VTc(u32 taskid, u32 typeid)", "creates task %{taskid} with type %{typeid}" }, { "VTc(u32 taskid, u32 typeid)", "creates task %{taskid} with type %{typeid}" },
{ "VTx(u32 taskid)", "executes the task %{taskid}" }, { "VTC(u32 taskid, u32 typeid)", "creates parallel task %{taskid} with type %{typeid}" },
{ "VTe(u32 taskid)", "ends the task %{taskid}" }, { "VTx(u32 taskid, u32 bodyid)", "executes the task %{taskid} with bodyid %{bodyid}" },
{ "VTp(u32 taskid)", "pauses the task %{taskid}" }, { "VTe(u32 taskid, u32 bodyid)", "ends the task %{taskid} with bodyid %{bodyid}" },
{ "VTr(u32 taskid)", "resumes the task %{taskid}" }, { "VTp(u32 taskid, u32 bodyid)", "pauses the task %{taskid} with bodyid %{bodyid}" },
{ "VTr(u32 taskid, u32 bodyid)", "resumes the task %{taskid} with bodyid %{bodyid}" },
{ "VYc+(u32 typeid, str label)", "creates task type %{typeid} with label \"%{label}\"" }, { "VYc+(u32 typeid, str label)", "creates task type %{typeid} with label \"%{label}\"" },
@ -72,7 +73,7 @@ static struct ev_decl model_evlist[] = {
struct model_spec model_nosv = { struct model_spec model_nosv = {
.name = model_name, .name = model_name,
.version = "1.1.0", .version = "2.0.0",
.evlist = model_evlist, .evlist = model_evlist,
.model = model_id, .model = model_id,
.create = model_nosv_create, .create = model_nosv_create,
@ -85,6 +86,7 @@ struct model_spec model_nosv = {
/* ----------------- channels ------------------ */ /* ----------------- channels ------------------ */
static const char *chan_name[CH_MAX] = { static const char *chan_name[CH_MAX] = {
[CH_BODYID] = "bodyid",
[CH_TASKID] = "taskid", [CH_TASKID] = "taskid",
[CH_TYPE] = "task_type", [CH_TYPE] = "task_type",
[CH_APPID] = "appid", [CH_APPID] = "appid",
@ -97,6 +99,7 @@ static const int chan_stack[CH_MAX] = {
}; };
static const int chan_dup[CH_MAX] = { static const int chan_dup[CH_MAX] = {
[CH_BODYID] = 1, /* Switch to another task with body 1 */
[CH_APPID] = 1, [CH_APPID] = 1,
[CH_TYPE] = 1, [CH_TYPE] = 1,
[CH_RANK] = 1, [CH_RANK] = 1,
@ -108,6 +111,7 @@ static const int chan_dup[CH_MAX] = {
/* ----------------- pvt ------------------ */ /* ----------------- pvt ------------------ */
static const int pvt_type[CH_MAX] = { static const int pvt_type[CH_MAX] = {
[CH_BODYID] = PRV_NOSV_BODYID,
[CH_TASKID] = PRV_NOSV_TASKID, [CH_TASKID] = PRV_NOSV_TASKID,
[CH_TYPE] = PRV_NOSV_TYPE, [CH_TYPE] = PRV_NOSV_TYPE,
[CH_APPID] = PRV_NOSV_APPID, [CH_APPID] = PRV_NOSV_APPID,
@ -116,6 +120,7 @@ static const int pvt_type[CH_MAX] = {
}; };
static const char *pcf_prefix[CH_MAX] = { static const char *pcf_prefix[CH_MAX] = {
[CH_BODYID] = "nOS-V task body ID",
[CH_TASKID] = "nOS-V task ID", [CH_TASKID] = "nOS-V task ID",
[CH_TYPE] = "nOS-V task type", [CH_TYPE] = "nOS-V task type",
[CH_APPID] = "nOS-V task AppID", [CH_APPID] = "nOS-V task AppID",
@ -152,11 +157,12 @@ static const struct pcf_value_label *pcf_labels[CH_MAX] = {
}; };
static const long prv_flags[CH_MAX] = { static const long prv_flags[CH_MAX] = {
[CH_TASKID] = PRV_SKIPDUP, [CH_BODYID] = PRV_SKIPDUPNULL, /* Switch to different task, same bodyid */
[CH_TYPE] = PRV_EMITDUP, /* Switch to task of same type */ [CH_TASKID] = PRV_SKIPDUPNULL, /* Switch to another body of the same task */
[CH_APPID] = PRV_EMITDUP, /* Switch to task of same appid */ [CH_TYPE] = PRV_SKIPDUPNULL, /* Switch to task of same type */
[CH_SUBSYSTEM] = PRV_SKIPDUP, [CH_APPID] = PRV_SKIPDUPNULL, /* Switch to task of same appid */
[CH_RANK] = PRV_EMITDUP, /* Switch to task of same rank */ [CH_SUBSYSTEM] = PRV_SKIPDUPNULL,
[CH_RANK] = PRV_SKIPDUPNULL, /* Switch to task of same rank */
}; };
static const struct model_pvt_spec pvt_spec = { static const struct model_pvt_spec pvt_spec = {
@ -169,6 +175,7 @@ static const struct model_pvt_spec pvt_spec = {
/* ----------------- tracking ------------------ */ /* ----------------- tracking ------------------ */
static const int th_track[CH_MAX] = { static const int th_track[CH_MAX] = {
[CH_BODYID] = TRACK_TH_RUN,
[CH_TASKID] = TRACK_TH_RUN, [CH_TASKID] = TRACK_TH_RUN,
[CH_TYPE] = TRACK_TH_RUN, [CH_TYPE] = TRACK_TH_RUN,
[CH_APPID] = TRACK_TH_RUN, [CH_APPID] = TRACK_TH_RUN,
@ -177,6 +184,7 @@ static const int th_track[CH_MAX] = {
}; };
static const int cpu_track[CH_MAX] = { static const int cpu_track[CH_MAX] = {
[CH_BODYID] = TRACK_TH_RUN,
[CH_TASKID] = TRACK_TH_RUN, [CH_TASKID] = TRACK_TH_RUN,
[CH_TYPE] = TRACK_TH_RUN, [CH_TYPE] = TRACK_TH_RUN,
[CH_APPID] = TRACK_TH_RUN, [CH_APPID] = TRACK_TH_RUN,
@ -256,12 +264,6 @@ model_nosv_create(struct emu *emu)
return -1; return -1;
} }
/* Init task stack thread pointer */
for (struct thread *t = sys->threads; t; t = t->gnext) {
struct nosv_thread *th = EXT(t, model_id);
th->task_stack.thread = t;
}
for (struct proc *p = sys->procs; p; p = p->gnext) { for (struct proc *p = sys->procs; p; p = p->gnext) {
if (init_proc(p) != 0) { if (init_proc(p) != 0) {
err("init_proc failed"); err("init_proc failed");

View File

@ -5,7 +5,7 @@ test_emu(attach.c)
test_emu(attach-old.c) test_emu(attach-old.c)
test_emu(nested-tasks.c) test_emu(nested-tasks.c)
test_emu(nested-tasks-bad.c SHOULD_FAIL test_emu(nested-tasks-bad.c SHOULD_FAIL
REGEX "cannot execute task 1: state is not created") REGEX "body_execute: body 1 state must be Created but is Running")
test_emu(task-types.c MP) test_emu(task-types.c MP)
test_emu(pause.c MP) test_emu(pause.c MP)
#test_emu(mp-rank.c MP) #test_emu(mp-rank.c MP)