MT/content/system_trace.tex

496 lines
26 KiB
TeX
Raw Normal View History

2020-08-20 17:39:46 +02:00
\section{System Trace}
\label{chapter:btf}
A trace is defined as a sequence of events. Events depict a change in the
state of a system and can be represented on different levels of abstraction.
These are discussed in more detail in \autoref{section:trace_measurement}.
For the timing analysis of embedded multi-core real-time systems a trace on
system level is required.
Tools that analyze or visualize traces must be able to interpret the recorded
events. For example, the software that interacts with hardware trace devices
must be able to understand the hardware events that are generated on-chip.
Otherwise it is not possible to transform the hardware events into higher level
software events. For that reason a well-defined format for events is required
for further processing of recorded traces.
Depending on the goal pursued with a trace measurement, one level of
abstraction can be more appropriate than another. On the one hand, a software
engineer who implements a feedback control system is mainly interested in the
functions and variables that correspond to that particular task. A system
engineer on the other hand, who integrates a variety of different modules into
a single application, is not interested in the details of each individual
module. Instead the functionality of the system as a whole is of interest.
\subsection{BTF Specification}
A trace on system level can be used to analyze timing, performance, and
reliability of an embedded system. \glsdesc{btf} (\gls{btf}) \cite{btf} was
specified to support these use cases. It assumes a signal processing system
where one entity influences another entity in the system. This means an event
does not only contain which system state changes but also the source of that
change. For example, an observed event on system level could be the activation
of a task with the corresponding timestamp. Then a \gls{btf} event
additionally contains the information that the task activation was triggered by
a certain alarm.
Let $k$ be an index in $\mathbb{N}_{0}$ denoting an individual event
occurrence then a \gls{btf} event can be defined as an octuple
\begin{equation}
\label{eq:btf_trace}
b_{k} = (t_k,\, \Psi_k,\, \psi_k,\, \iota_k,\, T_k,\, \tau_k,\, \alpha_k,\, \nu_k)
\end{equation}
where each element maps to a \gls{btf} field: $t_k$ is the \emph{timestamp},
$\Psi_k$ is the \emph{source}, $\psi_k$ is the \emph{source instance},
$\iota_k$ is the \emph{target type}, $T_k$ is the \emph{target}, $\tau_k$ is
the \emph{target instance}, $\alpha$ is the event \emph{action} and $\nu_k$ is
an optional \emph{note}.
A \gls{btf} trace can then be defined as a sequence of \gls{btf} events where
$n \in \mathbb{N}_{0}$ is the number of events in the trace:
\begin{equation}
B = (b_1, b_2, \dots, b_n)
\end{equation}
\begin{table}[]
\centering
\begin{tabular}{r|l}
Field & Meaning \\
\hline
time $(t)$ & Timestamp relative to a certain point in time. \\
source $(\Psi)$ & Entity that caused an event. \\
source instance $(\psi)$ & Entity instance that caused an event. \\
target type $(\iota)$ & Type of the entity that is influenced by an event. \\
target $(T)$ & Entity that is influenced by an event. \\
target instance $(\tau)$ & Entity instance that is influenced by an event. \\
action $(\alpha)$ & The way in which target is influenced by source. \\
note $(\nu)$ & An optional field that is used for certain events. \\
\end{tabular}
\caption[\gls{btf} event fields]{A \gls{btf} event consists of eight fields.
An event describes the way in which one system entity is influenced by
another one.}
\label{tab:btf_fields}
\end{table}
A \gls{btf} event can be represented textually as a comma-separated list where
each field maps to an element as shown in the following listing.
\vspace{1cm}
\begin{lstlisting}
12891, TASK_200MS, 3, SIG, EngineSpeed, 0, write, 42
\end{lstlisting}
\vspace{1cm}
The first field (\lstinline{12891}) represents the timestamp of the event. A
\gls{btf} trace contains the chronological order of events that occurred in a
system. Therefore, for each timestamp $t_k \in \mathbb{N}_{0}$ in a trace it
holds that $t_{k} \leq t_{k+1}$. All timestamps within the same trace must be
specified relative to a certain point in time, that can be chosen arbitrarily.
Hence, neither trace nor system start must occur at $t_0 = 0$. The time period
between two events $b_{k}$ and $b_{k+1}$ can be calculated as $\Delta t =
t_{k+1} - t_{k}$. If not specified otherwise, the unit for time is
nanoseconds.
A \gls{btf} event represents the notification of one entity by another. Each
entity has an unique name. In the previous example, the source entity $\Psi$
has the name \lstinline{TASK_200MS} and the target entity $T$ is called
\lstinline{EngineSpeed}.
The fourth field \lstinline{SIG} is the short representation of the target
entity type $\iota$. \autoref{tab:entity_overview} gives an overview of all
entity types and their corresponding short \glspl{id}. Entity types are
discussed in more detail in \autoref{subsection:btf_entity_types}. In this
example, the target entity \lstinline{EngineSpeed} is a signal. The source
entity type is not part of a \gls{btf} event.
Some entities, tasks, \glspl{isr}, runnables, and stimuli have a lifecycle.
This means at a certain point in time an entity becomes active in the system
and eventually it leaves the system. For example, the lifecycle of a task
starts with its activation and ends when it terminates. If \glspl{mta} are
allowed for an application, it is possible that multiple \emph{instances} of a
task are active at the same time. For those cases where multiple instances
of an entity are currently active, it is consequently not clear to which
instance of the entity the event refers.
Instance counter fields $\psi$ and $\tau$ are used to distinguish between
multiple instances of the same entity. The counters are integer values $\psi,
\tau \in \mathbb{N}_{0}$ that are incremented for each new entity becoming
active in the system. The first instance of an entity gets the counter value
$0$. \lstinline{TASK_200MS} has an instance counter value of \lstinline{3}
which means the event refers to the fourth instance of this entity. For
entities that do not have a lifecycle like signals, the counter field is not
relevant and $0$ can be used as a placeholder value.
The seventh field $\alpha$ represents the way in which the target entity is
influenced by the source entity. In this example \lstinline{TASK_200MS}
writes a new value to the signal entity \lstinline{EngineSpeed}. Depending on
source and target entity type, different actions are allowed by the
specification as discussed in \autoref{subsection:btf_actions}.
For signal write events the note field $\nu$ is used to denote the value that
is written to the signal in this case \lstinline{42}. The note field is only
required for certain events. \autoref{tab:btf_fields} summarizes the meaning
of the different \gls{btf} fields.
A \gls{btf} trace can be persisted in a \gls{btf} trace file. This file
contains two parts: a meta and a data section. The meta section is written at
the beginning of the file. It contains general information on the trace such
as \gls{btf} version, creator of the trace file, creation date, and time unit
used by the time field. Each meta attribute uses a separate line, starting
with a \lstinline{#}, followed by the attribute name, a space, and the
attribute definition.
\begin{code}
\begin{lstlisting}[caption={[An example \gls{btf} trace file]A \gls{btf} trace
file contains of two sections. A meta section at the beginning of a file
includes information such as creator, creation date and time unit. It is
followed by a data section that contains one event per line. Comments are
denoted by a number sign followed by a space.},
label={listing:btf_example}]
#version 2.1.4
#creator BTF-Writer (15.01.0.537)
#creationDate 2015-02-18T14:18:20Z
#timeScale ns
0, Sim, 0, STI, S_1MS, 0, trigger
0, S_1MS, 0, T, T_1MS_0, 0, activate
100, Core_0, 0, T, T_1MS_0, 0, start
100, T_1MS_1, 0, R, Runnable_0, 0, start
25000, T_1MS_1, 0, R, Runnable_0, 0, terminate
25100, Core_1, 0, T, T_1MS_0, 0, terminate
\end{lstlisting}
\end{code}
In the data section one \gls{btf} event is written per line in chronological
order. The first event of a trace is located directly after the meta section
and the last event at the end of the file. Comments are denoted by a
\lstinline{#} followed by a space. \autoref{listing:btf_example} shows an
example trace file.
\subsection{BTF Entity Types}
\label{subsection:btf_entity_types}
As shown in \autoref{tab:entity_overview} \gls{btf} specifies fourteen entity
types that can be classified into five categories: environment, software,
hardware, operating system, and information. Some entity types are not
relevant for this thesis and therefore only discussed briefly. The actions
or in other words the way in which one entity can be influenced by another
are defined for each entity type as discussed in
\autoref{subsection:btf_actions}. Actions for types that are classified as not
relevant are not considered.
\begin{table}[]
\centering
\begin{tabular}{c|c c c}
Category & Entity Type & Type \gls{id} & Relevant \\
\hline
Environment & Stimulus & STI & X \\
\hline
& Task & T & X \\
Software & \gls{isr} & I & X \\
& Runnable & R & X \\
& Instruction Block & IB & \\
\hline
& Electronic Control Unit & ECU & \\
Hardware & Processor & Processor & \\
& Core & C & X \\
& Memory Module & M & \\
\hline
& Scheduler & SCHED & \\
Operating System & Signal & SIG & X \\
& Semaphore & SEM & X \\
& Event & EVENT & X \\
\hline
Information & Simulation & SIM & X \\
\end{tabular}
\caption[\gls{btf} entity types]{\gls{btf} entity types can be divided into
five categories. Types that are relevant in the context of this thesis are
marked by an X.}
\label{tab:entity_overview}
\end{table}
\textbf{Environment} contains only the stimulus entity type. Stimuli are used
to depict application behavior that cannot be represented by other entity
types. A stimulus can be used to activate a task or \gls{isr} and to set a
signal value. Multiple stimulus instances can exist in a system at a certain
point in time. Thus, the instance counter field is required for stimulus
entities.
\textbf{Software} contains the task, \gls{isr}, runnable, and instruction block
types. Tasks and \glspl{isr} summarized by the term process are containers
for application software and discussed in \autoref{section:osekvdxos}.
Runnable is a term established by \gls{autosar} and relates to the concept of C
type functions. A runnable can be executed from the context of processes and
contains application specific functionality. Multiple runnables can be active
in a system at the same time for example, if the same runnable is executed by
two different tasks allocated to distinct cores. Hence, an instance counter is
required for runnable entities.
Instruction blocks are used to represent execution time within the context of
runnables. Since these execution times become available implicitly via the
corresponding runnable events, the addition of instruction blocks to a
\gls{btf} trace is optional and does not provide any immediate benefits.
\textbf{Hardware} contains the electronic control unit (ECU), processor, core,
and memory module types. An ECU consists of one or more processors. This
allows it to represent a multi-processor system. Generally, tracing only
supports the recording of a single processor. Multi-processor setups require a
way to synchronize the measurement between multiple trace measurement tools.
The design of such a setup is not in the scope of this thesis.
A processor is composed of one or more cores and recording multiple cores on
the same chip is feasible via tracing. Cores are necessary to map software and
\gls{os} events to the corresponding hardware entities. Since this information
is important for the analysis of embedded systems, cores are relevant for this
thesis.
Memory modules model different memory sections on a chip. They allow it to
represent memory related processes on the CPU such as access times to variables
or cache misses. According to Helm \cite{christianmaster}, direct measurement
of memory access times is not possible. Instead, dedicated code must be added
to the application in order to determine the execution times for different
memory access operations. Due to the intrusiveness of this approach it is not
feasible for real applications. Therefore, memory modules are not supported in
this thesis.
\textbf{Operating System} covers scheduler, signal, semaphore, and event
entity types. The scheduler entity type is used to represent actions executed
by the \gls{os} that relate to the scheduling of process instances. Scheduler
events become available implicitly via the respective process actions and are
thus not considered in this thesis.
Signals represent access to variables that are relevant for the analysis of an
application. Consequently, signal events must be added to a \gls{btf} trace
that is recorded from hardware.
Semaphores entities are used to control access to common resources in parallel
systems. A process can request a semaphore before it enters a critical
section, e.g.\ a section that contains an access to a memory region that is
vulnerable to race conditions. If the semaphore is free the request is
accepted, the semaphore is locked and all subsequent requests fail. Once the
process has left the critical section it releases the semaphore.
Events are objects for inter-process communication provided by the \gls{os}.
One process can use an event to notify another one for example, when a
computation finishes or a resource becomes available. Event entities do not
have a lifecycle therefore, no instance counter value is required.
\textbf{Information} contains only the simulation entity type. This entity
type has two purposes. Firstly, it can be used to provide information about
errors that occurred during trace recording. Secondly, it is required to
trigger stimulus events. Since stimulus events are mandatory to represent task
activations by non process objects, the simulation entity must be considered in
the context of this thesis. Because \emph{simulation} does not make sense in a
trace recorded from hardware \emph{system} can be used as a more appropriate
term.
\subsection{BTF Actions}
\label{subsection:btf_actions}
\gls{btf} specifies different actions. The available actions are dependent on
the source and target entity types of the respective event.
\textbf{Stimuli} only support the \emph{trigger} action. A stimulus can be
triggered by process and simulation entities. Once a stimulus is triggered it
can be used for the actual event: the activation of a task or \gls{isr} or to
set the value of a signal.
\begin{figure}[]
\centering
\centerline{\includegraphics[width=\textwidth]{./media/btf/process_state_chart.png}}
\caption[Process state figure]{\gls{btf} \cite{btf} specifies more process
states than \gls{osek} (compare \autoref{fig:extended_task_state_model}). The
additional states polling and parking are required to represent active
waiting. Not initialized and terminated indicate the beginning and end of a
process lifecycle. The green boxes between the states show the name of the
\gls{btf} action for the respective transition.}
\label{fig:process_state_chart}
\end{figure}
\textbf{Process} entities support the actions shown in
\autoref{fig:process_state_chart}. A process instance starts in the \emph{not
initialized} state. From there it can be \emph{activated} in order to switch
into the \emph{active} state by a stimulus entity. All state transitions
except \emph{activate} are executed by core entities. An active process is
changed into the \emph{running} state as soon as it is scheduled by the
\gls{os}.
A running process can \emph{preempt}, \emph{terminate}, \emph{poll}, and
\emph{wait}. Preemption occurs if another process is scheduled to be executed
on the core. In this case, the current process changes into the \emph{ready}
state. A ready process \emph{resumes} running once the core becomes available
again. If a process finishes execution it \emph{terminates} and switches into
the \emph{terminated} state. This finishes the lifecycle of a process
instance.
A process that \emph{polls} a resource switches into the active waiting state
\emph{polling}. If the resource becomes available, the process continues
running which is indicated by the \emph{run} action. A process that
\emph{waits} for an event switches into the passive waiting state
\emph{waiting}. A \emph{waiting} process is \emph{released} into the ready
state if one of the requested events becomes available.
A polling process that is removed from the core is \emph{parked} and switched
into the \emph{parking} state. If the resource becomes available while the
process is parking it is switched into the ready state. This transition is
called \emph{release\_parking}. Otherwise the process continues polling, once
it is reallocated to the core which is called \emph{poll\_parking}.
In addition to state transition actions, \gls{btf} specifies process
notification actions. These actions do not trigger a process state change but
indicate other events related to a process entity. The \emph{mtalimitexceeded}
action is triggered if more process instances than allowed are activated in
parallel. If this happens, no new task instance is created. Therefore, a
notification event is necessary to make the event visible in the trace.
All other process notification actions are related to migration the
reallocation of a process from one core to another. \gls{osekos} does not
support process migration since a separate kernel is executed on each core.
Thus migration notifications are not relevant for an \gls{osek} compliant
\gls{os}. Additionally, migration actions become available implicitly via the
respective process transition actions. If a process instance is preempted on
one core and resumed on another, the resume event has a different source core
than the preempt event. Consequently, the related migration event is known.
\begin{figure}[]
\centering
\centerline{\includegraphics[width=0.8\textwidth]{./media/btf/runnable_state_chart.png}}
\caption[Runnable state figure]{\gls{btf} runnable states and state
transitions \cite{btf}.}
\label{fig:runnable_state_chart}
\end{figure}
\textbf{Runnable} instances start in the \emph{not initialized} state as shown
in \autoref{fig:runnable_state_chart}. Runnables can be \emph{started} by
\glspl{isr} and tasks in order to switch into the \emph{running} state. A
runnable instance that \emph{terminates} switches into the \emph{terminated}
stated and therefore finishes its lifecycle.
Because a runnable can only be executed from process context, it can not
continue running if the respective process is preempted. In this case the
runnable must be \emph{suspended}. Once the process resumes execution the
runnable can also \emph{resume}.
\textbf{Core} entities are used to provide an execution context for process
entities and cannot be used as a target entity themselves. Consequently, no
\gls{btf} core actions are specified. Only one process can be allocated to a
core at the same time and core entities do not have a lifecycle.
\textbf{Signal} entities can be influenced by two actions: \emph{read} and
\emph{write}. A signal can be read within the context of a process entity.
This means that the value of a variable is retrieved from memory. A signal
entity does not have a lifecycle thus, the instance counter value for signals
can remain constant.
Write actions can be executed by process and stimulus entities. They indicate
that a new value is assigned to a variable. If this assignment is done from
process context, the respective process entity is the source for the write
event. Otherwise, a stimulus entity can be used to represent the source for
example, if a signal is changed by the \gls{os} or a hardware module.
For signal writes, the note field must denote the value that was assigned to a
variable. For read events the note field can optionally indicate the value of
the variable that was accessed.
\textbf{Semaphores} can be categorized into different types. Counting
se\-ma\-phores can be requested multiple times. They have an initial counter
value of zero. For every request, this counter is incremented and every time
it is released the value is decremented. A counting semaphore is locked once
the counter has reached a predefined value.
A binary semaphore is a specialization of a counting semaphore for which the
maximum counter value is one. A mutex is a binary semaphore that supports an
ownership concept. This means a mutex knows all processes that may request it.
This information allows the implementation of priority ceiling protocols in
order to avoid deadlocks and priority inversion. The \gls{osek} term for mutex
is \emph{resource}, resources are discussed in
\autoref{subsection:osek_architecture}.
\gls{btf} semaphore events can represent all mentioned semaphore types.
Semaphore actions can be divided into two categories: actions triggered by
process instances as shown in \autoref{tab:semaphore_process} and actions
executed by a semaphore entity itself as shown in
\autoref{fig:semaphore_state_chart}.
\begin{table}[]
\centering
\begin{tabular}{r l}
Action & Meaning \\
\hline
requestsemaphore & Process requests a semaphore. \\
exclusivesemaphore & Process requests a semaphore exclusively. \\
assigned & Process is assigned as the owner of a semaphore. \\
waiting & Process is assigned as waiting to a locked semaphore.\\
released & Assignment from process to semaphore is removed. \\
increment & Semaphore counter is incremented. \\
decrement & Semaphore counter is decremented. \\
\end{tabular}
\caption[Semaphore process actions]{Processes can interact with semaphores in
different ways. If a process requests a semaphore successfully, it is
\emph{assigned} to the semaphore and the counter is \emph{incremented},
otherwise a \emph{waiting} event is triggered. Once a semaphore is
\emph{released}, the assignment is removed and the counter is
\emph{decremented}.}
\label{tab:semaphore_process}
\end{table}
\begin{figure}[]
\centering
\centerline{\includegraphics[width=\textwidth]{./media/btf/semaphore_state_chart.png}}
\caption[Semaphore states and actions]{\gls{btf} \cite{btf} semaphore entities
do not have a lifecycle. Nevertheless, they must be \emph{initialized} before
they are ready for the first time. A semaphore can be \emph{unlocked} or
\emph{locked}. A counting semaphore can be requested multiple times in which
case it changes into the \emph{used} state. If there are no requests the
semaphore is \emph{free}. A semaphore that has at least as many requests as
allowed is \emph{full} and changes into the \emph{locked} state. Further
requests in the locked stated result in an \emph{overfull} action.}
\label{fig:semaphore_state_chart}
\end{figure}
A process request to a semaphore is indicated by \emph{requestsemaphore}. If a
request is successful the semaphore counter is \emph{incremented} and the
process is \emph{assigned} to the semaphore. The \emph{exclusivesemaphore}
action represents a semaphore request that only succeeds, if the semaphore is
currently not requested by any other process, i.e. the counter value is zero.
If a process fails to request a semaphore and switches into polling mode,
indicated by the \emph{waiting} action. A process that releases a semaphore
\emph{decrements} the semaphore counter and the respective semaphore is
\emph{released}, the process is no longer assigned to it.
Semaphores do not have a lifecycle which is why their instant counter remains
constant. Nevertheless, a semaphore must be moved from the \emph{not
initialized} to the \emph{free} state by the \emph{ready} action before it is
requested for the first time.
A free semaphore is not requested by any process. At the first request the
behavior is dependent on the semaphore type. A mutex or binary semaphore is
\emph{locked} and moved into the \emph{full} state. A counting semaphored is
changed into the \emph{used} state which is indicated by the \emph{used}
action. The used action is repeated for a counting semaphore for each further
request or release as long as the counter value stays greater than zero and
smaller than the maximum value. If the counter value of a used semaphore
becomes zero this semaphore is \emph{freed}. If the maximum counter value is
reached the semaphore state becomes \emph{full} which is indicated by the
\emph{lock\_used} action.
When a full binary semaphore or mutex is released, it is \emph{unlocked} and
becomes free again, while a counting semaphore is changed back to the used
state, indicated by the \emph{unlock\_full} action. A request to a full
semaphore entity results in an \emph{overfull} action and the state is changed
to \emph{overfull}. The overfull state indicates that there is at least one
process polling a semaphore. Each additional request also results in an
overfull action. Once there are no more processes waiting for a semaphore,
this semaphore becomes \emph{full} again.
\textbf{Events} can be influenced by three different actions. If a process
starts waiting for an event, this is indicated by the \emph{wait\_event}
action. Another process can set an event via the \emph{set\_event} action.
For this action it is necessary to provide the entity for which the event is
set via the \gls{btf} note field. An event can be cleared by the process for
which the event was set which is indicated by \emph{clear\_event}.