Add more documentation

This commit is contained in:
Rodrigo Arias 2022-08-31 11:31:55 +02:00
parent 135f3dc7aa
commit 2679655b2a
30 changed files with 1042 additions and 84 deletions

31
doc/concepts.md Normal file
View File

@ -0,0 +1,31 @@
# Overview
The objective of the ovni project is to provide insight into what
happened at execution of a program.
![Instrumentation process](fig/instrumentation.svg)
The key pieces of software involved are instrumented so they emit events
during the execution which allow the reconstruction of the execution
later on.
During the execution phase, the information gathered in the events is
kept very short and simple, so the overhead is kept at minimum to avoid
disturbing the execution process. Here is an example of a single event
emitted during the execution phase, informing the current thread to
finish the execution:
00 4f 48 65 52 c0 27 b4 d3 ec 01 00
During the emulation phase, the events are read and processed in the
emulator, reconstructing the execution. State transitions are recorded
in a Paraver trace. Here is an example of the same thread ceasing the
execution:
2:0:1:1:1:50105669:1:0
Finally, loading the trace in the Paraver program, we can generate a
timeline visualization of the state change. Here is the example for the
same state transition of the thread stopping the execution:
![Visualization](fig/visualization.png)

View File

@ -0,0 +1,62 @@
# Developer guide
To contribute to the ovni project, please read carefully this guide and
follow the guidelines to have your contribution accepted in the project.
## First principle: keep things simple
The most important principle in the emulator is to keep things simple.
It is extremely important to avoid any complexities, including
sacrificing the performance if necessary to keep the design simple.
## Use a formal model
Design a model of the library or runtime that you want to instrument and
all posible state transitions to be checked by the emulator. Detect
as many error conditions as posible. Otherwise, it becomes very hard to
analyze millions of state transitions by the naked eye to determine if
something went wrong.
## Emit redundant information
At runtime, emit redundant information in the events, unless they affect
the performance very badly. This information may include the ID of the
current task or any other identification, which the emulator already
knows. This redundant information is the only bit of data the emulator
can use to perform consistency checks and ensure the emulated state
follows the runtime state.
The extra information also allows a human to read the binary trace and
understand what is happening without the need to keep track of the
emulation state all the time.
## Document your model
Explain your model and the concepts behind it, so a user can understand
how to interpret the information provided by the timeline views.
The emulator only tries to represent the execution, but is never
perfect. Sometimes it is difficult or impossible to instrument what
happened at runtime, so an approximation is the only posible approach.
Explain in the documentation how the model approximates the real
execution so the user can determine what information is only an
approximation.
## No dependencies
Don't pull any extra dependencies. If you need them, you are probably
violating the first principle (keeping things simple). Alternatively,
place a portable implementation in ovni, so we don't need to depend on
any other library when running the emulator.
## Testing
The ovni project has two types of tests: manual tests, which
artificially create the events in the trace, and only test the emulation
part. And runtime tests, which run the complete program with the
instrumentation enabled, generate a trace and then run the emulator.
When adding support for a new library or model, ensure you add enough
tests to cover the most important problems. Specially those hard to
detect without the current runtime state. See the `test/` directory for
examples of other models.

View File

@ -161,8 +161,9 @@ 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
6Hs Begins the spawn of a function
6HS Ends the spawn of a function
6s[ Begins to spawn a function via spawnFunction()
6s] Ends spawning a function
6Dr Begins the registration of a task's accesses
6DR Ends the registration of a task's accesses

View File

@ -0,0 +1,66 @@
digraph {
#rankdir=LR;
graph [ranksep="1"];
newrank=true;
subgraph cluster_resource {
color="#ffeeee";
style=filled;
label="Resouce model";
cluster -> {"node 0", "node 1"}
"node 0" -> {"cpu 0.0", "cpu 0.1"}
"node 1" -> {"cpu 1.0", "cpu 1.1"}
}
subgraph cluster_process {
color="#eeffee";
style=filled;
label="Process model"
genesis -> {"loom 0", "loom 1"}
"loom 0" -> {"pid 0.0", "pid 0.1"}
"loom 1" -> {"pid 1.0", "pid 1.1"}
"pid 0.0" -> {"th 0.0.0", "th 0.0.1"}
"pid 0.1" -> {"th 0.1.0", "th 0.1.1"}
}
subgraph cluster_task {
color="#eeeeff";
style=filled;
label="Task model";
workload -> { "app 0", "app 1"};
"app 0" -> {"rank 0.0", "rank 0.1"};
"app 1" -> {"rank 1.0", "rank 1.1"};
"rank 0.0" -> {"task 0.0.0","task 0.0.1"};
"rank 0.1" -> {"task 0.1.0", "task 0.1.1"};
}
{rank = same; workload; cluster; genesis;}
{
rank = same;
"node 0"; "node 1"; "loom 0"; "loom 1";
}
{ rank=same; "app 0"; "app 1"; }
{
rank = same; "rank 0.0"; "pid 0.0";
}
{
rank = same; "th 0.0.0"; "task 0.0.0";
"cpu 0.0"; "cpu 0.1"; "cpu 1.0"; "cpu 1.1";
}
edge [style=dashed, constraint=false];
"loom 0" -> "node 0" [color=blue, label="mapped to"];
"rank 0.0" -> "pid 0.0" [color=blue, label="mapped to"];
"task 0.0.0" -> "th 0.0.0" [color=red, label="runs at"];
"th 0.0.0" -> "cpu 0.0" [color=red, label="runs at"];
}

View File

Before

Width:  |  Height:  |  Size: 158 KiB

After

Width:  |  Height:  |  Size: 158 KiB

385
doc/emulation/fig/model.svg Normal file
View File

@ -0,0 +1,385 @@
<?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 5.0.0 (0)
-->
<!-- Pages: 1 -->
<svg width="1439pt" height="491pt"
viewBox="0.00 0.00 1439.00 491.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 487)">
<polygon fill="white" stroke="transparent" points="-4,4 -4,-487 1435,-487 1435,4 -4,4"/>
<g id="clust1" class="cluster">
<title>cluster_resource</title>
<polygon fill="#ffeeee" stroke="#ffeeee" points="8,-8 8,-475 438,-475 438,-8 8,-8"/>
<text text-anchor="middle" x="223" y="-459.8" font-family="Times,serif" font-size="14.00">Resouce model</text>
</g>
<g id="clust5" class="cluster">
<title>cluster_process</title>
<polygon fill="#eeffee" stroke="#eeffee" points="446,-8 446,-475 892,-475 892,-8 446,-8"/>
<text text-anchor="middle" x="669" y="-459.8" font-family="Times,serif" font-size="14.00">Process model</text>
</g>
<g id="clust11" class="cluster">
<title>cluster_task</title>
<polygon fill="#eeeeff" stroke="#eeeeff" points="900,-8 900,-475 1423,-475 1423,-8 900,-8"/>
<text text-anchor="middle" x="1161.5" y="-459.8" font-family="Times,serif" font-size="14.00">Task model</text>
</g>
<!-- cluster -->
<g id="node1" class="node">
<title>cluster</title>
<ellipse fill="none" stroke="black" cx="223" cy="-403" rx="42.79" ry="18"/>
<text text-anchor="middle" x="223" y="-399.3" font-family="Times,serif" font-size="14.00">cluster</text>
</g>
<!-- node 0 -->
<g id="node2" class="node">
<title>node 0</title>
<ellipse fill="none" stroke="black" cx="169" cy="-280" rx="42.49" ry="18"/>
<text text-anchor="middle" x="169" y="-276.3" font-family="Times,serif" font-size="14.00">node 0</text>
</g>
<!-- cluster&#45;&gt;node 0 -->
<g id="edge1" class="edge">
<title>cluster&#45;&gt;node 0</title>
<path fill="none" stroke="black" d="M215.49,-385.18C206.51,-365.06 191.38,-331.16 180.83,-307.51"/>
<polygon fill="black" stroke="black" points="183.89,-305.78 176.62,-298.07 177.5,-308.63 183.89,-305.78"/>
</g>
<!-- node 1 -->
<g id="node3" class="node">
<title>node 1</title>
<ellipse fill="none" stroke="black" cx="277" cy="-280" rx="42.49" ry="18"/>
<text text-anchor="middle" x="277" y="-276.3" font-family="Times,serif" font-size="14.00">node 1</text>
</g>
<!-- cluster&#45;&gt;node 1 -->
<g id="edge2" class="edge">
<title>cluster&#45;&gt;node 1</title>
<path fill="none" stroke="black" d="M230.51,-385.18C239.49,-365.06 254.62,-331.16 265.17,-307.51"/>
<polygon fill="black" stroke="black" points="268.5,-308.63 269.38,-298.07 262.11,-305.78 268.5,-308.63"/>
</g>
<!-- cpu 0.0 -->
<g id="node4" class="node">
<title>cpu 0.0</title>
<ellipse fill="none" stroke="black" cx="61" cy="-34" rx="44.69" ry="18"/>
<text text-anchor="middle" x="61" y="-30.3" font-family="Times,serif" font-size="14.00">cpu 0.0</text>
</g>
<!-- node 0&#45;&gt;cpu 0.0 -->
<g id="edge3" class="edge">
<title>node 0&#45;&gt;cpu 0.0</title>
<path fill="none" stroke="black" d="M161.58,-262.23C143.08,-220.44 94.83,-111.43 72.57,-61.13"/>
<polygon fill="black" stroke="black" points="75.72,-59.62 68.48,-51.89 69.32,-62.45 75.72,-59.62"/>
</g>
<!-- cpu 0.1 -->
<g id="node5" class="node">
<title>cpu 0.1</title>
<ellipse fill="none" stroke="black" cx="169" cy="-34" rx="44.69" ry="18"/>
<text text-anchor="middle" x="169" y="-30.3" font-family="Times,serif" font-size="14.00">cpu 0.1</text>
</g>
<!-- node 0&#45;&gt;cpu 0.1 -->
<g id="edge4" class="edge">
<title>node 0&#45;&gt;cpu 0.1</title>
<path fill="none" stroke="black" d="M169,-261.84C169,-220.1 169,-112.99 169,-62.33"/>
<polygon fill="black" stroke="black" points="172.5,-62.14 169,-52.14 165.5,-62.14 172.5,-62.14"/>
</g>
<!-- cpu 1.0 -->
<g id="node6" class="node">
<title>cpu 1.0</title>
<ellipse fill="none" stroke="black" cx="277" cy="-34" rx="44.69" ry="18"/>
<text text-anchor="middle" x="277" y="-30.3" font-family="Times,serif" font-size="14.00">cpu 1.0</text>
</g>
<!-- node 1&#45;&gt;cpu 1.0 -->
<g id="edge5" class="edge">
<title>node 1&#45;&gt;cpu 1.0</title>
<path fill="none" stroke="black" d="M277,-261.84C277,-220.1 277,-112.99 277,-62.33"/>
<polygon fill="black" stroke="black" points="280.5,-62.14 277,-52.14 273.5,-62.14 280.5,-62.14"/>
</g>
<!-- cpu 1.1 -->
<g id="node7" class="node">
<title>cpu 1.1</title>
<ellipse fill="none" stroke="black" cx="385" cy="-34" rx="44.69" ry="18"/>
<text text-anchor="middle" x="385" y="-30.3" font-family="Times,serif" font-size="14.00">cpu 1.1</text>
</g>
<!-- node 1&#45;&gt;cpu 1.1 -->
<g id="edge6" class="edge">
<title>node 1&#45;&gt;cpu 1.1</title>
<path fill="none" stroke="black" d="M284.15,-262.06C298.32,-228.63 331.06,-151.89 360,-88 363.97,-79.25 368.41,-69.74 372.44,-61.22"/>
<polygon fill="black" stroke="black" points="375.63,-62.66 376.76,-52.12 369.31,-59.65 375.63,-62.66"/>
</g>
<!-- genesis -->
<g id="node8" class="node">
<title>genesis</title>
<ellipse fill="none" stroke="black" cx="685" cy="-403" rx="46.29" ry="18"/>
<text text-anchor="middle" x="685" y="-399.3" font-family="Times,serif" font-size="14.00">genesis</text>
</g>
<!-- loom 0 -->
<g id="node9" class="node">
<title>loom 0</title>
<ellipse fill="none" stroke="black" cx="633" cy="-280" rx="42.49" ry="18"/>
<text text-anchor="middle" x="633" y="-276.3" font-family="Times,serif" font-size="14.00">loom 0</text>
</g>
<!-- genesis&#45;&gt;loom 0 -->
<g id="edge7" class="edge">
<title>genesis&#45;&gt;loom 0</title>
<path fill="none" stroke="black" d="M677.77,-385.18C669.13,-365.06 654.55,-331.16 644.39,-307.51"/>
<polygon fill="black" stroke="black" points="647.5,-305.88 640.34,-298.07 641.07,-308.64 647.5,-305.88"/>
</g>
<!-- loom 1 -->
<g id="node10" class="node">
<title>loom 1</title>
<ellipse fill="none" stroke="black" cx="737" cy="-280" rx="42.49" ry="18"/>
<text text-anchor="middle" x="737" y="-276.3" font-family="Times,serif" font-size="14.00">loom 1</text>
</g>
<!-- genesis&#45;&gt;loom 1 -->
<g id="edge8" class="edge">
<title>genesis&#45;&gt;loom 1</title>
<path fill="none" stroke="black" d="M692.23,-385.18C700.87,-365.06 715.45,-331.16 725.61,-307.51"/>
<polygon fill="black" stroke="black" points="728.93,-308.64 729.66,-298.07 722.5,-305.88 728.93,-308.64"/>
</g>
<!-- loom 0&#45;&gt;node 0 -->
<g id="edge27" class="edge">
<title>loom 0&#45;&gt;node 0</title>
<path fill="none" stroke="blue" stroke-dasharray="5,2" d="M602.07,-292.52C564.32,-307.07 498.2,-330.2 439,-339 355.62,-351.4 259.53,-319 207.44,-297.44"/>
<polygon fill="blue" stroke="blue" points="208.5,-294.09 197.93,-293.42 205.78,-300.54 208.5,-294.09"/>
<text text-anchor="middle" x="401" y="-337.8" font-family="Times,serif" font-size="14.00">mapped to</text>
</g>
<!-- pid 0.0 -->
<g id="node11" class="node">
<title>pid 0.0</title>
<ellipse fill="none" stroke="black" cx="529" cy="-157" rx="42.79" ry="18"/>
<text text-anchor="middle" x="529" y="-153.3" font-family="Times,serif" font-size="14.00">pid 0.0</text>
</g>
<!-- loom 0&#45;&gt;pid 0.0 -->
<g id="edge9" class="edge">
<title>loom 0&#45;&gt;pid 0.0</title>
<path fill="none" stroke="black" d="M618.97,-262.68C601.04,-241.82 569.86,-205.54 549.33,-181.65"/>
<polygon fill="black" stroke="black" points="551.98,-179.36 542.8,-174.06 546.67,-183.93 551.98,-179.36"/>
</g>
<!-- pid 0.1 -->
<g id="node12" class="node">
<title>pid 0.1</title>
<ellipse fill="none" stroke="black" cx="633" cy="-157" rx="42.79" ry="18"/>
<text text-anchor="middle" x="633" y="-153.3" font-family="Times,serif" font-size="14.00">pid 0.1</text>
</g>
<!-- loom 0&#45;&gt;pid 0.1 -->
<g id="edge10" class="edge">
<title>loom 0&#45;&gt;pid 0.1</title>
<path fill="none" stroke="black" d="M633,-261.92C633,-242.04 633,-208.92 633,-185.42"/>
<polygon fill="black" stroke="black" points="636.5,-185.38 633,-175.38 629.5,-185.38 636.5,-185.38"/>
</g>
<!-- pid 1.0 -->
<g id="node13" class="node">
<title>pid 1.0</title>
<ellipse fill="none" stroke="black" cx="737" cy="-157" rx="42.79" ry="18"/>
<text text-anchor="middle" x="737" y="-153.3" font-family="Times,serif" font-size="14.00">pid 1.0</text>
</g>
<!-- loom 1&#45;&gt;pid 1.0 -->
<g id="edge11" class="edge">
<title>loom 1&#45;&gt;pid 1.0</title>
<path fill="none" stroke="black" d="M737,-261.92C737,-242.04 737,-208.92 737,-185.42"/>
<polygon fill="black" stroke="black" points="740.5,-185.38 737,-175.38 733.5,-185.38 740.5,-185.38"/>
</g>
<!-- pid 1.1 -->
<g id="node14" class="node">
<title>pid 1.1</title>
<ellipse fill="none" stroke="black" cx="841" cy="-157" rx="42.79" ry="18"/>
<text text-anchor="middle" x="841" y="-153.3" font-family="Times,serif" font-size="14.00">pid 1.1</text>
</g>
<!-- loom 1&#45;&gt;pid 1.1 -->
<g id="edge12" class="edge">
<title>loom 1&#45;&gt;pid 1.1</title>
<path fill="none" stroke="black" d="M751.03,-262.68C768.96,-241.82 800.14,-205.54 820.67,-181.65"/>
<polygon fill="black" stroke="black" points="823.33,-183.93 827.2,-174.06 818.02,-179.36 823.33,-183.93"/>
</g>
<!-- th 0.0.0 -->
<g id="node15" class="node">
<title>th 0.0.0</title>
<ellipse fill="none" stroke="black" cx="501" cy="-34" rx="46.59" ry="18"/>
<text text-anchor="middle" x="501" y="-30.3" font-family="Times,serif" font-size="14.00">th 0.0.0</text>
</g>
<!-- pid 0.0&#45;&gt;th 0.0.0 -->
<g id="edge13" class="edge">
<title>pid 0.0&#45;&gt;th 0.0.0</title>
<path fill="none" stroke="black" d="M525.05,-138.92C520.42,-118.92 512.7,-85.55 507.25,-62.02"/>
<polygon fill="black" stroke="black" points="510.6,-60.95 504.93,-51.99 503.78,-62.52 510.6,-60.95"/>
</g>
<!-- th 0.0.1 -->
<g id="node16" class="node">
<title>th 0.0.1</title>
<ellipse fill="none" stroke="black" cx="613" cy="-34" rx="46.59" ry="18"/>
<text text-anchor="middle" x="613" y="-30.3" font-family="Times,serif" font-size="14.00">th 0.0.1</text>
</g>
<!-- pid 0.0&#45;&gt;th 0.0.1 -->
<g id="edge14" class="edge">
<title>pid 0.0&#45;&gt;th 0.0.1</title>
<path fill="none" stroke="black" d="M540.68,-139.18C554.91,-118.68 579.08,-83.85 595.53,-60.16"/>
<polygon fill="black" stroke="black" points="598.59,-61.89 601.42,-51.68 592.84,-57.9 598.59,-61.89"/>
</g>
<!-- th 0.1.0 -->
<g id="node17" class="node">
<title>th 0.1.0</title>
<ellipse fill="none" stroke="black" cx="725" cy="-34" rx="46.59" ry="18"/>
<text text-anchor="middle" x="725" y="-30.3" font-family="Times,serif" font-size="14.00">th 0.1.0</text>
</g>
<!-- pid 0.1&#45;&gt;th 0.1.0 -->
<g id="edge15" class="edge">
<title>pid 0.1&#45;&gt;th 0.1.0</title>
<path fill="none" stroke="black" d="M645.41,-139.68C661.05,-119.11 688.07,-83.57 706.24,-59.67"/>
<polygon fill="black" stroke="black" points="709.23,-61.53 712.5,-51.45 703.66,-57.29 709.23,-61.53"/>
</g>
<!-- th 0.1.1 -->
<g id="node18" class="node">
<title>th 0.1.1</title>
<ellipse fill="none" stroke="black" cx="837" cy="-34" rx="46.59" ry="18"/>
<text text-anchor="middle" x="837" y="-30.3" font-family="Times,serif" font-size="14.00">th 0.1.1</text>
</g>
<!-- pid 0.1&#45;&gt;th 0.1.1 -->
<g id="edge16" class="edge">
<title>pid 0.1&#45;&gt;th 0.1.1</title>
<path fill="none" stroke="black" d="M656.8,-141.88C693.15,-120.32 762.61,-79.12 803.87,-54.65"/>
<polygon fill="black" stroke="black" points="805.9,-57.51 812.72,-49.4 802.33,-51.49 805.9,-57.51"/>
</g>
<!-- th 0.0.0&#45;&gt;cpu 0.0 -->
<g id="edge30" class="edge">
<title>th 0.0.0&#45;&gt;cpu 0.0</title>
<path fill="none" stroke="red" stroke-dasharray="5,2" d="M484.26,-50.97C468.31,-65.83 442.8,-86.38 416,-95 351.68,-115.69 180.53,-68.48 115,-52 111.44,-51.1 107.77,-50.09 104.1,-49.01"/>
<polygon fill="red" stroke="red" points="105.06,-45.64 94.47,-46.03 102.99,-52.33 105.06,-45.64"/>
<text text-anchor="middle" x="390" y="-91.8" font-family="Times,serif" font-size="14.00">runs at</text>
</g>
<!-- workload -->
<g id="node19" class="node">
<title>workload</title>
<ellipse fill="none" stroke="black" cx="1190" cy="-403" rx="53.09" ry="18"/>
<text text-anchor="middle" x="1190" y="-399.3" font-family="Times,serif" font-size="14.00">workload</text>
</g>
<!-- app 0 -->
<g id="node20" class="node">
<title>app 0</title>
<ellipse fill="none" stroke="black" cx="1132" cy="-280" rx="36.29" ry="18"/>
<text text-anchor="middle" x="1132" y="-276.3" font-family="Times,serif" font-size="14.00">app 0</text>
</g>
<!-- workload&#45;&gt;app 0 -->
<g id="edge17" class="edge">
<title>workload&#45;&gt;app 0</title>
<path fill="none" stroke="black" d="M1181.94,-385.18C1172.2,-364.86 1155.71,-330.47 1144.36,-306.79"/>
<polygon fill="black" stroke="black" points="1147.47,-305.19 1140,-297.68 1141.16,-308.21 1147.47,-305.19"/>
</g>
<!-- app 1 -->
<g id="node21" class="node">
<title>app 1</title>
<ellipse fill="none" stroke="black" cx="1249" cy="-280" rx="36.29" ry="18"/>
<text text-anchor="middle" x="1249" y="-276.3" font-family="Times,serif" font-size="14.00">app 1</text>
</g>
<!-- workload&#45;&gt;app 1 -->
<g id="edge18" class="edge">
<title>workload&#45;&gt;app 1</title>
<path fill="none" stroke="black" d="M1198.2,-385.18C1208.11,-364.86 1224.88,-330.47 1236.42,-306.79"/>
<polygon fill="black" stroke="black" points="1239.63,-308.2 1240.87,-297.68 1233.34,-305.14 1239.63,-308.2"/>
</g>
<!-- rank 0.0 -->
<g id="node22" class="node">
<title>rank 0.0</title>
<ellipse fill="none" stroke="black" cx="1015" cy="-157" rx="49.29" ry="18"/>
<text text-anchor="middle" x="1015" y="-153.3" font-family="Times,serif" font-size="14.00">rank 0.0</text>
</g>
<!-- app 0&#45;&gt;rank 0.0 -->
<g id="edge19" class="edge">
<title>app 0&#45;&gt;rank 0.0</title>
<path fill="none" stroke="black" d="M1116.7,-263.18C1096.58,-242.37 1061.05,-205.63 1037.77,-181.55"/>
<polygon fill="black" stroke="black" points="1040.14,-178.96 1030.67,-174.21 1035.11,-183.83 1040.14,-178.96"/>
</g>
<!-- rank 0.1 -->
<g id="node23" class="node">
<title>rank 0.1</title>
<ellipse fill="none" stroke="black" cx="1132" cy="-157" rx="49.29" ry="18"/>
<text text-anchor="middle" x="1132" y="-153.3" font-family="Times,serif" font-size="14.00">rank 0.1</text>
</g>
<!-- app 0&#45;&gt;rank 0.1 -->
<g id="edge20" class="edge">
<title>app 0&#45;&gt;rank 0.1</title>
<path fill="none" stroke="black" d="M1132,-261.92C1132,-242.04 1132,-208.92 1132,-185.42"/>
<polygon fill="black" stroke="black" points="1135.5,-185.38 1132,-175.38 1128.5,-185.38 1135.5,-185.38"/>
</g>
<!-- rank 1.0 -->
<g id="node24" class="node">
<title>rank 1.0</title>
<ellipse fill="none" stroke="black" cx="1249" cy="-157" rx="49.29" ry="18"/>
<text text-anchor="middle" x="1249" y="-153.3" font-family="Times,serif" font-size="14.00">rank 1.0</text>
</g>
<!-- app 1&#45;&gt;rank 1.0 -->
<g id="edge21" class="edge">
<title>app 1&#45;&gt;rank 1.0</title>
<path fill="none" stroke="black" d="M1249,-261.92C1249,-242.04 1249,-208.92 1249,-185.42"/>
<polygon fill="black" stroke="black" points="1252.5,-185.38 1249,-175.38 1245.5,-185.38 1252.5,-185.38"/>
</g>
<!-- rank 1.1 -->
<g id="node25" class="node">
<title>rank 1.1</title>
<ellipse fill="none" stroke="black" cx="1366" cy="-157" rx="49.29" ry="18"/>
<text text-anchor="middle" x="1366" y="-153.3" font-family="Times,serif" font-size="14.00">rank 1.1</text>
</g>
<!-- app 1&#45;&gt;rank 1.1 -->
<g id="edge22" class="edge">
<title>app 1&#45;&gt;rank 1.1</title>
<path fill="none" stroke="black" d="M1264.3,-263.18C1284.42,-242.37 1319.95,-205.63 1343.23,-181.55"/>
<polygon fill="black" stroke="black" points="1345.89,-183.83 1350.33,-174.21 1340.86,-178.96 1345.89,-183.83"/>
</g>
<!-- rank 0.0&#45;&gt;pid 0.0 -->
<g id="edge28" class="edge">
<title>rank 0.0&#45;&gt;pid 0.0</title>
<path fill="none" stroke="blue" stroke-dasharray="5,2" d="M982.2,-170.78C917.51,-196.09 769.17,-244.84 647,-216 615.71,-208.61 583.26,-191.59 560.32,-177.72"/>
<polygon fill="blue" stroke="blue" points="562.06,-174.68 551.72,-172.39 558.38,-180.63 562.06,-174.68"/>
<text text-anchor="middle" x="685" y="-214.8" font-family="Times,serif" font-size="14.00">mapped to</text>
</g>
<!-- task 0.0.0 -->
<g id="node26" class="node">
<title>task 0.0.0</title>
<ellipse fill="none" stroke="black" cx="965" cy="-34" rx="56.59" ry="18"/>
<text text-anchor="middle" x="965" y="-30.3" font-family="Times,serif" font-size="14.00">task 0.0.0</text>
</g>
<!-- rank 0.0&#45;&gt;task 0.0.0 -->
<g id="edge23" class="edge">
<title>rank 0.0&#45;&gt;task 0.0.0</title>
<path fill="none" stroke="black" d="M1008.05,-139.18C999.74,-119.06 985.73,-85.16 975.95,-61.51"/>
<polygon fill="black" stroke="black" points="979.11,-59.98 972.05,-52.07 972.64,-62.65 979.11,-59.98"/>
</g>
<!-- task 0.0.1 -->
<g id="node27" class="node">
<title>task 0.0.1</title>
<ellipse fill="none" stroke="black" cx="1096" cy="-34" rx="56.59" ry="18"/>
<text text-anchor="middle" x="1096" y="-30.3" font-family="Times,serif" font-size="14.00">task 0.0.1</text>
</g>
<!-- rank 0.0&#45;&gt;task 0.0.1 -->
<g id="edge24" class="edge">
<title>rank 0.0&#45;&gt;task 0.0.1</title>
<path fill="none" stroke="black" d="M1026.26,-139.18C1039.98,-118.68 1063.3,-83.85 1079.16,-60.16"/>
<polygon fill="black" stroke="black" points="1082.18,-61.94 1084.83,-51.68 1076.36,-58.04 1082.18,-61.94"/>
</g>
<!-- task 0.1.0 -->
<g id="node28" class="node">
<title>task 0.1.0</title>
<ellipse fill="none" stroke="black" cx="1227" cy="-34" rx="56.59" ry="18"/>
<text text-anchor="middle" x="1227" y="-30.3" font-family="Times,serif" font-size="14.00">task 0.1.0</text>
</g>
<!-- rank 0.1&#45;&gt;task 0.1.0 -->
<g id="edge25" class="edge">
<title>rank 0.1&#45;&gt;task 0.1.0</title>
<path fill="none" stroke="black" d="M1145.21,-139.18C1161.37,-118.59 1188.88,-83.55 1207.49,-59.85"/>
<polygon fill="black" stroke="black" points="1210.48,-61.71 1213.9,-51.68 1204.97,-57.39 1210.48,-61.71"/>
</g>
<!-- task 0.1.1 -->
<g id="node29" class="node">
<title>task 0.1.1</title>
<ellipse fill="none" stroke="black" cx="1358" cy="-34" rx="56.59" ry="18"/>
<text text-anchor="middle" x="1358" y="-30.3" font-family="Times,serif" font-size="14.00">task 0.1.1</text>
</g>
<!-- rank 0.1&#45;&gt;task 0.1.1 -->
<g id="edge26" class="edge">
<title>rank 0.1&#45;&gt;task 0.1.1</title>
<path fill="none" stroke="black" d="M1158.81,-141.64C1199.18,-120.03 1275.66,-79.08 1321.21,-54.7"/>
<polygon fill="black" stroke="black" points="1323,-57.71 1330.16,-49.9 1319.69,-51.54 1323,-57.71"/>
</g>
<!-- task 0.0.0&#45;&gt;th 0.0.0 -->
<g id="edge29" class="edge">
<title>task 0.0.0&#45;&gt;th 0.0.0</title>
<path fill="none" stroke="red" stroke-dasharray="5,2" d="M922.11,-45.88C837.96,-68.38 654.09,-113.41 593,-95 568.4,-87.59 544.34,-71.21 526.99,-57.29"/>
<polygon fill="red" stroke="red" points="528.98,-54.39 519.04,-50.7 524.51,-59.78 528.98,-54.39"/>
<text text-anchor="middle" x="619" y="-91.8" font-family="Times,serif" font-size="14.00">runs at</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -0,0 +1,11 @@
digraph {
rankdir=LR;
{ rank=same; Running; Paused; }
Unknown -> Created;
Created -> Running;
Running -> Paused;
Paused -> Running;
Running -> Dead;
}

View File

@ -0,0 +1,72 @@
<?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 5.0.0 (0)
-->
<!-- Pages: 1 -->
<svg width="490pt" height="98pt"
viewBox="0.00 0.00 490.37 98.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 94)">
<polygon fill="white" stroke="transparent" points="-4,4 -4,-94 486.37,-94 486.37,4 -4,4"/>
<!-- Running -->
<g id="node1" class="node">
<title>Running</title>
<ellipse fill="none" stroke="black" cx="327.43" cy="-18" rx="50.09" ry="18"/>
<text text-anchor="middle" x="327.43" y="-14.3" font-family="Times,serif" font-size="14.00">Running</text>
</g>
<!-- Paused -->
<g id="node2" class="node">
<title>Paused</title>
<ellipse fill="none" stroke="black" cx="327.43" cy="-72" rx="44.39" ry="18"/>
<text text-anchor="middle" x="327.43" y="-68.3" font-family="Times,serif" font-size="14.00">Paused</text>
</g>
<!-- Running&#45;&gt;Paused -->
<g id="edge3" class="edge">
<title>Running&#45;&gt;Paused</title>
<path fill="none" stroke="black" d="M356.99,-32.55C364.84,-38.68 366.89,-44.81 363.15,-50.94"/>
<polygon fill="black" stroke="black" points="360.59,-48.55 356.08,-58.13 365.59,-53.45 360.59,-48.55"/>
</g>
<!-- Dead -->
<g id="node5" class="node">
<title>Dead</title>
<ellipse fill="none" stroke="black" cx="447.92" cy="-18" rx="34.39" ry="18"/>
<text text-anchor="middle" x="447.92" y="-14.3" font-family="Times,serif" font-size="14.00">Dead</text>
</g>
<!-- Running&#45;&gt;Dead -->
<g id="edge5" class="edge">
<title>Running&#45;&gt;Dead</title>
<path fill="none" stroke="black" d="M377.65,-18C386.05,-18 394.74,-18 402.99,-18"/>
<polygon fill="black" stroke="black" points="403.17,-21.5 413.17,-18 403.17,-14.5 403.17,-21.5"/>
</g>
<!-- Paused&#45;&gt;Running -->
<g id="edge4" class="edge">
<title>Paused&#45;&gt;Running</title>
<path fill="none" stroke="black" d="M298.77,-58.13C290.67,-52.14 288.11,-46.14 291.11,-40.15"/>
<polygon fill="black" stroke="black" points="293.83,-42.35 297.87,-32.55 288.6,-37.69 293.83,-42.35"/>
</g>
<!-- Unknown -->
<g id="node3" class="node">
<title>Unknown</title>
<ellipse fill="none" stroke="black" cx="54.6" cy="-18" rx="54.69" ry="18"/>
<text text-anchor="middle" x="54.6" y="-14.3" font-family="Times,serif" font-size="14.00">Unknown</text>
</g>
<!-- Created -->
<g id="node4" class="node">
<title>Created</title>
<ellipse fill="none" stroke="black" cx="193.29" cy="-18" rx="48.19" ry="18"/>
<text text-anchor="middle" x="193.29" y="-14.3" font-family="Times,serif" font-size="14.00">Created</text>
</g>
<!-- Unknown&#45;&gt;Created -->
<g id="edge1" class="edge">
<title>Unknown&#45;&gt;Created</title>
<path fill="none" stroke="black" d="M109.23,-18C117.63,-18 126.34,-18 134.82,-18"/>
<polygon fill="black" stroke="black" points="135.02,-21.5 145.02,-18 135.02,-14.5 135.02,-21.5"/>
</g>
<!-- Created&#45;&gt;Running -->
<g id="edge2" class="edge">
<title>Created&#45;&gt;Running</title>
<path fill="none" stroke="black" d="M241.62,-18C249.83,-18 258.47,-18 266.95,-18"/>
<polygon fill="black" stroke="black" points="267.2,-21.5 277.2,-18 267.2,-14.5 267.2,-21.5"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

View File

@ -0,0 +1,15 @@
digraph {
graph [nodesep=1, ranksep=1];
{rank = same; unknown; "running"; "dead";}
//{rank = same; cooling; paused; warming;}
unknown -> "running" [label="eXecute *"];
"running" -> "cooling" [label="Cool"];
"cooling" -> "paused" [label="* Pause"];
"running" -> "paused" [label="* Pause"];
"paused" -> "running" [label="Resume *"];
"paused" -> "warming" [label="Warm *"];
"warming" -> "running" [label="Resume"];
"running" -> "dead" [label="* End"];
}

View File

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -0,0 +1,104 @@
<?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 5.0.0 (0)
-->
<!-- Pages: 1 -->
<svg width="596pt" height="413pt"
viewBox="0.00 0.00 596.34 413.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 409)">
<polygon fill="white" stroke="transparent" points="-4,4 -4,-409 592.34,-409 592.34,4 -4,4"/>
<!-- unknown -->
<g id="node1" class="node">
<title>unknown</title>
<ellipse fill="none" stroke="black" cx="87.2" cy="-387" rx="52.79" ry="18"/>
<text text-anchor="middle" x="87.2" y="-383.3" font-family="Times,serif" font-size="14.00">unknown</text>
</g>
<!-- running -->
<g id="node2" class="node">
<title>running</title>
<ellipse fill="none" stroke="black" cx="331.2" cy="-387" rx="47.39" ry="18"/>
<text text-anchor="middle" x="331.2" y="-383.3" font-family="Times,serif" font-size="14.00">running</text>
</g>
<!-- unknown&#45;&gt;running -->
<g id="edge1" class="edge">
<title>unknown&#45;&gt;running</title>
<path fill="none" stroke="black" d="M140.14,-387C179.47,-387 233.07,-387 273.49,-387"/>
<polygon fill="black" stroke="black" points="273.72,-390.5 283.72,-387 273.72,-383.5 273.72,-390.5"/>
<text text-anchor="middle" x="211.8" y="-393.8" font-family="Times,serif" font-size="14.00">eXecute *</text>
</g>
<!-- dead -->
<g id="node3" class="node">
<title>dead</title>
<ellipse fill="none" stroke="black" cx="555.2" cy="-387" rx="33.29" ry="18"/>
<text text-anchor="middle" x="555.2" y="-383.3" font-family="Times,serif" font-size="14.00">dead</text>
</g>
<!-- running&#45;&gt;dead -->
<g id="edge8" class="edge">
<title>running&#45;&gt;dead</title>
<path fill="none" stroke="black" d="M378.7,-387C418.03,-387 473.44,-387 511.64,-387"/>
<polygon fill="black" stroke="black" points="511.93,-390.5 521.93,-387 511.93,-383.5 511.93,-390.5"/>
<text text-anchor="middle" x="450.35" y="-393.8" font-family="Times,serif" font-size="14.00">* End</text>
</g>
<!-- cooling -->
<g id="node4" class="node">
<title>cooling</title>
<ellipse fill="none" stroke="black" cx="44.2" cy="-264" rx="44.39" ry="18"/>
<text text-anchor="middle" x="44.2" y="-260.3" font-family="Times,serif" font-size="14.00">cooling</text>
</g>
<!-- running&#45;&gt;cooling -->
<g id="edge2" class="edge">
<title>running&#45;&gt;cooling</title>
<path fill="none" stroke="black" d="M289.6,-378.08C251,-369.83 192.54,-355.01 145.2,-333 118.48,-320.58 90.92,-301.53 71.35,-286.75"/>
<polygon fill="black" stroke="black" points="73.28,-283.82 63.21,-280.5 69.01,-289.37 73.28,-283.82"/>
<text text-anchor="middle" x="161.2" y="-321.8" font-family="Times,serif" font-size="14.00">Cool</text>
</g>
<!-- paused -->
<g id="node5" class="node">
<title>paused</title>
<ellipse fill="none" stroke="black" cx="331.2" cy="-141" rx="44.39" ry="18"/>
<text text-anchor="middle" x="331.2" y="-137.3" font-family="Times,serif" font-size="14.00">paused</text>
</g>
<!-- running&#45;&gt;paused -->
<g id="edge4" class="edge">
<title>running&#45;&gt;paused</title>
<path fill="none" stroke="black" d="M321.28,-369.05C310.18,-349.04 292.9,-314.36 286.2,-282 277.68,-240.9 298.67,-194.84 314.77,-167.15"/>
<polygon fill="black" stroke="black" points="317.82,-168.87 319.99,-158.5 311.83,-165.25 317.82,-168.87"/>
<text text-anchor="middle" x="313.2" y="-260.3" font-family="Times,serif" font-size="14.00">* Pause</text>
</g>
<!-- cooling&#45;&gt;paused -->
<g id="edge3" class="edge">
<title>cooling&#45;&gt;paused</title>
<path fill="none" stroke="black" d="M58.64,-246.83C73.38,-231.3 97.68,-208.29 123.2,-195 172.77,-169.19 235.64,-155.43 279.22,-148.46"/>
<polygon fill="black" stroke="black" points="279.96,-151.89 289.32,-146.91 278.9,-144.97 279.96,-151.89"/>
<text text-anchor="middle" x="150.2" y="-198.8" font-family="Times,serif" font-size="14.00">* Pause</text>
</g>
<!-- paused&#45;&gt;running -->
<g id="edge5" class="edge">
<title>paused&#45;&gt;running</title>
<path fill="none" stroke="black" d="M340.01,-158.67C344.91,-168.85 350.54,-182.32 353.2,-195 365.77,-255.04 368.14,-273.04 355.2,-333 353.24,-342.08 349.58,-351.48 345.71,-359.8"/>
<polygon fill="black" stroke="black" points="342.47,-358.47 341.15,-368.98 348.73,-361.58 342.47,-358.47"/>
<text text-anchor="middle" x="398.7" y="-260.3" font-family="Times,serif" font-size="14.00">Resume *</text>
</g>
<!-- warming -->
<g id="node6" class="node">
<title>warming</title>
<ellipse fill="none" stroke="black" cx="470.2" cy="-18" rx="51.99" ry="18"/>
<text text-anchor="middle" x="470.2" y="-14.3" font-family="Times,serif" font-size="14.00">warming</text>
</g>
<!-- paused&#45;&gt;warming -->
<g id="edge6" class="edge">
<title>paused&#45;&gt;warming</title>
<path fill="none" stroke="black" d="M349.08,-124.43C373.24,-103.4 416.46,-65.78 444.21,-41.62"/>
<polygon fill="black" stroke="black" points="446.69,-44.1 451.94,-34.9 442.1,-38.82 446.69,-44.1"/>
<text text-anchor="middle" x="436.2" y="-75.8" font-family="Times,serif" font-size="14.00">Warm *</text>
</g>
<!-- warming&#45;&gt;running -->
<g id="edge7" class="edge">
<title>warming&#45;&gt;running</title>
<path fill="none" stroke="black" d="M475.21,-35.95C478.71,-49.65 482.54,-69.47 481.2,-87 474.51,-174.43 485.56,-201.33 451.2,-282 434.89,-320.27 396.12,-349.56 367.03,-367.15"/>
<polygon fill="black" stroke="black" points="365.21,-364.16 358.35,-372.24 368.74,-370.21 365.21,-364.16"/>
<text text-anchor="middle" x="504.2" y="-198.8" font-family="Times,serif" font-size="14.00">Resume</text>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

View File

@ -13,10 +13,10 @@ The emulator uses several models to identify how the resources are being
used. The following diagram despicts the resource, process and task
model.
![Model](model.png)
[![Model](fig/model.svg)](fig/model.svg)
The resource model directly maps to the available hardware on the
machine. It consists of clusters which contains nodes, where each node
machine. It consists of a cluster which contains nodes, where each node
contains a set of CPUs that can execute instructions.
The process model tracks the state of processes and threads. Processes
@ -39,3 +39,19 @@ processing of events can keep the disk writting as the bottleneck.
The linter mode enables more tests which are disabled from the default
mode to prevent costly operations running in the emulator by default.
The linter tests are enabled when running the ovni testsuite.
## Emulation models
Each component is implemented in an emulation model, which consists of
the following elements:
- A single byte model identification (for example `O`).
- A set of runtime events with that model identification (see the [list
of events](events)).
- Rules that determine which sequences of events are valid.
- The emulation hooks that process each event and modify the state of
the emulator.
- A set of channels that output the states from the emulator.
- A set of Paraver views that present the information in a timeline.
All the models are independent and can be instrumented at the same time.

View File

@ -1,54 +1,74 @@
# Nanos6 model
The Nanos6 emulator generates four different Paraver views, which are
explained in this document.
The Nanos6 runtime library implements the OmpSs-2 tasking model, which
schedules the execution of tasks with dependencies. For more information
see the [OmpSs-2 website][oss] and the [Nanos6 repository][nanos6].
## Task id
[oss]: https://pm.bsc.es/ompss-2
[nanos6]: https://github.com/bsc-pm/nanos6
The task id view represents the id of the Nanos6 task instance that is
currently executing on each thread/cpu. This id is a monotonically
increasing identifier assigned on task creation. Lower ids correspond to
tasks created at an earlier point than higher ids.
The library is instrumented to track the execution of tasks and also the
execution path inside the runtime library to identify what is happening.
This information is typically used by both the users and the developers
of the Nanos6 library to analyze problems and unwanted behaviors.
Towards this goal, four different Paraver views are generated, which are
explained below.
## Task type
The state of each task is modelled in a simple finite state machine,
which identifies the main state changes of the task. The task is set to
the *Running* state only when is executing the body of the task,
consisting of user defined code. The states can be observed in the
following diagram:
![Nanos6 task states](fig/nanos6-task-model.svg)
## Task ID view
The task ID view represents the ID of the Nanos6 task instance that is
currently executing on each thread. This ID is a monotonically
increasing identifier assigned on task creation. Lower IDs correspond to
tasks created at an earlier point than higher IDs.
## Task type view
Every task in Nanos6 contains a task type, which roughly corresponds to
the actual location in the code a task was declared. For example if a
function fn() is declared as a Nanos6 task, and it is called multiple
times in a program, every created task will have a different id, but the
same type.
function is declared as a Nanos6 task, and it is called multiple times
in a program, every created task will have a different ID, but the same
type.
In the view, each type is shown with a label declared in the source with
the label() attribute of the task. If no label was specified, one is
the label attribute of the task. If no label was specified, one is
automatically generated for each type.
Note that in this view, event value is a hash function of the type
label, so two distinct types (tasks declared in different parts of the
code) with the same label will share event value and will hence be
indistinguishable.
Note that in this view, the numeric event value is a hash function of
the type label, so two distinct types (tasks declared in different parts
of the code) with the same label will share the event value and have the
same color.
## MPI Rank
## MPI rank view
Represents the current MPI rank for the currently running task in a
thread or cpu.
This view shows the numeric MPI rank of the process running the current
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.
## Subsystem view
The subsystem view attempts to provide a general overview of what the
runtime is doing at any point in time. This view is more complex to
understand than the others but is generally the most useful to
understand what is happening and debug problems related with the
runtime.
The subsystem view attempts to provide a general overview of what Nanos6
is doing at any point in time. This view is more complex to understand
than the others but is generally the most useful to understand what is
happening and debug problems related with Nanos6 itself.
The view shows the state of the runtime for each thread (and for each
CPU, the state of the running thread in that CPU).
The state is computed by the following method: the runtime code is
completely divided into sections of code (machine instructions) S1, S2,
..., SN, which are instrumented (an event is emitted when entering and
exiting each section), and one common section of code which is shared
across the subsystems, U, of no interest. We also assume any other code
not belonging to the runtime to be in the U section.
completely divided into sections of code (machine instructions) $`S_1,
S_2, \ldots, S_N`$, which are instrumented (an event is emitted when entering
and exiting each section), and one common section of code which is
shared across the subsystems, $`U`$, of no interest. We also assume any
other code not belonging to the runtime belongs to the $`U`$ section.
!!! remark
@ -58,36 +78,35 @@ To determine the state of a thread, we look into the stack to see what
is the top-most instrumented section.
At any given point in time, a thread may be executing code with a stack
that spawns multiple sections, for example *S1, U, S2, S3* and *U* (the
last is on top). The subsystem view selects the last subsystem section
from the stack ignoring the common section *U*, and presents that section
as the current state of the execution, in this case the *S3*.
that spawns multiple sections, for example $`[ S_1, U, S_2, S_3, U ]`$
(the last is current stack frame). The subsystem view selects the last
subsystem section from the stack ignoring the common section $`U`$, and
presents that section as the current state of the execution, in this
case the section $`S_3`$.
Additionally, the runtime sections are grouped together in subsystems,
which form a group of closely related functions. A complete set of
states for each subsystem is listed below.
Additionally, the runtime sections $`S_i`$ are grouped together in
subsystems, which form a closely related group of functions. The
complete list of subsystems and sections is shown below.
When there is no instrumented section in the thread stack, the state is
set to **No subsystem**.
### Task subsystem
The **Task** subsystem contains the code that controls the lifecycle of
tasks. It contains the following sections:
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).
- **Spawning function**: Registering a new spawn function
(programmatically created task)
- **Spawning function**: Spawning a function as task (it will be
submitted to the scheduler for later execution).
- **Creating**: Creating a new task, through `nanos6_create_task`
- **Submitting**: Submitting a recently created task, through
`nanos6_submit_task`
### Scheduler subsystem
The **Scheduler** system groups the actions that relate to the queueing
Scheduler subsystem
: The **Scheduler** system groups the actions that relate to the queueing
and dequeueing of ready tasks. It contains the following sections:
- **Waiting for tasks**: Actively waiting for tasks inside the
@ -99,9 +118,8 @@ to other threads
- **Adding ready tasks**: Adding tasks to the scheduler queues,
but outside of the scheduler lock.
### Dependency subsystem
The **Dependency** system only contains the code that manages the
Dependency subsystem
: The **Dependency** system only contains the code that manages the
registration of task dependencies. It contains the following sections:
- **Registering**: Registering a task's dependencies
@ -109,9 +127,8 @@ registration of task dependencies. It contains the following sections:
- **Unregistering**: Releasing a task's dependencies because
it has ended
### Blocking subsystem
The **Blocking** subsystem deals with the code stops the thread
Blocking subsystem
: The **Blocking** subsystem deals with the code stops the thread
execution. It contains the following sections:
- **Taskwait**: Task is blocked while inside a taskwait

View File

@ -1,11 +1,16 @@
# nOS-V model
## nOS-V task type colors
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
execute other tasks. The nOS-V model tracks the state of each task as
well as the state of the runtime internal state.
The color assigned to each nOS-V task type is computed from the task
type label using a hash function; the task type id doesn't affect in any
way how the color gets assigned. This method provides two desirable
properties:
## Task type colors
In the Paraver timeline, the color assigned to each nOS-V task type is
computed from the task type label using a hash function; the task type
id doesn't affect in any way how the color gets assigned. This method
provides two desirable properties:
- Invariant type colors over time: the order in which task types are
created doesn't affect their color.

View File

@ -1,5 +1,63 @@
# Ovni model
The ovni model tracks the state of threads and cpus.
The ovni model tracks the state of threads and CPUs and provides the
basis for other models.
![Thread states](thread-model.png)
## Thread model
The thread state is modelled as a finite state machine, depicted below:
![Thread states](fig/thread-model.svg){: style="width:80%"}
All threads begin in the `unknown` state and perform a transition to
running then the `execute` event (with MCV `OHx`) is received.
Notice that the runtime thread started the execution **before** emitting
the execute event, as it is not posible to emit the event at the exact
moment the thread begins the execution.
The asterisk `*` in the transitions states when the event is emitted. If
appears *before* the transition name, it happens *before* the real
event. If appears *after* then it is emitted *after* the real event.
In the case of the thread beginning the execution, the event is emitted
*after* the thread begins the execution, so the asterisk appears after.
### Cooling and warming states
In the Linux kernel, it is generally not possible to switch from a
thread A to another thread B in a single atomic operation, from
user-space. The thread A must first wake B and then put itself to sleep.
But the kernel is free to continue the execution of B instead of just
executing the last instructions of A so it can stop.
This limitation causes a time region at which more than one thread is
scheduled to the same CPU, which is a property that is generally
considered an error in parallel runtimes. To avoid this situation, the
additional states *cooling* and *warming* are introduced.
The cooling state indicates that the thread will be put to sleep and may
temporarily wake another thread in the same CPU. Similarly, the warming
state indicates that a thread is waking up, but it may be another thread
in its own CPU for a while.
These states allow the emulator to ignore the threads in the cooling and
warming states when only interested in those in the running state, but
at the same time allow the developers to identify the real transition
sequence to explain potential delays.
## CPU model
The CPU can only execute one thread at a time, and it may have multiple
threads assigned. When two or more threads are in the execution state,
the emulator cannot determine which one is really being executed, so it
will set all the channels to an error state.
!!! Caution
Multiple threads running in the same CPU typically indicates an
error of instrumentation or a problem in the runtime.
The emulator automatically switches the channels from one thread to
another when a thread is switched from the CPU. So the different models
don't need to worry about thread transitions. See the
[channels](../channels) section for more information.

View File

@ -3,13 +3,14 @@
font-size: 85%;
border: none;
padding: 0px;
background: #f8f8f8;
background: #eee;
}
.rst-content pre code {
color: inherit;
font-size: 80%;
line-height: 1.5em;
background: #eee;
}
p {

View File

@ -0,0 +1,8 @@
digraph {
rankdir = LR;
Execution, Emulation, Visualization [ shape = circle, width=1.5 ];
"Event trace", "State trace", "Timeline" [ shape = box ];
Execution -> "Event trace" -> Emulation -> "State trace" -> Visualization -> "Timeline";
}

View File

@ -0,0 +1,78 @@
<?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 5.0.0 (0)
-->
<!-- Pages: 1 -->
<svg width="789pt" height="119pt"
viewBox="0.00 0.00 788.54 118.54" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 114.54)">
<polygon fill="white" stroke="transparent" points="-4,4 -4,-114.54 784.54,-114.54 784.54,4 -4,4"/>
<!-- Execution -->
<g id="node1" class="node">
<title>Execution</title>
<ellipse fill="none" stroke="black" cx="54" cy="-55.27" rx="54" ry="54"/>
<text text-anchor="middle" x="54" y="-51.57" font-family="Times,serif" font-size="14.00">Execution</text>
</g>
<!-- Event trace -->
<g id="node4" class="node">
<title>Event trace</title>
<polygon fill="none" stroke="black" points="244,-73.27 144,-73.27 144,-37.27 244,-37.27 244,-73.27"/>
<text text-anchor="middle" x="194" y="-51.57" font-family="Times,serif" font-size="14.00">Event trace</text>
</g>
<!-- Execution&#45;&gt;Event trace -->
<g id="edge1" class="edge">
<title>Execution&#45;&gt;Event trace</title>
<path fill="none" stroke="black" d="M108.35,-55.27C116.66,-55.27 125.28,-55.27 133.71,-55.27"/>
<polygon fill="black" stroke="black" points="133.85,-58.77 143.85,-55.27 133.85,-51.77 133.85,-58.77"/>
</g>
<!-- Emulation -->
<g id="node2" class="node">
<title>Emulation</title>
<ellipse fill="none" stroke="black" cx="334" cy="-55.27" rx="54" ry="54"/>
<text text-anchor="middle" x="334" y="-51.57" font-family="Times,serif" font-size="14.00">Emulation</text>
</g>
<!-- State trace -->
<g id="node5" class="node">
<title>State trace</title>
<polygon fill="none" stroke="black" points="520,-73.27 424,-73.27 424,-37.27 520,-37.27 520,-73.27"/>
<text text-anchor="middle" x="472" y="-51.57" font-family="Times,serif" font-size="14.00">State trace</text>
</g>
<!-- Emulation&#45;&gt;State trace -->
<g id="edge3" class="edge">
<title>Emulation&#45;&gt;State trace</title>
<path fill="none" stroke="black" d="M388.36,-55.27C396.72,-55.27 405.39,-55.27 413.83,-55.27"/>
<polygon fill="black" stroke="black" points="413.97,-58.77 423.97,-55.27 413.97,-51.77 413.97,-58.77"/>
</g>
<!-- Visualization -->
<g id="node3" class="node">
<title>Visualization</title>
<ellipse fill="none" stroke="black" cx="611.27" cy="-55.27" rx="55.04" ry="55.04"/>
<text text-anchor="middle" x="611.27" y="-51.57" font-family="Times,serif" font-size="14.00">Visualization</text>
</g>
<!-- Timeline -->
<g id="node6" class="node">
<title>Timeline</title>
<polygon fill="none" stroke="black" points="780.54,-73.27 702.54,-73.27 702.54,-37.27 780.54,-37.27 780.54,-73.27"/>
<text text-anchor="middle" x="741.54" y="-51.57" font-family="Times,serif" font-size="14.00">Timeline</text>
</g>
<!-- Visualization&#45;&gt;Timeline -->
<g id="edge5" class="edge">
<title>Visualization&#45;&gt;Timeline</title>
<path fill="none" stroke="black" d="M666.66,-55.27C675.11,-55.27 683.8,-55.27 692.1,-55.27"/>
<polygon fill="black" stroke="black" points="692.38,-58.77 702.38,-55.27 692.38,-51.77 692.38,-58.77"/>
</g>
<!-- Event trace&#45;&gt;Emulation -->
<g id="edge2" class="edge">
<title>Event trace&#45;&gt;Emulation</title>
<path fill="none" stroke="black" d="M244.04,-55.27C252.39,-55.27 261.17,-55.27 269.83,-55.27"/>
<polygon fill="black" stroke="black" points="269.9,-58.77 279.9,-55.27 269.9,-51.77 269.9,-58.77"/>
</g>
<!-- State trace&#45;&gt;Visualization -->
<g id="edge4" class="edge">
<title>State trace&#45;&gt;Visualization</title>
<path fill="none" stroke="black" d="M520.24,-55.27C528.49,-55.27 537.2,-55.27 545.82,-55.27"/>
<polygon fill="black" stroke="black" points="545.86,-58.77 555.86,-55.27 545.86,-51.77 545.86,-58.77"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 142 KiB

After

Width:  |  Height:  |  Size: 142 KiB

BIN
doc/fig/logo2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 118 KiB

BIN
doc/fig/visualization.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,4 +1,4 @@
![Ovni logo](logo2.png)
![Ovni logo](fig/logo2.png)
This is the documentation of ovni, the Obtuse (but Versatile) Nanoscale
Instrumentation project.
@ -6,8 +6,8 @@ Instrumentation project.
!!! Note
Preferably write the name of the project as lowercase *ovni*
unless the grammar rules suggest otherwise, such as starting a
new sentence.
unless the grammar rules suggest otherwise, such as when
starting a new sentence.
The ovni project implements a fast instrumentation library that records
small events (starting at 12 bytes) during the execution of programs to
@ -16,7 +16,7 @@ later investigate how the execution happened.
The instrumentation process is split in two stages: [runtime](runtime)
tracing and [emulation](emulation/).
During runtime, very simple and short events are stored on disk which
During runtime, very short binary events are stored on disk which
describe what is happening. Once the execution finishes, the events are
read and processed to reproduce the execution during the emulation
process, and the final execution trace is generated.
@ -29,5 +29,15 @@ Each event belongs to a model, which has a direct mapping to a target
library or program. Each model is independent of other models, and they
can be instrumented concurrently.
The events are classified by using three identifiers known as *model*,
*category* and *value* (or MCV for short).
## Quick start
To start a trace follow these steps:
- First enable the instrumentation of those libraries or programs that
you are interested in (see their documentation).
- Then simply run the program normally. You will see a new `ovni`
directory containing the runtime trace.
- Finally run the `ovniemu ovni` command to generate the Paraver traces.
- Use the command `wxparaver ovni/cpu.prv` to load the CPU trace.
- Load the configurations from the `cfg/` directory that you are
interested in, to open a timeline view.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

View File

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 26 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,8 +1,9 @@
# Trace specification
!!! Note
!!! Important
Thie is the trace specification for the version 1
This document refers to the trace specification for
the version 1
The ovni instrumentation library stores the information collected in a
trace following the specification of this document.
@ -83,7 +84,7 @@ the variable size events just after the header.
The header contains the magic 4 bytes of "ovni" and a version number of
4 bytes too. Here is a figure of the data stored in disk:
<img src="stream.svg" alt="Stream" width="400px"/>
![Stream](fig/stream.svg)
Similarly, events have a fixed size header followed by an optional
payload of varying size. The header has the following information:
@ -103,7 +104,7 @@ There are two types of events, depending of the size needed for the
payload:
- Normal events: with a payload up to 16 bytes
- Jumbo events: with a payload up to 2^32 bytes
- Jumbo events: with a payload up to $`2^{32}`$ bytes
## Normal events
@ -124,7 +125,7 @@ bytes:
And in the following figure you can see every field annotated:
<img src="event-normal.svg" alt="Normal event without payload" width="400px"/>
![Normal event without payload](fig/event-normal.svg)
Another example of a normal event with 16 bytes of payload, a total of
28 bytes:
@ -136,7 +137,7 @@ ff ff ff ff 00 00 00 00 00 00 00 00 |............|
In the following figure you can see each field annotated:
<img src="event-normal-payload.svg" alt="Normal event with payload content" width="400px"/>
![Normal event with payload content](fig/event-normal-payload.svg)
## Jumbo events
@ -161,7 +162,7 @@ data:
In the following figure you can see each field annotated:
<img src="event-jumbo.svg" alt="Jumbo event" width="400px"/>
![Jumbo event](fig/event-jumbo.svg)
## Design considerations
@ -171,11 +172,13 @@ parser library would take no more than 2 days for a single developer.
The size of the events has been designed to be small, with 12 bytes per
event when no payload is used.
**Important:** The events are stored in disk following the endianness of
the machine where they are generated. So a stream generated with a little
endian machine would be different than on a big endian machine. We
assume the same endiannes is used to write the trace at runtime and read
it after, at the emulation process.
!!! Caution
The events are stored in disk following the endianness of the
machine where they are generated. So a stream generated with a
little endian machine would be different than on a big endian
machine. We assume the same endiannes is used to write the trace
at runtime and read it after, at the emulation process.
The events are designed to be easily identified when looking at the
raw stream in binary, as the MCV codes can be read as ASCII characters:

View File

@ -1,6 +1,8 @@
# Tracing a program
# Tracing a new program
Read carefully this document before using libovni to generate a trace.
Read carefully this document before using libovni to instrument a new
component. There are a few rules you must follow to ensure the runtime
trace is correct.
## Trace processes and threads

View File

@ -1,14 +1,25 @@
site_name: ovni
theme: readthedocs
docs_dir: doc
extra_css: [extra.css]
theme:
name: readthedocs
sticky_navigation: false
extra_javascript:
- https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-AMS-MML_HTMLorMML
markdown_extensions:
- admonition
- attr_list
- def_list
- mdx_math:
use_gitlab_delimiters: true
enable_dollar_delimiter: true
add_preview: true
- toc:
permalink: "#"
separator: "_"
nav:
- index.md
- concepts.md
- 'Runtime':
- runtime/tracing.md
- runtime/kernel.md
@ -20,3 +31,5 @@ nav:
- emulation/nanos6.md
- emulation/events.md
- emulation/channels.md
- 'Developer guide':
- developer-guide/index.md