source: CIVL/mods/dev.civl.com/doc/manual/part-introduction.tex@ 1aaefd4

main test-branch
Last change on this file since 1aaefd4 was aad342c, checked in by Stephen Siegel <siegel@…>, 3 years ago

Performing huge refactor to incorporate ABC, GMC, and SARL into CIVL repo and use Java modules.

git-svn-id: svn://vsl.cis.udel.edu/civl/trunk@5664 fb995dde-84ed-4084-dfe6-e5aef3e2452c

  • Property mode set to 100644
File size: 19.4 KB
Line 
1\part{Introduction}
2\label{part:intro}
3
4\chapter{Acknowledgement}
5
6The CIVL project is funded by the U.S.\ National Science Foundation
7under 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
24The CIVL-C language is primarily intended to be an intermediate
25representation for verification. A C program using
26MPI~\cite{mpi-forum:2012:mpi30}, CUDA~\cite{cuda-programming-guide},
27OpenMP~\cite{openmp-standard}, OpenCL~\cite{opencl-standard}, or
28another API (or even some combination of APIs), will be automatically
29translated into CIVL-C and then verified. The advantages of such a
30framework are clear: the developer of a new verification technique
31could implement it for CIVL-C and then immediately see its impact
32across a broad range of concurrent programs. Likewise, when a new
33concurrency API is introduced, one only needs to implement a
34translator from it to CIVL-C in order to reap the benefits of all the
35verification tools in the platform. Programmers would have a valuable
36verification and debugging tool, while API designers could use CIVL as
37a ``sandbox'' to investigate possible API modifications, additions,
38and interactions.
39
40This manual covers all aspects of the CIVL framework, and is organized in parts
41as 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
52This chapter gives instructions for downloading and installing CIVL,
53and running the verification tool on an example.
54
55\subsection*{Notes}
56
57\begin{itemize}
58\item The instructions say to install three theorem provers. In
59 reality, each of these is optional. CIVL will still work without
60 any theorem provers, but the results will not be very precise, i.e.,
61 it will produce a lot of false warnings. The more provers you
62 install, the more precise the analysis.
63\end{itemize}
64
65\subsection*{Instructions}
66
67\begin{enumerate}
68\item Install the automated theorem prover CVC3 (if you have not
69 already). The easiest way to do this is to visit
70 \url{http://www.cs.nyu.edu/acsys/cvc3/download.html} and download
71 the latest, optimized build with static library and executable for
72 your OS. Place the executable file \texttt{cvc3} somewhere in your
73 \texttt{PATH}. You can discard everything else. Alternatively, on
74 some linux systems, CVC3 can be installed using the package manager
75 via ``\texttt{sudo apt-get install cvc3}''. This will place
76 \texttt{cvc3} in \texttt{/usr/bin}.
77
78\item Install the automated theorem prover CVC4 (if you have not
79 already). The easiest way to do this is to visit
80 \url{http://cvc4.cs.nyu.edu/downloads/} and choose one of the
81 installation approaches. You only need the binary (\texttt{cvc4}),
82 and you must put it in your \texttt{PATH}. Alternatively, on OS X
83 you may install using MacPorts by ``\texttt{sudo port install
84 cvc4}''.
85
86\item Install the automated theorem prover Z3 (if you have not
87 already). Follow instructions at
88 \url{http://z3.codeplex.com/SourceControl/latest#README}. Make sure
89 the executable \texttt{z3} is in your path.
90
91\item Install a Java 7 SDK if you have not already. Go to
92 \url{http://www.oracle.com/technetwork/java/javase/downloads/} for
93 the latest from Oracle. On linux, you can instead use the package
94 manager: ``\texttt{sudo apt-get install openjdk-7-jdk}''.
95
96\item Download and unpack the latest stable release of CIVL from
97 \url{http://vsl.cis.udel.edu/civl}.
98
99\item The resulting directory should be named
100 \texttt{CIVL-\textit{tag}} for some string \textit{tag} which
101 identifies the version of CIVL you downloaded. Move this directory
102 wherever you like.
103
104\item The JAR file in the \texttt{lib} directory is all you need to
105 run CIVL. You may move this JAR file wherever you want. You run
106 CIVL by typing a command of the form ``\texttt{java -jar
107 /path/to/civl-TAG.jar ...}''. For convenience, you may instead
108 use the shell script \texttt{civl} included in the \texttt{bin}
109 directory. This allows you to replace ``\texttt{java -jar
110 /path/to/civl-TAG.jar}'' with just ``\texttt{civl}'' on the
111 command line. Simply edit the \texttt{civl} script to reflect the
112 path to the JAR file and place the script somewhere in your
113 \texttt{PATH}. Alternatively, you can define an alias in your
114 \texttt{.profile}, \verb!.bash_profile!, \texttt{.bashrc}, or
115 equivalent, such as
116\begin{verbatim}
117alias civl='java -jar /path/to/civl-TAG.jar'
118\end{verbatim}
119 In the following, we will assume that you have defined a command
120 \texttt{civl} in one of these ways.
121
122\item From the command line, type ``\texttt{civl help}''. You should see
123 a help message describing the command line syntax.
124
125\item From the command line, type ``\texttt{civl config}''. This should
126 report that \texttt{cvc3}, \texttt{cvc4}, and \texttt{z3} were
127 found, and it should create a file called \texttt{.sarl} in your
128 home directory.
129
130\end{enumerate}
131
132To test your installation, copy the file
133\texttt{examples/concurrency/locksBad.cvl} to your working directory.
134Look at the program: it is a simple 2-process program with two shared
135variables used as locks. The two processes try to obtain the locks in
136opposite order, which can lead to a deadlock if both processes obtain
137their first lock before either obtains the second. Type
138``\verb!civl verify locksBad.cvl!''. You should see some output
139culminating in a message
140\begin{verbatim}
141The program MAY NOT be correct. See CIVLREP/locksBad_log.txt
142\end{verbatim}
143
144Type ``\verb!civl replay locksBad.cvl!''. You should see a
145step-by-step account of how the program arrived at the deadlock.
146
147
148\chapter{Examples}
149
150In this section we show a few simple CIVL-C programs which illustrate
151some of the pertinent features of the language. We also show the results
152of running some of the tools on them.
153
154\section{Dining Philosophers}
155
156Dijkstra's well-known Dining Philosophers system can be encoded in
157CIVL-C as shown in Figure \ref{fig:dining}.
158
159\begin{figure}[t]
160 \begin{small}
161\begin{verbatim}
162#include <civlc.cvh>
163
164$input int B = 4; // upper bound on number of philosophers
165$input int n; // number of philosophers
166$assume(2<=n && n<=B);
167
168_Bool forks[n]; // Each fork will be on the table ($true) or in a hand ($false).
169
170void dine(int id) {
171 int left = id;
172 int right = (id + 1) % n;
173
174 while (1) {
175 $when (forks[left]) forks[left] = $false;
176 $when (forks[right]) forks[right] = $false;
177 forks[right] = $true;
178 forks[left] = $true;
179 }
180}
181
182void main() {
183 $for(int i: 0 .. n-1)
184 forks[i] = $true;
185 $parfor(int i: 0 .. n-1)
186 dine(i);
187}
188\end{verbatim}
189 \end{small}
190 \caption{\texttt{diningBad.cvl}: CIVL-C encoding of Dijkstra's Dining Philosophers}
191 \label{fig:dining}
192\end{figure}
193
194In this encoding, an upper bound \ct{B} is placed on the number of
195philosophers \ct{n}. When verifying this program, a concrete value
196will be specified for \ct{B}. Hence the result of verification will
197apply to all \ct{n} between $2$ and \ct{B}, inclusive.
198
199Both \ct{B} and \ct{n} are delcared as \emph{input} variables using
200the type qualifier \cinput. An input variable may be
201initialized with any valid value of its type. In contrast, non-input
202variables declared in file scope will be initialized with a
203special \emph{undefined} value; if such a variable is read before it
204is defined, an error will be reported. In addition, any input variable
205may have a concrete initial value specified on the command line. In
206this case, we will specify a concrete value for \ct{B} on the command
207line but leave \ct{n} unconstrained.
208
209An $\cassume$ statement restricts the set of executions of the program
210to include only those traces in which the assumptions hold. In
211contrast with an $\cassert$ statement, CIVL does not check that the
212assumed expression holds, and will not generate an error message if it
213fails to hold. Thus an $\cassume$ statement allows the programmer to
214say to CIVL ``assume that this is true,'' while an $\cassert$
215statement allows the programmer to say to CIVL ``check that this is
216true.''
217
218A $\cwhen$ statement encodes a \emph{guarded command}. The $\cwhen$
219statement includes a boolean expression called the \emph{guard} and a
220statement body. The $\cwhen$ statement is enabled if and only if the
221\emph{guard} evaluates to \emph{true}, in which case the body may be
222executed. The first atomic statement in the body executes atomically
223with the evaluation of the guard, so it is guaranteed that the guard
224will hold when this initial sub-statement executes. Since assignment
225statements are atomic in CIVL, in this example the bodiy of each
226$\cwhen$ statement executes atomically with the guard evaluation.
227
228The $\cfor$ statement is very similar to a for loop. The main
229difference is that it takes a domain and loops over it.
230
231The $\cparfor$ statement is a combination of $\cfor$ and $\cspawn$.
232The latter is very similar to a function call. The main
233difference is that the function called is invoked in a new process
234which runs concurrently with the existing processes.
235
236The program may be verified for an upper bound of $5$ by typing the
237following at the command line:
238\begin{verbatim}
239 civl verify -inputB=5 diningBad.cvl
240\end{verbatim}
241
242The output indicates that a deadlock has been found and a
243counterexample has been produced and saved. We can examine the
244counterexample, but it is more helpful to work with a \emph{minimal}
245counterexample, i.e., a deadlocking trace of minimal length. To find a
246minimal counterexample, we issue the command
247
248\begin{verbatim}
249 civl verify -inputB=5 -min diningBad.cvl
250\end{verbatim}
251
252\begin{figure}[t]
253 \begin{small}
254\begin{verbatim}
255CIVL v1.5 of 2015-10-31 -- http://vsl.cis.udel.edu/civl
256
257Violation 0 encountered at depth 19:
258CIVL execution violation (kind: DEADLOCK, certainty: PROVEABLE)
259at diningBad.cvl:31.11-12 ";":
260A deadlock is possible:
261...
262
263Logging new entry 0, writing trace to CIVLREP/diningBad_0.trace
264Restricting search depth to 18
265
266Violation 1 encountered at depth 14:
267CIVL execution violation (kind: DEADLOCK, certainty: PROVEABLE)
268at diningBad.cvl:31.11-12 ";":
269A deadlock is possible:
270 Path condition: true
271 Enabling predicate: false
272process p0 (id=0): false
273process p1 (id=1): false
274process p2 (id=2): false
275
276Context:
277true
278
279Call stacks:
280process p0 (id=0):
281 _CIVL_system at diningBad.cvl:31.11-12 ";"
282process p1 (id=1):
283 dine at diningBad.cvl:21.4-9 "$when"
284process p2 (id=2):
285 dine at diningBad.cvl:21.4-9 "$when"
286
287...
288
289=== Stats ===
290 time (s) : 0.95
291 memory (bytes) : 128974848
292 max process count : 5
293 states : 81
294 states saved : 53
295 state matches : 2
296 transitions : 77
297 trace steps : 56
298 valid calls : 510
299 provers : cvc4, z3, cvc3
300 prover calls : 6
301
302=== Result ===
303The program MAY NOT be correct. See CIVLREP/diningBad_log.txt
304\end{verbatim}
305 \end{small}
306 \caption{Output from \texttt{civl verify -inputB=5 diningBad.cvl}}
307 \label{fig:diningOut}
308\end{figure}
309
310The result of this command is shown in Figure \ref{fig:diningOut}. The
311output indicates that a minimal counterexample has length 14, i.e.,
312involves 15 states and 14 transitions (the depth of 19 is five more
313than 14). It was the 2nd and shortest trace found. It was deemed
314equivalent to the earlier traces and hence the earlier ones were
315discarded and only this one saved. We can replay the trace with the command
316\begin{verbatim}
317 civl replay -showTransitions diningBad.cvl
318\end{verbatim}
319
320\begin{figure}
321 \begin{small}
322\begin{verbatim}
323...
324Step 0: State 0, p0:
325 0->1: B=5 at diningBad.cvl:9.0-16 "$input int B = 4"
326 1->2: n=InitialValue(n) [n:=X0] at diningBad.cvl:10.0-12 "$input int n"
327 2->3: $assume((2<=X0)&&(X0<=5)) at diningBad.cvl:11.0-21 "$assume(2<=n && n ... )"
328 3->4: forks=InitialValue(forks) [forks:=(lambda i : int . false)] at diningBad.cvl:13.0-14 "_Bool forks[n]"
329--> State 1
330...
331Step 2: State 2, p0:
332 5->6: LOOP_BODY_ENTER(($domain(1)){(0..1#1)} has next for (NULL)) at diningBad.cvl:28.14-22 "0 .. n-1"
333 6->7: $for((NULL) has next in ($domain(1)){(0..1#1)} at diningBad.cvl:28.2-6 "$for"
334--> State 3
335...
336Step 6: State 6, p0:
337 ...
338 9->10: $parfor(i0: ($domain(1)){(0..1#1)}) $spawn dine(i0) at diningBad.cvl:30.2-9 "$parfor"
339--> State 7
340
341Step 7: State 7, p1:
342 12->13: left=0 at diningBad.cvl:16.2-15 "int left = id"
343 13->14: right=(0+1)%2 [right:=1] at diningBad.cvl:17.2-26 "int right = (id ... n"
344--> State 8
345...
346Step 11: State 11, p1:
347 15->16: forks[0]=false at diningBad.cvl:20.24-44 "forks[left] = $false"
348--> State 12
349
350Step 12: State 12, p2:
351 15->16: forks[1]=false at diningBad.cvl:20.24-44 "forks[left] = $false"
352--> State 13
353...
354Violation of Deadlock found in State 13:
355A deadlock is possible:
356 Path condition: true
357 Enabling predicate: false
358process p0 (id=0): false
359process p1 (id=1): false
360process p2 (id=2): false
361
362Trace ends after 13 trace steps.
363Violation(s) found.
364...
365\end{verbatim}
366 \end{small}
367 \caption{Output from \texttt{civl replay -showTransitions diningBad.cvl}}
368 \label{fig:diningReplay}
369\end{figure}
370
371The result of this command is shown in Figure \ref{fig:diningReplay}.
372The output indicates that a deadlock has been found involving 2
373philosophers. The trace has 15 transitions; after the initialization
374sequence, each philosopher picks up her left fork.
375
376\section{A Multithreaded MPI Example}
377
378\begin{figure}[t]
379 \begin{small}
380\begin{verbatim}
381#include<civlc.h>
382#define TAG 0
383#define NPROCS 2
384#define NTHREADS 2
385
386$gcomm gcomm = $gcomm_create($here, NPROCS);
387
388void MPI_Process (int rank) {
389 $comm comm = $comm_create($here, gcomm, rank);
390 $proc threads[NTHREADS];
391
392 void Thread(int tid) {
393 int x = rank;
394 $message in, out = $message_pack(rank, 1-rank, TAG, &x, sizeof(int));
395
396 for (int j=0; j<2; j++) {
397 if (rank == 1) {
398 for (int i=0; i<2; i++) $comm_enqueue(comm, out);
399 for (int i=0; i<2; i++) in = $comm_dequeue(comm, 1-rank, TAG);
400 } else {
401 for (int i=0; i<2; i++) in = $comm_dequeue(comm, 1-rank, TAG);
402 for (int i=0; i<2; i++) $comm_enqueue(comm, out);
403 }
404 }
405 }
406
407 for (int i=0; i<NTHREADS; i++) threads[i] = $spawn Thread(i);
408 for (int i=0; i<NTHREADS; i++) $wait(threads[i]);
409 $comm_destroy(comm);
410}
411
412void main() {
413 $proc procs[NPROCS];
414
415 for (int i=0; i<NPROCS; i++) procs[i] = $spawn MPI_Process(i);
416 for (int i=0; i<NPROCS; i++) $wait(procs[i]);
417 $gcomm_destroy(gcomm);
418}
419\end{verbatim}
420 \end{small}
421 \caption{\texttt{mpi-pthreads.cvl}: CIVL-C model of a (defective)
422 multithreaded MPI program.}
423 \label{fig:mpithreads}
424\end{figure}
425
426Figure \ref{fig:mpithreads} is an example of a CIVL-C model of
427multithreaded MPI program. The program consists of two processes,
428each of which spawns two threads. All four threads issue
429message-passing operations.
430
431This example illustrates some of the message-passing primitives
432provided in CIVL-C. A \emph{global communicator} object is allocated
433in the root scope. The constant $\chere$ has type $\cscope$ and
434refers to the scope in which the expression occurs; in this case it is
435the root (i.e., file) scope. This global communicator is declared to
436have \texttt{NPROCS} \emph{places}; these are points from which
437messages can be sent or received. The function \verb!MPI_Process! is
438used to model an MPI process. Each instance will create its own
439\emph{local communicator} object which specifies the global
440communicator and a place; this is the object that will be used to send
441or receive messages at that place.
442
443Each process spawns two instances of function \texttt{Thread}. Each
444thread creates a message object from a buffer, specifying the source
445and destination places, tag, pointer to the beginning of the buffer,
446and the size of the buffer. The message is \emph{enqueued} into the
447communication universe using the local communicator. Similarly,
448messages are dequeued by specifying the local communicator, source
449place, and tag.
450
451The program has a subtle defect, which only manifests on very specific
452interleavings of the threads. This defect can be found using
453\texttt{civl verify}.
454
455\section{Verifying C programs}
456CIVL can be used to verify C programs, with a number of transformers. One can also insert macros to C programs to tune it for verification, which, most of time, involves defining input variables. This is usually accomplished by the default macro \texttt{\_CIVL}.
457
458For example, Figure~\ref{fig:CIVLmacro} is a simple program that computes the sum of a number of positive numbers. The program can be compiled by any C compiler, as long as no \texttt{\_CIVL} macro is defined in the command for compiling. When CIVL runs this program, it will automatically have \texttt{\_CIVL} defined and thus \texttt{N} becomes an input variable and \texttt{sum} becomes an output variable and there is an assertion to check the correctness the sum computed by the program.
459
460If one wants to CIVL to treat a program as it is originally, then the command line option \texttt{-\_CIVL} can be set to false to disable the \texttt{\_CIVL} macro.
461
462\begin{figure}[h]
463\begin{small}
464\begin{verbatim}
465#ifdef _CIVL
466#include<civlc.cvh>
467#endif
468
469#ifdef _CIVL
470$input int N;
471$output int sum;
472#else
473#define N 100
474int sum;
475#endif
476
477void main() {
478 int localsum = 0;
479 for (int i = 1; i <= N; i++) {
480 localsum+=i;
481 }
482 sum = localsum;
483#ifdef _CIVL
484 $assert(sum == (N+1)*N/2);
485#endif
486}
487
488\end{verbatim}
489 \end{small}
490 \caption{\texttt{\_CIVL}: the default macro}
491 \label{fig:CIVLmacro}
492\end{figure}
493
494
495\subsection{Verifying MPI C programs}
496CIVL generates default input variables for verifying MPI programs:
497\begin{itemize}
498\item \texttt{\_mpi\_nprocs}: number of MPI processes to be created;
499\item \texttt{\_mpi\_nprocs\_lo}/\texttt{\_mpi\_nprocs\_hi}: lower/upper bound of the number of MPI processes to be created.
500\end{itemize}
501
502CIVL requires at least either \texttt{\_mpi\_nprocs} or \texttt{\_mpi\_nprocs\_hi} be specified in the command line in order to verify MPI programs (the default value of \texttt{\_mpi\_nprocs\_lo} is 1). For example, one can specify \texttt{civl verify -input\_mpi\_nprocs=5 ring.c}.
503
504\subsection{Verifying OpenMP C programs}
505CIVL introduces a default input variables \texttt{\_omp\_thread\_max} for OpenMP programs, and it needs to be specified in the command line. CIVL will create 1 to \texttt{\_omp\_thread\_max-1} threads for all OpenMP parallel region during the verification. If \texttt{\_omp\_thread\_max} is not specified, then somewhere in the OpenMP program must be specifying the number of threads explicitly. By default, CIVL applies simplification to OpenMP based on independent loop analysis, and optimally that might reduce the program to be purely sequential. The option \texttt{ompNoSimplify} can be set to false so as to skip such simplification. Another option, \texttt{ompLoopDecomp} can be used to specify the loop decomposition strategy, which can be \texttt{ALL}, \texttt{ROUND\_ROBIN} or \texttt{RANDOM}.
506
507\subsection{Verifying Pthreads C and CUDA C programs}
508There are no special option or default input variables for Pthreads or CUDA programs.
509
510
511
Note: See TracBrowser for help on using the repository browser.