| 1 | \part{Introduction}
|
|---|
| 2 | \label{part:intro}
|
|---|
| 3 |
|
|---|
| 4 | \chapter{Acknowledgement}
|
|---|
| 5 |
|
|---|
| 6 | The CIVL project is funded by the U.S.\ National Science Foundation
|
|---|
| 7 | under awards CCF-1346769 and CCF-1346756.
|
|---|
| 8 |
|
|---|
| 9 | \chapter{What is CIVL?}
|
|---|
| 10 |
|
|---|
| 11 | \textbf{CIVL} stands for \emph{Concurrency Intermediate Verification
|
|---|
| 12 | Language}. The \emph{CIVL platform} encompasses:
|
|---|
| 13 | \begin{enumerate}
|
|---|
| 14 | \item the programming language \textbf{CIVL-C}, a dialect of C with
|
|---|
| 15 | additional primitives supporting concurrency, specification, and modeling;
|
|---|
| 16 | \item verification and
|
|---|
| 17 | analysis tools, including a symbolic execution-based model checker for
|
|---|
| 18 | checking various properties of, or finding defects in, CIVL-C
|
|---|
| 19 | programs; and
|
|---|
| 20 | \item tools that translate from many commonly used
|
|---|
| 21 | languages/APIs to CIVL-C.
|
|---|
| 22 | \end{enumerate}
|
|---|
| 23 |
|
|---|
| 24 | The CIVL-C language is primarily intended to be an intermediate
|
|---|
| 25 | representation for verification. A C program using
|
|---|
| 26 | MPI~\cite{mpi-forum:2012:mpi30}, CUDA~\cite{cuda-programming-guide},
|
|---|
| 27 | OpenMP~\cite{openmp-standard}, OpenCL~\cite{opencl-standard}, or
|
|---|
| 28 | another API (or even some combination of APIs), will be automatically
|
|---|
| 29 | translated into CIVL-C and then verified. The advantages of such a
|
|---|
| 30 | framework are clear: the developer of a new verification technique
|
|---|
| 31 | could implement it for CIVL-C and then immediately see its impact
|
|---|
| 32 | across a broad range of concurrent programs. Likewise, when a new
|
|---|
| 33 | concurrency API is introduced, one only needs to implement a
|
|---|
| 34 | translator from it to CIVL-C in order to reap the benefits of all the
|
|---|
| 35 | verification tools in the platform. Programmers would have a valuable
|
|---|
| 36 | verification and debugging tool, while API designers could use CIVL as
|
|---|
| 37 | a ``sandbox'' to investigate possible API modifications, additions,
|
|---|
| 38 | and interactions.
|
|---|
| 39 |
|
|---|
| 40 | This manual covers all aspects of the CIVL framework, and is organized in parts
|
|---|
| 41 | as follows:
|
|---|
| 42 | \begin{enumerate}
|
|---|
| 43 | \item this introduction, including ``quick start'' instructions for
|
|---|
| 44 | downloading and installing CIVL and several examples;
|
|---|
| 45 | \item a complete description of the CIVL-C language;
|
|---|
| 46 | \item a formal semantics for the language; and
|
|---|
| 47 | \item a description of the tools in the framework.
|
|---|
| 48 | \end{enumerate}
|
|---|
| 49 |
|
|---|
| 50 | \chapter{Installation and Quick Start}
|
|---|
| 51 |
|
|---|
| 52 | This chapter gives instructions for downloading and installing CIVL,
|
|---|
| 53 | and running the verification tool on an example.
|
|---|
| 54 |
|
|---|
| 55 | \textbf{Note.} The following instructions explain how to install CIVL
|
|---|
| 56 | under the directory \texttt{/opt}, which is the standard installation
|
|---|
| 57 | point. If you do not wish to install CIVL there (e.g., because you
|
|---|
| 58 | don't want to use \texttt{sudo}, or you want to install it in your
|
|---|
| 59 | home directory), you can just modify the instructions by replacing
|
|---|
| 60 | \texttt{/opt} with another directory. You will just need to edit the
|
|---|
| 61 | script file \texttt{civl} appropriately, replacing the default paths
|
|---|
| 62 | with your chosen paths.
|
|---|
| 63 |
|
|---|
| 64 | \begin{enumerate}
|
|---|
| 65 | \item Download and unpack the appropriate pre-compiled library of CIVL
|
|---|
| 66 | dependencies from
|
|---|
| 67 | \url{http://vsl.cis.udel.edu/tools/vsl_depend/}.
|
|---|
| 68 | There are versions for Darwin (OS X), 32-bit Linux, and 64-bit Linux.
|
|---|
| 69 | After unpacking, you should have a directory named \texttt{vsl}.
|
|---|
| 70 | \item If you do not already have a directory \texttt{/opt},
|
|---|
| 71 | create it; use \texttt{sudo} as needed (\verb!sudo mkdir /opt!).
|
|---|
| 72 | \item Move the directory \texttt{vsl} into \texttt{/opt}
|
|---|
| 73 | (\verb!mv vsl /opt!).
|
|---|
| 74 | \item Download and unpack the latest stable release of CIVL from
|
|---|
| 75 | \url{http://vsl.cis.udel.edu/civl}. Again there are versions
|
|---|
| 76 | for Darwin, 32-bit Linux, and 64-bit Linux.
|
|---|
| 77 | \item The resulting directory should be named
|
|---|
| 78 | \texttt{CIVL-\textit{tag}} for some string \textit{tag} which
|
|---|
| 79 | identifies the version of CIVL you downloaded. Move this directory
|
|---|
| 80 | into \texttt{/opt} (\texttt{mv\ CIVL-\textit{tag}\ /opt}).
|
|---|
| 81 | \item There should now be an executable script at
|
|---|
| 82 | \texttt{/opt/CIVL-\textit{tag}/bin/civl}. Move this script into
|
|---|
| 83 | your path, or create a symlink from somewhere in your path to it, or
|
|---|
| 84 | add the directory \texttt{/opt/CIVL-\textit{tag}/bin} to your path.
|
|---|
| 85 | \end{enumerate}
|
|---|
| 86 |
|
|---|
| 87 | From the command line, you should now be able to type ``\texttt{civl
|
|---|
| 88 | help}'' and see a help message describing the command line syntax.
|
|---|
| 89 |
|
|---|
| 90 | Copy the file
|
|---|
| 91 | \texttt{CIVL-\textit{tag}/examples/concurrency/locksBad.cvl} to your
|
|---|
| 92 | working directory. Look at the program: it is a simple 2-process
|
|---|
| 93 | program with two shared variables used as locks. The two processes
|
|---|
| 94 | try to obtain the locks in opposite order, which can lead to a
|
|---|
| 95 | deadlock if both processes obtain their first lock before either
|
|---|
| 96 | obtains the second. Type
|
|---|
| 97 | ``\verb!civl verify locksBad.cvl!''. You should see some output
|
|---|
| 98 | culminating in a message
|
|---|
| 99 | \begin{verbatim}
|
|---|
| 100 | The program MAY NOT be correct. See CIVLREP/locksBad_log.txt
|
|---|
| 101 | \end{verbatim}
|
|---|
| 102 |
|
|---|
| 103 | Type ``\verb!civl replay locksBad.cvl!''. You should see a
|
|---|
| 104 | step-by-step account of how the program arrived at the deadlock.
|
|---|
| 105 |
|
|---|
| 106 |
|
|---|
| 107 | \chapter{Examples}
|
|---|
| 108 |
|
|---|
| 109 | In this section we show a few simple CIVL-C programs which illustrate
|
|---|
| 110 | some of the pertinent features of the language. We also show the results
|
|---|
| 111 | of running some of the tools on them.
|
|---|
| 112 |
|
|---|
| 113 | \section{Dining Philosophers}
|
|---|
| 114 |
|
|---|
| 115 | Dijkstra's well-known Dining Philosophers system can be encoded in
|
|---|
| 116 | CIVL-C as shown in Figure \ref{fig:dining}.
|
|---|
| 117 |
|
|---|
| 118 | \begin{figure}[t]
|
|---|
| 119 | \begin{small}
|
|---|
| 120 | \begin{verbatim}
|
|---|
| 121 | #include <civlc.h>
|
|---|
| 122 |
|
|---|
| 123 | $input int B; // upper bound on number of philosophers
|
|---|
| 124 | $input int n; // number of philosophers
|
|---|
| 125 | $assume 2<=n && n<=B;
|
|---|
| 126 | _Bool forks[n]; // Each fork will be on the table (0) or in a hand (1).
|
|---|
| 127 |
|
|---|
| 128 | void dine(int id) {
|
|---|
| 129 | int left = id;
|
|---|
| 130 | int right = (id + 1) % n;
|
|---|
| 131 |
|
|---|
| 132 | while (1) {
|
|---|
| 133 | $when (forks[left] == 0) forks[left] = 1;
|
|---|
| 134 | $when (forks[right] == 0) forks[right] = 1;
|
|---|
| 135 | forks[right] = 0;
|
|---|
| 136 | forks[left] = 0;
|
|---|
| 137 | }
|
|---|
| 138 | }
|
|---|
| 139 |
|
|---|
| 140 | void main() {
|
|---|
| 141 | for (int i = 0; i < n; i++) forks[i] = 0;
|
|---|
| 142 | for (int i = 0; i < n; i++) $spawn dine(i);
|
|---|
| 143 | }
|
|---|
| 144 | \end{verbatim}
|
|---|
| 145 | \end{small}
|
|---|
| 146 | \caption{CIVL-C encoding of Dijkstra's Dining Philosophers}
|
|---|
| 147 | \label{fig:dining}
|
|---|
| 148 | \end{figure}
|
|---|
| 149 |
|
|---|
| 150 | In this encoding, an upper bound \ct{B} is placed on the number of
|
|---|
| 151 | philosophers \ct{n}. When verifying this program, a concrete value
|
|---|
| 152 | will be specified for \ct{B}. Hence the result of verification will
|
|---|
| 153 | apply to all \ct{n} between $2$ and \ct{B}, inclusive.
|
|---|
| 154 |
|
|---|
| 155 | Both \ct{B} and \ct{n} are delcared as \emph{input} variables using
|
|---|
| 156 | the type qualifier \cinput. An input variable may be
|
|---|
| 157 | initialized with any valid value of its type. In contrast, non-input
|
|---|
| 158 | variables declared in file scope will be initialized with a
|
|---|
| 159 | special \emph{undefined} value; if such a variable is read before it
|
|---|
| 160 | is defined, an error will be reported. In addition, any input variable
|
|---|
| 161 | may have a concrete initial value specified on the command line. In
|
|---|
| 162 | this case, we will specify a concrete value for \ct{B} on the command
|
|---|
| 163 | line but leave \ct{n} unconstrained.
|
|---|
| 164 |
|
|---|
| 165 | An $\cassume$ statement restricts the set of executions of the program
|
|---|
| 166 | to include only those traces in which the assumptions hold. In
|
|---|
| 167 | contrast with an $\cassert$ statement, CIVL does not check that the
|
|---|
| 168 | assumed expression holds, and will not generate an error message if it
|
|---|
| 169 | fails to hold. Thus an $\cassume$ statement allows the programmer to
|
|---|
| 170 | say to CIVL ``assume that this is true,'' while an $\cassert$
|
|---|
| 171 | statement allows the programmer to say to CIVL ``check that this is
|
|---|
| 172 | true.''
|
|---|
| 173 |
|
|---|
| 174 | A $\cwhen$ statement encodes a \emph{guarded command}. The $\cwhen$
|
|---|
| 175 | statement includes a boolean expression called the \emph{guard} and a
|
|---|
| 176 | statement body. The $\cwhen$ statement is enabled if and only if the
|
|---|
| 177 | \emph{guard} evaluates to \emph{true}, in which case the body may be
|
|---|
| 178 | executed. The first atomic statement in the body executes atomically
|
|---|
| 179 | with the evaluation of the guard, so it is guaranteed that the guard
|
|---|
| 180 | will hold when this initial sub-statement executes. Since assignment
|
|---|
| 181 | statements are atomic in CIVL, in this example the bodiy of each
|
|---|
| 182 | $\cwhen$ statement executes atomically with the guard evaluation.
|
|---|
| 183 |
|
|---|
| 184 | The $\cspawn$ statement is very similar to a function call. The main
|
|---|
| 185 | difference is that the function called is invoked in a new process
|
|---|
| 186 | which runs concurrently with the existing processes. The $\cspawn$
|
|---|
| 187 | statement itself returns immediately.
|
|---|
| 188 |
|
|---|
| 189 | The program may be verified for an upper bound of $5$ by typing the
|
|---|
| 190 | following at the command line:
|
|---|
| 191 | \begin{verbatim}
|
|---|
| 192 | civl verify -inputB=5 diningBad.cvl
|
|---|
| 193 | \end{verbatim}
|
|---|
| 194 |
|
|---|
| 195 | The output indicates that a deadlock has been found and a
|
|---|
| 196 | counterexample has been produced and saved. We can examine the
|
|---|
| 197 | counterexample, but it is more helpful to work with a \emph{minimal}
|
|---|
| 198 | counterexample, i.e., a deadlocking trace of minimal length. To find a
|
|---|
| 199 | minimal counterexample, we issue the command
|
|---|
| 200 |
|
|---|
| 201 | \begin{verbatim}
|
|---|
| 202 | civl verify -inputB=5 -min diningBad.cvl
|
|---|
| 203 | \end{verbatim}
|
|---|
| 204 |
|
|---|
| 205 | \begin{figure}[t]
|
|---|
| 206 | \begin{small}
|
|---|
| 207 | \begin{verbatim}
|
|---|
| 208 | CIVL v0.8 of 2014-02-28 -- http://vsl.cis.udel.edu/civl
|
|---|
| 209 | Error 0 encountered at depth 129:
|
|---|
| 210 | ...
|
|---|
| 211 | Error 25 encountered at depth 16:
|
|---|
| 212 | CIVL execution error (kind: DEADLOCK, certainty: PROVEABLE)
|
|---|
| 213 | A deadlock is possible:
|
|---|
| 214 | Path condition: true
|
|---|
| 215 | Enabling predicate: false
|
|---|
| 216 | ProcessState 0: terminated
|
|---|
| 217 | ProcessState 1: at location 26, f0:21.30-42 "forks[right]"
|
|---|
| 218 | Enabling predicate: false
|
|---|
| 219 | ProcessState 2: at location 26, f0:21.30-42 "forks[right]"
|
|---|
| 220 | Enabling predicate: false
|
|---|
| 221 | at f0:21.30-42 "forks[right]".
|
|---|
| 222 | State 664
|
|---|
| 223 | | Path condition
|
|---|
| 224 | | | true
|
|---|
| 225 | | Dynamic scopes
|
|---|
| 226 | | | dyscope 0 (parent=-1, static=0)
|
|---|
| 227 | | | | reachers = {1,2}
|
|---|
| 228 | | | | variables
|
|---|
| 229 | | | | | __atomic_lock_var = process<-1>
|
|---|
| 230 | | | | | B = 5
|
|---|
| 231 | | | | | n = 2
|
|---|
| 232 | | | | | forks = X_s0v3[0:=1, 1:=1]
|
|---|
| 233 | ...
|
|---|
| 234 | | Process states
|
|---|
| 235 | ...
|
|---|
| 236 | | | process 2
|
|---|
| 237 | | | | atomicCount = 0
|
|---|
| 238 | | | | call stack
|
|---|
| 239 | | | | | Frame[function=dine, location=26, f0:21.30-42 "forks[right]", scope=3]
|
|---|
| 240 | ...
|
|---|
| 241 | =================== Stats ===================
|
|---|
| 242 | validCalls : 15328
|
|---|
| 243 | proverCalls : 17
|
|---|
| 244 | memory (bytes) : 26738688
|
|---|
| 245 | time (s) : 2.24
|
|---|
| 246 | maxProcs : 6
|
|---|
| 247 | statesInstantiated : 9267
|
|---|
| 248 | statesSaved : 665
|
|---|
| 249 | statesSeen : 1758
|
|---|
| 250 | statesMatched : 1177
|
|---|
| 251 | steps : 2994
|
|---|
| 252 | transitions : 2934
|
|---|
| 253 |
|
|---|
| 254 | The program MAY NOT be correct. See CIVLREP/diningBad_log.txt
|
|---|
| 255 | \end{verbatim}
|
|---|
| 256 | \end{small}
|
|---|
| 257 | \caption{Output from \texttt{civl verify -inputB=5 -min diningBad.cvl}}
|
|---|
| 258 | \label{fig:diningOut}
|
|---|
| 259 | \end{figure}
|
|---|
| 260 |
|
|---|
| 261 | The result of this command is shown in Figure \ref{fig:diningOut}. The
|
|---|
| 262 | output indicates that a minimal counterexample has length 19, i.e.,
|
|---|
| 263 | involves 20 states and 19 transitions (the depth of 20 is one more
|
|---|
| 264 | than 19). It was the 26th and shortest trace found. It was deemed
|
|---|
| 265 | equivalent to the earlier traces and hence the earlier ones were
|
|---|
| 266 | discarded and only this one saved. We can replay the trace with the command
|
|---|
| 267 | \begin{verbatim}
|
|---|
| 268 | civl replay diningBad.cvl
|
|---|
| 269 | \end{verbatim}
|
|---|
| 270 |
|
|---|
| 271 | \begin{figure}
|
|---|
| 272 | \begin{small}
|
|---|
| 273 | \begin{verbatim}
|
|---|
| 274 | ...
|
|---|
| 275 | Transition 1: State 0, proc 0:
|
|---|
| 276 | 0->1: B = 5 at f0:9.0-12 "$input int B";
|
|---|
| 277 | 1->2: n = InitialValue(n) at f0:10.0-12 "$input int n";
|
|---|
| 278 | 2->3: $assume ((2<=n)&&(n<=B)) at f0:11.0-20 "$assume 2<=n && n ... B";
|
|---|
| 279 | 3->4: forks = InitialValue(forks) at f0:13.0-12 "int forks[n]";
|
|---|
| 280 | 4->6: __h__ = InitialValue(__h__) at f0:27.12-13 "{";
|
|---|
| 281 | 6->7: i = 0 at f0:28.7-16 "int i = 0";
|
|---|
| 282 | --> State 1
|
|---|
| 283 |
|
|---|
| 284 | Transition 2: State 1, proc 0:
|
|---|
| 285 | 7->9: LOOP_TRUE_BRANCH at f0:28.18-23 "i < n";
|
|---|
| 286 | --> State 2
|
|---|
| 287 |
|
|---|
| 288 | ...
|
|---|
| 289 |
|
|---|
| 290 | Transition 12: State 12, proc 2:
|
|---|
| 291 | 19->20: left = id at f0:16.2-15 "int left = id";
|
|---|
| 292 | 20->21: right = ((id+1)%n) at f0:17.2-26 "int right = (id ... n";
|
|---|
| 293 | --> State 13
|
|---|
| 294 |
|
|---|
| 295 | Transition 13: State 13, proc 2:
|
|---|
| 296 | 21->24: LOOP_TRUE_BRANCH at f0:19.9-10 "1";
|
|---|
| 297 | --> State 14
|
|---|
| 298 |
|
|---|
| 299 | Transition 14: State 14, proc 1:
|
|---|
| 300 | 24->26: forks[left] = 1 at f0:20.29-44 "forks[left] = 1";
|
|---|
| 301 | --> State 15
|
|---|
| 302 |
|
|---|
| 303 | Transition 15: State 15, proc 2:
|
|---|
| 304 | 24->26: forks[left] = 1 at f0:20.29-44 "forks[left] = 1";
|
|---|
| 305 | --> State 16
|
|---|
| 306 |
|
|---|
| 307 | Violation of Deadlock found in State 16:
|
|---|
| 308 | A deadlock is possible:
|
|---|
| 309 | Path condition: true
|
|---|
| 310 | Enabling predicate: false
|
|---|
| 311 | ProcessState 0: terminated
|
|---|
| 312 | ProcessState 1: at location 26, f0:21.30-42 "forks[right]"
|
|---|
| 313 | Enabling predicate: false
|
|---|
| 314 | ProcessState 2: at location 26, f0:21.30-42 "forks[right]"
|
|---|
| 315 | Enabling predicate: false
|
|---|
| 316 |
|
|---|
| 317 | Trace ends after 15 transitions.
|
|---|
| 318 | Violation(s) found.
|
|---|
| 319 | ...
|
|---|
| 320 | \end{verbatim}
|
|---|
| 321 | \end{small}
|
|---|
| 322 | \caption{Output from \texttt{civl replay}}
|
|---|
| 323 | \label{fig:diningReplay}
|
|---|
| 324 | \end{figure}
|
|---|
| 325 |
|
|---|
| 326 | The result of this command is shown in Figure \ref{fig:diningReplay}.
|
|---|
| 327 | The output indicates that a deadlock has been found involving 2
|
|---|
| 328 | philosophers. The trace has 15 transitions; after the initialization
|
|---|
| 329 | sequence, each philosopher picks up her left fork.
|
|---|