promela expl done (minus ltl)
This commit is contained in:
parent
422c06c7aa
commit
1e25f0d9d1
2 changed files with 112 additions and 1 deletions
BIN
report.pdf
BIN
report.pdf
Binary file not shown.
113
report.tex
113
report.tex
|
@ -159,7 +159,118 @@ init {
|
|||
|
||||
Each of the enumerated sections is surrounded by curly braces to emulate the
|
||||
effect of locally scoped variables in procedures, which do not exist in
|
||||
\textit{ProMeLa} aside the cuncurrency-like \texttt{proctype} construct.
|
||||
\textit{ProMeLa} aside the concurrency emulating \texttt{proctype} construct.
|
||||
|
||||
The array initialization is carried out as follows:
|
||||
|
||||
\begin{minted}{c}
|
||||
int i;
|
||||
for (i in to_reverse) {
|
||||
int value;
|
||||
select(value: 0 .. R);
|
||||
to_reverse[i] = value;
|
||||
printf("to_reverse[%d]: %d\n", i, value);
|
||||
}
|
||||
\end{minted}
|
||||
|
||||
As specified above, the array is initialized with values in $[0,R]$.
|
||||
Specifically, values are generated using a nondeterministic \texttt{select}
|
||||
statement to allow the model checker to try all possible values efficiently.
|
||||
|
||||
The sequential reversed algorithm is implemented with the following code:
|
||||
|
||||
\begin{minted}{c}
|
||||
int k;
|
||||
for (k: 0 .. (LENGTH - 1)) {
|
||||
reversed_seq[LENGTH - k - 1] = to_reverse[k];
|
||||
printf("reversed_seq[%d] = to_reverse[%d]\n", LENGTH - k - 1, k);
|
||||
}
|
||||
done[0] = true;
|
||||
\end{minted}
|
||||
|
||||
which is a direct translation of the Java implementation to verify.
|
||||
|
||||
The sequential reverser is used to implement each thread of the parallel
|
||||
reverser through the \textit{ThreadedReverser} class. In the model, the class is
|
||||
translated in a Spin process through the \texttt{proctype} construct with the
|
||||
following implementation:
|
||||
|
||||
\begin{minted}{c}
|
||||
proctype ThreadedReverser(int from; int to; int n) {
|
||||
printf("proc[%d]: started from=%d to=%d\n", n, from, to);
|
||||
int k;
|
||||
for (k: from .. (to - 1)) {
|
||||
printf("reversed_par[%d] = to_reverse[%d]\n", LENGTH - k - 1, k);
|
||||
reversed_par[LENGTH - k - 1] = to_reverse[k];
|
||||
}
|
||||
printf("proc[%d]: ended\n", n);
|
||||
done[n] = true;
|
||||
}
|
||||
\end{minted}
|
||||
|
||||
The implementation is closely related to the sequential one, as it differs only
|
||||
in \texttt{reversed\_par} being used as the destination array and limiting the
|
||||
reversal between \texttt{from} and \texttt{to}. The argument \texttt{n} is used
|
||||
to identify the thread in the \texttt{done} array to store the termination
|
||||
state. Following the indexing rules of \texttt{done} given earlier, the i-th
|
||||
spawned thread corresponds to a \texttt{proctype} call with $n = i$, so that at
|
||||
termination \mintinline{c}{done[i]} is set to \mintinline{c}{true}.
|
||||
|
||||
The actual thread-spawning part of the parallel reverser, i.e.\ class
|
||||
\textit{ParallelReverser} itself, is represented by the following
|
||||
\textit{ProMeLa} code placed in the \texttt{init} section of the model:
|
||||
|
||||
\begin{minted}{c}
|
||||
int n;
|
||||
int s = LENGTH / N;
|
||||
for (n: 0 .. (N - 1)) { // fork loop
|
||||
int from = n * s;
|
||||
int to;
|
||||
if
|
||||
:: (n == N - 1) -> to = LENGTH;
|
||||
:: else -> to = n * s + s;
|
||||
fi
|
||||
run ThreadedReverser(from, to, n + 1); // fork here
|
||||
}
|
||||
for (n: 1 .. N) { // join loop
|
||||
(done[n] == true); // join n-th thread here
|
||||
printf("[%d] joined\n", n);
|
||||
}
|
||||
\end{minted}
|
||||
|
||||
Here the values of \texttt{n}, \texttt{s}, \texttt{from} and \texttt{to}
|
||||
replicate exactly the values used in the Java implementation. The \texttt{n + 1}
|
||||
parameter identifies maps each \texttt{proctype} invocation to its place in the
|
||||
invocation order (e.g.\ for $n=0$, \texttt{ThreadedReverser} is called with
|
||||
$n+1=1$, since this is the 1st invocation of the process).
|
||||
|
||||
The second ``join'' loop waits for each process to complete in order of
|
||||
invocation, replication the thread joining behaviour of the parallel reverser
|
||||
implementation in the Java program. Note that the \textit{ProMeLa} statement
|
||||
\mintinline{c}{(done[n] == true);} will ``wait'' for the value of
|
||||
\mintinline{c}{done[n]} to be \mintinline{c}{true} before executing the
|
||||
following statement, thus being an adequate analogy for
|
||||
\mintinline{java}{Thread.join()}.
|
||||
|
||||
Finally, the congruence check between the arrays produced by both implementation
|
||||
is implemented with the following code:
|
||||
|
||||
\begin{minted}{c}
|
||||
int i;
|
||||
for (i: 0 .. (LENGTH - 1)) {
|
||||
if
|
||||
:: (reversed_seq[i] != reversed_par[i]) -> seq_eq_to_parallel = false;
|
||||
fi
|
||||
}
|
||||
\end{minted}
|
||||
|
||||
Should any matching pair of elements be different,
|
||||
\texttt{seq\_eq\_to\_parallel} will be set to \mintinline{c}{false}. Note that
|
||||
this boolean variable is used to implement one of the LTL properties, hence why
|
||||
it is declared and set to a meaningful value in this block of the model.
|
||||
|
||||
\subsection{LTL properties}
|
||||
|
||||
|
||||
The citation \cite{tange_2023_7855617}.
|
||||
The citation \cite{spin}.
|
||||
|
|
Reference in a new issue