diff --git a/doc/concepts.md b/doc/concepts.md
new file mode 100644
index 0000000..c867319
--- /dev/null
+++ b/doc/concepts.md
@@ -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)
diff --git a/doc/developer-guide/index.md b/doc/developer-guide/index.md
new file mode 100644
index 0000000..ea8a890
--- /dev/null
+++ b/doc/developer-guide/index.md
@@ -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.
diff --git a/doc/emulation/events.md b/doc/emulation/events.md
index 1f22d19..91cbecf 100644
--- a/doc/emulation/events.md
+++ b/doc/emulation/events.md
@@ -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
diff --git a/doc/emulation/fig/model.dot b/doc/emulation/fig/model.dot
new file mode 100644
index 0000000..116e359
--- /dev/null
+++ b/doc/emulation/fig/model.dot
@@ -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"];
+}
diff --git a/doc/emulation/model.png b/doc/emulation/fig/model.png
similarity index 100%
rename from doc/emulation/model.png
rename to doc/emulation/fig/model.png
diff --git a/doc/emulation/fig/model.svg b/doc/emulation/fig/model.svg
new file mode 100644
index 0000000..c445357
--- /dev/null
+++ b/doc/emulation/fig/model.svg
@@ -0,0 +1,385 @@
+
+
+
+
+
diff --git a/doc/emulation/fig/nanos6-task-model.dot b/doc/emulation/fig/nanos6-task-model.dot
new file mode 100644
index 0000000..8d7e28b
--- /dev/null
+++ b/doc/emulation/fig/nanos6-task-model.dot
@@ -0,0 +1,11 @@
+digraph {
+ rankdir=LR;
+
+ { rank=same; Running; Paused; }
+
+ Unknown -> Created;
+ Created -> Running;
+ Running -> Paused;
+ Paused -> Running;
+ Running -> Dead;
+}
diff --git a/doc/emulation/fig/nanos6-task-model.svg b/doc/emulation/fig/nanos6-task-model.svg
new file mode 100644
index 0000000..f36e8f0
--- /dev/null
+++ b/doc/emulation/fig/nanos6-task-model.svg
@@ -0,0 +1,72 @@
+
+
+
+
+
diff --git a/doc/emulation/fig/thread-model.dot b/doc/emulation/fig/thread-model.dot
new file mode 100644
index 0000000..24daa4d
--- /dev/null
+++ b/doc/emulation/fig/thread-model.dot
@@ -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"];
+}
diff --git a/doc/emulation/ovni/thread-model.png b/doc/emulation/fig/thread-model.png
similarity index 100%
rename from doc/emulation/ovni/thread-model.png
rename to doc/emulation/fig/thread-model.png
diff --git a/doc/emulation/fig/thread-model.svg b/doc/emulation/fig/thread-model.svg
new file mode 100644
index 0000000..c64171f
--- /dev/null
+++ b/doc/emulation/fig/thread-model.svg
@@ -0,0 +1,104 @@
+
+
+
+
+
diff --git a/doc/emulation/index.md b/doc/emulation/index.md
index 46d9c63..3023741 100644
--- a/doc/emulation/index.md
+++ b/doc/emulation/index.md
@@ -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.
diff --git a/doc/emulation/nanos6.md b/doc/emulation/nanos6.md
index 33e7e66..e6c78cd 100644
--- a/doc/emulation/nanos6.md
+++ b/doc/emulation/nanos6.md
@@ -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
diff --git a/doc/emulation/nosv.md b/doc/emulation/nosv.md
index 51167ae..7d5b541 100644
--- a/doc/emulation/nosv.md
+++ b/doc/emulation/nosv.md
@@ -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.
diff --git a/doc/emulation/ovni.md b/doc/emulation/ovni.md
index 2412a83..c945d03 100644
--- a/doc/emulation/ovni.md
+++ b/doc/emulation/ovni.md
@@ -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.
diff --git a/doc/extra.css b/doc/extra.css
index 9799b33..6704cc6 100644
--- a/doc/extra.css
+++ b/doc/extra.css
@@ -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 {
diff --git a/doc/fig/instrumentation.dot b/doc/fig/instrumentation.dot
new file mode 100644
index 0000000..6f49d82
--- /dev/null
+++ b/doc/fig/instrumentation.dot
@@ -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";
+}
diff --git a/doc/fig/instrumentation.svg b/doc/fig/instrumentation.svg
new file mode 100644
index 0000000..4fd1889
--- /dev/null
+++ b/doc/fig/instrumentation.svg
@@ -0,0 +1,78 @@
+
+
+
+
+
diff --git a/doc/logo.png b/doc/fig/logo.png
similarity index 100%
rename from doc/logo.png
rename to doc/fig/logo.png
diff --git a/doc/fig/logo2.png b/doc/fig/logo2.png
new file mode 100644
index 0000000..cf10abd
Binary files /dev/null and b/doc/fig/logo2.png differ
diff --git a/doc/fig/visualization.png b/doc/fig/visualization.png
new file mode 100644
index 0000000..9b86f83
Binary files /dev/null and b/doc/fig/visualization.png differ
diff --git a/doc/index.md b/doc/index.md
index ab01c4a..c76b124 100644
--- a/doc/index.md
+++ b/doc/index.md
@@ -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.
diff --git a/doc/logo2.png b/doc/logo2.png
deleted file mode 100644
index 78ac0f9..0000000
Binary files a/doc/logo2.png and /dev/null differ
diff --git a/doc/runtime/trace_spec/event-jumbo.svg b/doc/runtime/fig/event-jumbo.svg
similarity index 100%
rename from doc/runtime/trace_spec/event-jumbo.svg
rename to doc/runtime/fig/event-jumbo.svg
diff --git a/doc/runtime/trace_spec/event-normal-payload.svg b/doc/runtime/fig/event-normal-payload.svg
similarity index 100%
rename from doc/runtime/trace_spec/event-normal-payload.svg
rename to doc/runtime/fig/event-normal-payload.svg
diff --git a/doc/runtime/trace_spec/event-normal.svg b/doc/runtime/fig/event-normal.svg
similarity index 100%
rename from doc/runtime/trace_spec/event-normal.svg
rename to doc/runtime/fig/event-normal.svg
diff --git a/doc/runtime/trace_spec/stream.svg b/doc/runtime/fig/stream.svg
similarity index 100%
rename from doc/runtime/trace_spec/stream.svg
rename to doc/runtime/fig/stream.svg
diff --git a/doc/runtime/trace_spec.md b/doc/runtime/trace_spec.md
index 0b01f39..c7daf4e 100644
--- a/doc/runtime/trace_spec.md
+++ b/doc/runtime/trace_spec.md
@@ -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:
-
+![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:
-
+![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:
-
+![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:
-
+![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:
diff --git a/doc/runtime/tracing.md b/doc/runtime/tracing.md
index 47d70a7..72f07c4 100644
--- a/doc/runtime/tracing.md
+++ b/doc/runtime/tracing.md
@@ -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
diff --git a/mkdocs.yml b/mkdocs.yml
index 2944875..2f27a70 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -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