ovni/doc/emulation/channels.md

171 lines
6.1 KiB
Markdown

# Channels
As the emulation progresses, information is written in the PRV trace to
record the new states. The emulator has specific mechanism to handle the
output of new states in the PRV trace via channels. A channel stores an
integer that represents an state at a given point in time and
corresponds to the value that will be observed in the Paraver timeline.
!!! Note
In general, the emulator receives events, then performs a state
transition and the new state (or states) are written into the
PRV file.
There are two classes of channels: CPU and thread channels. Both CPU and
threads have the same fixed number of channels, given by the enumeration
`enum chan`.
For example the `CHAN_OVNI_STATE` of the thread stores the execution
state of the thread (running, paused ...). Whereas, the CPU channel
`CHAN_OVNI_NRTHREADS` records how many running threads a given CPU has.
The channels are used in the following way:
- In the "pre" phase, the emulator modifies the state of the emulator
based on the new event. The channels are then updated accordingly in
this phase, for example when a thread goes from running to paused it
must update the `CHAN_OVNI_STATE` channel of the thread by also the
`CHAN_OVNI_NRTHREADS` channel of the CPU.
- In the "emit" phase, the emulator calls the `chan_emit()` method on
those channels that have been modified. Those have the dirty attribute
set to 1.
- The optional "post" phase is used to perform some operations before
the next event is loaded, but is not commonly used.
Then the emulator then loads the next event and repeats the process
again.
## Disabling and enabling channels
Some channels provide information that only makes sense in some
conditions. For example, the CPU channel `CHAN_OVNI_TID` tracks the TID
of the thread currently running in the CPU. When there is no thread
running or there are multiple threads running in the same CPU, this
channel cannot output valid information.
For those cases, the channels can be enabled or disabled as to only
provide information when it is necessary. When a channel is disabled, it
will emit the value stored in `badst` which by default is set to 0.
Notice that if a channel was in a given state A, and was disabled, it
must emit the new state is 0. When the channel is enabled again, it will
emit again the state A.
## Thread tracking channels
Regarding thread channels, there are two common conditions that cause
the channels to become disabled. When the thread is no longer running,
and then the thread is not active.
For those cases, the thread channels can be configured to automatically
be enabled or disabled, following the execution state of the thread. The
tracking mode specifies how the tracking must be done:
- `CHAN_TRACK_NONE`: nothing to track
- `CHAN_TRACK_RUNNING_TH`: enable the channel only if the thread is
running
- `CHAN_TRACK_ACTIVE_TH`: enable the channel only if the thread is
running, cooling or warming.
This mechanism removes the complexity of detecting when a thread stops
running, to update a channel of a given module. As the thread state
changes as handled by the `emu_ovni.c` module only.
## CPU tracking channels
Similarly, CPU channels can also be configured to track the execution
state of the threads. They become disabled when the tracking condition
is not met, but also copy the state of the tracking thread channel.
They share the same tracking modes, but their behavior is slightly
different:
In the case of tracking the running thread, if the CPU has more than one
thread running, the channel will always output the error state
`ST_TOO_MANY_TH`.
If is has no threads running, will be disabled and emit a 0 state by
default.
Otherwise, it will emit the same value as the running thread. If the
thread channel is disabled, it will emit a `ST_BAD` error state.
Regarding the active thread tracking mode, the CPU channels behave
similarly, but with the active threads instead of running ones.
The CPU tracking mechanism simplify the process of updating CPU
channels, as the modules don't need to worry about the execution model.
Only the channels need to be configured to follow the proper execution
state.
## Channel state modes
The channels can be updated in three ways:
1. A fixed state can be set to the channel using `chan_set()`, which
overrides the previous state.
2. The new state can be stored in a stack with `chan_push()` and
`chan_pop()`, to remember the history of the previous states. The
emitted event will be the one on the top.
3. Using a punctual event.
Setting the channel state is commonly used to track quantities such as
the number of threads running per CPU. While the stack mode is commonly
used to track functions or sections of code delimited with enter and
exit events, which can call an return to the previous state.
An example program may be instrumented like this:
int bar() {
instr("Xb[");
...
instr("Xb]");
}
int foo() {
instr("Xf[");
bar();
instr("Xf]");
}
Then, in the emulator, when processing the events `Xf[` and `Xf]`, we
could track of the state as follows:
int hook_pre_foo(struct ovni_chan *chan, int value) {
switch(value) {
case '[': chan_push(chan, 2); break;
case ']': chan_pop(chan, 2); break;
default: break;
}
}
int hook_pre_bar(struct ovni_chan *chan, int value) {
switch(value) {
case '[': chan_push(chan, 1); break;
case ']': chan_pop(chan, 1); break;
default: break;
}
}
The channel will emit the following sequence of states: 0, 1, 2, 1, 0.
Notice that the `chan_pop()` function uses the same state being pop()'ed
as argument. The function checks that the stack contains the expected
state, forcing the emulator to always receive a matching pair of enter
and exit events.
## Punctual events
There are some conditions that are better mapped to events rather than
to state transitions. For those cases, the channels provide punctual
events which are emitted as a state than only has 1 ns of duration.
When a channel is configured to emit a punctual event with `chan_ev()`,
it will first output the new state at the current time minus 1 ns, then
restore the previous channel state and emit it at the current time.