source: CIVL/doc/manual/civl-manual.tex@ f9c2d43

1.23 2.0 acw/focus-triggers main test-branch
Last change on this file since f9c2d43 was 426ef0f, checked in by Stephen Siegel <siegel@…>, 13 years ago

Basic cleanup of manual.

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

  • Property mode set to 100644
File size: 66.7 KB
Line 
1% LaTeX source for CIVL Reference Manual.
2%
3\documentclass[11pt, oneside, letterpaper]{book}
4\usepackage[letterpaper,textheight=9in,left=1in,%
5 textwidth=6.5in,bottom=1in]{geometry}
6\usepackage{amsmath}
7\usepackage{amsthm}
8\usepackage{xcolor}
9\usepackage{bbold}
10\usepackage{url}
11\usepackage[lined,vlined,linesnumbered,noresetcount]{algorithm2e}
12
13\include{preambular}
14
15\title{{\huge\bf CIVL}\\\mbox{The Concurrency Intermediate Verification
16 Language}\\Reference Manual\\ v0.5}
17\author{%
18 Matthew B.\ Dwyer \and
19 Ganesh Gopalakrishnan \and
20 Zvonimir Rakamaric \and
21 Stephen F.\ Siegel \and
22 Manchun Zheng \and
23 Timothy K.\ Zirkel
24}
25
26\begin{document}
27\maketitle
28\tableofcontents
29
30\chapter{Quick Start}
31
32\begin{enumerate}
33\item Download and unpack the appropriate pre-compiled library of CIVL
34 dependencies from \url{http://vsl.cis.udel.edu/tools/vsl_depend/}.
35 There are versions for Darwin (OS X), 32-bit linux, and 64-bit
36 linux.
37\item Move the resulting directory \texttt{vsl} to \texttt{/opt/vsl}.
38\item Download and unpack the latest stable release of CIVL from
39 \url{http://vsl.cis.udel.edu/civl}. Again there are versions
40 for Darwin, 32-bit linux, and 64-bit linux.
41\item The resulting directory should be named
42 \texttt{CIVL-\textit{tag}} for some string \textit{tag} which
43 identifies the version of CIVL you downloaded. Move this directory
44 into \texttt{/opt}.
45\item You should now have an executable script
46 \texttt{/opt/CIVL-\textit{tag}/bin/civl}. Move this script into
47 your path, or create a symlink from somewhere in your path to it, or
48 add the directory \texttt{/opt/CIVL-\textit{tag}/bin} to your path.
49\end{enumerate}
50
51From the command line, you should now be able to type \texttt{civl
52 help} and see a help message describing the command line syntax.
53
54Copy the file
55\texttt{CIVL-\textit{tag}/examples/concurrency/locksBad.cvl} to your
56working directory. Look at the program: it is a simple 2-process
57program with two shared variables used as locks. The 2 processes try
58to obtain the locks in opposite order, leading to a deadlock.
59
60Type
61\begin{verbatim}
62civl verify locksBad.cvl
63\end{verbatim}
64You should see some output culminating in a message
65\begin{verbatim}
66The program MAY NOT be correct. See CIVLREP/locksBad_log.txt
67\end{verbatim}
68
69Type
70\begin{verbatim}
71civl replay locksBad.cvl
72\end{verbatim}
73You should see a step-by-step account of how the program arrived
74at the deadlock.
75
76\textbf{Note.} You can install \texttt{CIVL-\textit{tag}} and
77\texttt{vsl} in any directory you want, not just in \texttt{/opt}.
78You just need to edit the script file \texttt{civl} appropriately,
79replacing the default paths with the new paths.
80
81\part{Language}
82
83\chapter{Overview of CIVL-C}
84
85% write a grammar. Leave out type qualifiers, etc. Keep pointers.
86% Keep simple types? Why not keep all the standard types.
87% How about "symbolic types"? Make all the casts explicit.
88% Look at CIL?
89
90% Describe as subset of C, but leave out:... and add...
91
92% add Set<proc> and use it.
93
94\section{CIVL-C concepts and primitives}
95
96CIVL-C is a programming language. It is an extension of a subset of
97the C11 dialect of C. It does not include the standard C library.
98
99A CIVL-C program should begin with the line
100\begin{verbatim}
101#include <civlc.h>
102\end{verbatim}
103which includes the main CIVL-C header file, which declares all the
104types and other CIVL primitives. Almost all of the CIVL-C primitives
105which are not already in C begin with the symbol \texttt{\$} to easily
106distinguish them from any reserved work or identifier in a C program.
107
108A CIVL-C program encodes a CIVL model for a particular CIVL
109context. The types are essentially the C types with the additional
110process reference type (denoted \cproc). The expressions are C
111expressions with some additional expressions defined below.
112
113In CIVL-C, functions can be defined in any scope, not just in file
114scope. The lexical scope structure and placement of function
115definitions determine the static scope tree $\Sigma$ and the function
116prototype system. A function's defining scope is, as you would
117expect, the scope in which its definition occurs.
118
119The CIVL-C code will not have an explicit ``root'' procedure.
120Instead, a root procedure will be implicitly wrapped around the entire
121code. The global input variables will become the inputs to the root
122procedure. A ``\texttt{main}'' procedure must be delcared that takes
123no parameters but can have any return type. The body of \texttt{main}
124becomes the body of the root procedure. The return type of
125\texttt{main} becomes the return type of the root procedure. The
126\texttt{main} procedure itself disappears in translation.
127
128The reason for this protocol is that an arbitrary (sequential) C program
129is a legal (and reasonable) CIVL-C program. The global variables in the
130C program simply become variables declared in the root scope.
131
132The additional language elements are shown in Figure \ref{fig:cc}.
133
134\begin{figure}[t]
135 \begin{tabular}{ll}
136 \cproc & the process type \\
137 \cself & the evaluating process (constant of type \cproc) \\
138 \cinput & type qualifier declaring variable to be a program input \\
139 \coutput & type qualifier declaring variable to be a program output \\
140 \cspawn & create a new process running procedure \\
141 \cwait & wait for a process to terminate \\
142 \cassert & check something holds \\
143 \ctrue & boolean value true, used in assertions \\
144 \cfalse & boolean value false, used in assertions \\
145 \cassume & assume something holds \\
146 \catom & defines statements to be executed as one transition\\
147 \catomic & defines statements to be executed without interleaving other processes\\
148 \cwhen & guarded statement \\
149 \cchoose & nondeterministic choice statement \\
150 \cchooseint & nondeterministic choice of integer \\
151 \cinvariant & declare a loop invariant \\
152 \crequires & procedure precondition \\
153 \censures & procedure postcondition \\
154 \cresult & refers to result returned by procedure in contracts \\
155 \cat & refer to variable in other process, e.g., \texttt{p@x} \\
156 \ccollective & a collective expression\\
157 \cheap & the heap type \\
158 \cscope & the scope type, used to give a name to a scope \\
159 \cmalloc & malloc function with additional heap arguments \\
160 \texttt{*<...>} & scope-qualified pointer type
161 \end{tabular}
162 \caption{CIVL-C primitives. Some of these are part of the grammar of the language;
163 others are defined in the header file \texttt{civlc.h}.}
164 \label{fig:cc}
165\end{figure}
166
167
168
169\section{Detailed descriptions of primitives}
170
171\subsection{\cproc} This is a primitive object type and functions like
172any other primitive C type (e.g., \texttt{int}). An object of this
173type refers to a process. It can be thought of as a process ID, but
174it is not an integer and cannot be cast to one. Certain expressions
175take an argument of \cproc{} type and some return something of
176\cproc{} type.
177
178\subsection{\cself} This is a constant of type \cproc. It can be used
179wherever an argument of type \cproc{} is called for. It refers to the
180process that is evaluating the expression containing ``\cself''.
181
182\subsection{\cinput} A variable in the root scope only may be declared
183with this type modifier indicating it is an ``input'' variable, as in
184\begin{verbatim}
185 $input int n;
186\end{verbatim}
187As explained above, the variable becomes a parameter to the root
188procedure. This is used when comparing two programs for functional
189equivalence. The two programs are functionally equivalent if,
190whenever they are given the same inputs (i.e., corresponding \cinput{}
191variables are initialized with the same values) they will produce the
192same outputs (i.e., corresponding \coutput{} variables will end up
193with the same values at termination). Input variables can also be
194assigned a concrete value on the command line.
195
196\subsection{\coutput} A variable in the root scope may be declared
197with this type modifier to declare it to be an output variable.
198
199\subsection{\cspawn} This is an expression with side-effects. It
200spawns a new process and returns a reference to the new process, i.e.,
201an object of type \cproc. The syntax is the same as a procedure
202invocation with the keyword ``\cspawn'' inserted in front:
203\begin{verbatim}
204 $spawn f(expr1, ..., exprn)
205\end{verbatim}
206Typically the returned value is assigned to a variable, e.g.,
207\begin{verbatim}
208 $proc p = $spawn f(i);
209\end{verbatim}
210If the invoked function \texttt{f} returns a value, that value is
211simply ignored.
212
213\subsection{\cwait} This is a statement that takes an argument of type
214\cproc{} and blocks until the referenced process terminates:
215\begin{verbatim}
216 $wait expr;
217\end{verbatim}
218
219\subsection{\cassert} This is an assertion statement. It takes as its
220sole argument an expression of boolean type. The expressions have a
221richer syntax than C expressions. During verification, the assertion
222is checked. If it does not hold, a violation is reported.
223\begin{verbatim}
224 $assert expr;
225\end{verbatim}
226Boolean values \ctrue{} and \cfalse{} may be used in assertions
227and assumptions.
228
229\subsection{\cassume} This is an assume statement. Its syntax is the
230same as that of \cassert. During verification, the assumed expression
231is assumed to hold. If this leads to a contradiction on some
232execution, that execution is simply ignored. It never reports a
233violation, it only restricts the set of possible executions that will
234be explored by the verification algorithm.
235\begin{verbatim}
236 $assume expr;
237\end{verbatim}
238
239\subsection{\cwhen} This represents a guarded command:
240\begin{verbatim}
241 $when (expr) stmt;
242\end{verbatim}
243All statements have a guard, either implicit or explicit. For most
244statements, the guard is \ctrue. The \cwhen{} statement allows one to
245attach an explicit guard to a statement.
246
247When \texttt{expr} is \emph{true}, the statement is enabled, otherwise
248it is disabled. A disabled statement is \emph{blocked}---it will not
249be scheduled for execution. When it is enabled, it may execute by
250moving control to the \texttt{stmt} and executing the first atomic
251action in the \texttt{stmt}.
252
253If \texttt{stmt} itself has a non-trivial guard, the guard of the
254\cwhen{} statement is effectively the conjunction of the \texttt{expr}
255and the guard of \texttt{stmt}.
256
257The evaluation of \texttt{expr} and the first atomic action of
258\texttt{stmt} effectively occur as a single atomic action. There is
259no guarantee that execution of \texttt{stmt} will continue atomically
260if it contains more than one atomic action, i.e., other processes may
261be scheduled.
262
263Examples:
264\begin{verbatim}
265 $when (s>0) s--;
266\end{verbatim}
267This will block until \texttt{s} is positive and then decrement
268\texttt{s}. The execution of \texttt{s--} is guaranteed to take place
269in an environment in which \texttt{s} is positive.
270
271\begin{verbatim}
272 $when (s>0) {s--; t++}
273\end{verbatim}
274The execution of \texttt{s--} must happen when \texttt{s>0}, but
275between \texttt{s--} and \texttt{t++}, other processes may execute.
276
277\begin{verbatim}
278 $when (s>0) $when (t>0) x=y*t;
279\end{verbatim}
280This blocks until both \texttt{x} and \texttt{t} are positive then
281executes the assignment in that state. It is equivalent to
282\begin{verbatim}
283 $when (s>0 && t>0) x=y*t;
284\end{verbatim}
285
286\subsection{\cchoose} A \cchoose{} statement has the form
287\begin{verbatim}
288 $choose {
289 stmt1;
290 stmt2;
291 ...
292 default: stmt
293 }
294\end{verbatim}
295The \texttt{default} clause is optional.
296
297The guards of the statements are evaluated and among those that are
298\emph{true}, one is chosen nondeterministically and executed. If none
299are \emph{true} and the \texttt{default} clause is present, it is
300chosen. The \texttt{default} clause will only be selected if all
301guards are \emph{false}. If no \texttt{default} clause is present and
302all guards are \emph{false}, the statement blocks. Hence the implicit
303guard of the \cchoose{} statement without a \texttt{default} clause is
304the disjunction of the guards of its sub-statements. The implicit
305guard of the \cchoose{} statement with a default clause is
306\emph{true}.
307
308Example: this shows how to encode a ``low-level'' CIVL guarded
309transition system:
310
311\begin{verbatim}
312 l1: $choose {
313 $when (x>0) {x--; goto l2;}
314 $when (x==0) {y=1; goto l3;}
315 default: {z=1; goto l4;}
316 }
317 l2: $choose {
318 ...
319 }
320 l3: $choose {
321 ...
322 }
323\end{verbatim}
324
325\subsection{\cchooseint} This is a function with the following prototype:
326\begin{verbatim}
327 int $choose_int(int n);
328\end{verbatim}
329It takes as input a positive integer \texttt{n} and returns an integer
330in the range $[0,\texttt{n}-1]$.
331
332\subsection{\catom} This defines a number of statements to be executed as one transition. An \catom~block has the following form.
333\begin{verbatim}
334 $atom {
335 stmt1;
336 stmt2;
337 ...
338 }
339\end{verbatim}
340
341The statements inside an \catom~block are to be executed as one transition. It is required that the execution of the statements in an \catom~block is deterministic, non-blocking and finite. If one of the requirement is found to be violated, an error or a warning will be reported. For example, an error will be reported when executing the code below, because the \cwait~statement is blocked.
342
343\begin{verbatim}
344$atom{
345 for(int i = 0; i < 5; i++) p[i] = $spawn foo(i);
346 for(int i = 0; i < 5; i++) $wait p[i];
347}
348\end{verbatim}
349
350
351\subsection{\catomic} This defines a number of statements that will only allow the process to interleave with others when necessary. An \catomic~block has the following form.
352
353\begin{verbatim}
354 $atomic {
355 stmt1;
356 stmt2;
357 ...
358 }
359\end{verbatim}
360
361A process executing an \catomic~block will try to execute statements contained in the \catomic~block without interleaving with other processes, unless the process is blocked. For example, the following loop will be executed without interleaving with other processes.
362
363\begin{verbatim}
364$atomic{
365 for(int i = 0; i < 5; i++) p[i] = $spawn foo(i);
366}
367\end{verbatim}
368
369
370When no transition can be enabled, the execution of the \catomic~block will be interrupted. And other processes are allowed to execute, until the process gets enabled again to continue executing its \catomic~block. For example, in the following lines of code, after executing the first loop, the \catomic~block is blocked, because it has to wait for other processes' termination.
371
372\begin{verbatim}
373$atomic{
374 for(int i = 0; i < 5; i++) p[i] = $spawn foo(i);
375 for(int i = 0; i < 5; i++) $wait p[i];
376}
377\end{verbatim}
378
379%Ideally, there will be two states saved for [Example 2]. The first is the state after executing the first loop, and the second is after executing the second loop.
380%
381%One question here is, if processes p[0] to p[4] terminates in the order of 0-4, then the loop for(int i = 0; i < 5; i++) $wait p[i]; will have 5 saved states, the transitions of which are like ...p[0] terminates...wait p[0]... p[1] terminates... wait p[1]....
382%Maybe we need some special structure for $wait, like $wait {p[0], p[1], p[2], ...}? That is to wait for a set of processes at a time, instead of one process at a time. Or provide some expression to specify the termination of certain processes as a guard, something to return true if a given process terminates like $terminate(p[0])?
383%
384%Interleaving between processes are enabled when blocking happens, we need to think carefully. When there are more than one processes that have previously blocked atomic sections but gets enabled again at some state, that state is saved, and enabled transitions at that state are all enabled transitions from processes that are in some atomic sections (i.e. the atomic counter of the process is greater than 0). A statement to update the atomic lock variable is also integrated into the transitions from each process.
385%
386%[Example 3] gives an example for this situation. In [Example 3], p1 and p2 will both execute the first two statements (y = y + i; z++;) in its atomic block, and then they get blocked because x!=0. Then the main process gets to execute when(z==2) x = 0;, which enables both p1 and p2. Then p1 and p2 are non-deterministically chosen to complete its atomic block.
387%
388%If there is only one such process, then that process gets to execute as a normal atomic block, like [Example 2].
389%
390%[Example 3]
391%int x = 1;
392%int y = 0;
393%int z = 0;
394%int sum = 0;
395%void main(){
396% $proc p1 = $spawn foo(1);
397% $proc p2 = $spawn foo(2);
398% when (z==2) x = 0;
399%}
400%
401%void foo(i){
402% $atomic{
403% y = y + i;
404% z++;
405% when(x==0)
406% switch(y){
407% case 1: sum += 1*i; break;
408% case 2: sum += 2*i; break;
409% case 3: sum += 3*i; break;
410% }
411% }
412%}
413%
414%3. a loop in the state space is detected: this means that the atomic block is infinite, we shall throw an exception or report a warning for this.
415%
416%Here is how to detect the loop.
417%- if there is no non-determinism or blocking, then the loop can be detected by maintaining a stack of states at this level.
418%
419%- if there is non-determinism or blocking that separates the execution of atomic blocks into several parts, then the stack mentioned above can't identify loops for some case, like [Example 4]. Even in this case, DfsSearcher should be able to tell if a state has been encountered before, and I think we do not introduce bugs here if we don't purposely identify loops.
420%
421%We may maintain a counter to record the number of states that have been established in a process's atomic block and report warnings if the counter exceeds some upper bound.
422%
423%[Example 4]
424%int a = 0, b = 0;
425%
426%$atomic{
427% 1: for(int i = 0; i < 5; i--){
428% 2: a = 1;
429% 3: choose{
430% 4: when(2 > 1) b = 2;
431% 5: when(3 > 1) b = 3;
432% 6: }
433% 7: i++;
434% }
435%}
436%
437%In [Example 4], assume we have the following states during the execution, where s(x,y,z,L) means a state s with a = x, b=y, i=z and location being L.
438%
439%s1(1,0,0,L3) (after executing a=1)
440%s2(1,2,0,L3) (after executing when(2 > 1) b = 2; i++; i--; a=1)
441%s3(1,3,0,L3) (after executing when(3 > 1) b = 3; i++; i--; a=1)
442%s4(1,2,0,L3) (after executing when(2 > 1) b = 2; i++; i--; a=1)
443%s5(1,3,0,L3) (after executing when(3 > 1) b = 3; i++; i--; a=1)
444%
445%Here s2 and s4 are identical, s5 and s6 are identical. And DfsSearcher should be able to detect the loop because s1, s2, s3 are saved.
446
447
448
449\subsection{\cinvariant} This indicates a loop invariant. Each C loop
450construct has an optional invariant clause as follows:
451\begin{verbatim}
452 while (expr) $invariant (expr) stmt
453 for (e1; e2; e3) $invariant (expr) stmt
454 do stmt while (expr) $invariant (expr) ;
455\end{verbatim}
456The invariant encodes the claim that if \texttt{expr} holds upon
457entering the loop and the loop condition holds, then it will hold
458after completion of execution of the loop body. The invariant is used
459by certain verification techniques.
460
461\emph{Status:} parsed, but nothing is currently done with this
462information.
463
464\subsection{Procedure contracts}
465The \crequires{} and \censures{} primitives are used to encode
466procedure contracts. There are optional
467elements that may occur in a procedure declaration or definition,
468as follows. For a function prototype:
469\begin{verbatim}
470 T f(...)
471 $requires expr;
472 $ensures expr;
473 ;
474\end{verbatim}
475For a function definition:
476\begin{verbatim}
477 T f(...)
478 $requires expr;
479 $ensures expr;
480 {
481 ...
482 }
483\end{verbatim}
484The value \cresult{} may be used in post-conditions to refer
485to the result returned by a procedure.
486
487\emph{Status}: parsed, but nothing is currently done with this
488information.
489
490\subsection{Remote expressions}. These have the form \verb!expr@x!
491and refer to a variable in another process, e.g., \verb!procs[i]@x!.
492This special kind of expression is used in collective expressions,
493which are used to formulate collective assertions and invariants.
494
495The expression \verb!expr! must have \cproc{} type. The variable
496\texttt{x} must be a statically visible variable in the context in
497which it is occurs. When this expression is evaluated, the evaluation
498context will be shifted to the process referred to by \texttt{expr}.
499
500\emph{Status}: not implemented.
501
502\subsection{Collective expressions}. These have the form
503\begin{verbatim}
504 $collective(proc_expr, int_expr) expr
505\end{verbatim}
506This is a collective expression over a set of processes. The
507expression \texttt{proc{\U}expr} yields a pointer to the first element
508of an array of \cproc. The expression \texttt{int{\U}expr} gives the
509length of that array, i.e., the number of processes. Expression
510\texttt{expr} is a boolean-valued expression; it may use remote
511expressions to refer to variables in the processes specified in the
512array. Example:
513\begin{verbatim}
514 $proc procs[N];
515 ...
516 $assert $collective(procs, N) i==procs[(pid+1)%N]@i ;
517\end{verbatim}
518
519\emph{Status}: not implemented.
520
521\chapter{Pointers and heaps}
522
523CIVL-C supports pointers, using the same operators with the same
524meanings as C (\texttt{\&}, \texttt{*}, pointer arithmetic).
525As mentioned above, there is also a heap type \cheap{}, which can
526be used to declare multiple heaps in a CIVL-C program. The
527interaction between pointers, heaps, and scopes is an important
528aspect of CIVL-C.
529
530\section{Pointer types}
531
532Given any object type $T$ and a static scope $s$ in a CIVL-C program,
533there is a type \emph{pointer-to-$T$-in-$s$}. The type is used to
534represent a pointer to a memory location of type $T$ in scope $s$ or a
535descendant of $s$ (i.e., some scope contained in $s$).
536
537If scope $s_1$ is a descendant of $s_2$ (i.e., $s_1$ is lexically
538contained in $s_2$), the type \emph{pointer-to-$T$-in-$s_1$} is a
539subtype of \emph{pointer-to-$T$-in-$s_2$}. This means that any
540expression of the first type can be used wherever an object of the
541second type is expected. In particular, any expression $e$ of the
542subtype can be assigned to a left-hand-side expression of the
543supertype without explicit casts; also $e$ can be used as an argument
544to a function for which the corresponding parameter has the supertype.
545
546The syntax for denoting this type adheres to the usual C syntax for
547denoting the type \emph{pointer-to-$T$} with the addition of a scope
548parameter within angular brackets immediately following the \texttt{*}
549token. For example, to declare a variable \texttt{p} of type
550\emph{pointer-to-$T$-in-$s$}, one writes
551\begin{verbatim}
552 int *<s> p;
553\end{verbatim}
554If the scope modifier \texttt{<...>} is absent, the scope is taken to
555be the root scope $s_0$. The object has type
556\emph{pointer-to-$T$-in-$s_0$}, which is abreviated as
557\emph{pointer-to-$T$}. In this way, stanard C programs can be
558interpreted as CIVL-C programs.
559
560\section{Address-of operator}
561
562The address-of operator \texttt{\&} returns a pointer of the
563appropriate subtype using the innermost scope in which its left-hand-side
564argument is declared. For example
565
566\begin{verbatim}
567 {
568 $scope s1;
569 int x;
570 double a[N];
571 int *<s1> p = &x;
572 double *<s1> q = &a[2];
573 }
574\end{verbatim}
575is correct (in particular, it is type-correct) because \texttt{\&x}
576has type \emph{pointer-to-\texttt{int}-in-\texttt{s1}}, since
577\texttt{s1} is the scope in which \texttt{x} is declared.
578
579\section{Pointer addition and subtractions}
580
581If \texttt{e} is an expression of type \emph{pointer-to-$T$-in-$s$}
582and \texttt{i} is an expression of integer type then \texttt{e+i} also
583has type \emph{pointer-to-$T$-in-$s$}. In other words, pointer
584addition cannot leave the scope of the original pointer. This
585reflects the fact that every object is contained in one scope, and
586pointer addition cannot leave the object.
587
588
589Pointer subtraction is defined on two pointers of the same type, where
590``same'' includes the scope. That is checked statically. As in C, it
591is only defined if the two pointers point to the same object. In
592CIVL-C, a runtime error will be thrown if they do not point to the
593same object.
594
595\section{Semantics of scopes and pointer types}
596
597A variable of type \cscope{} is treated like any other variable.
598It becomes part of the state when the scope in which it is declared
599is instantiated to form a dynamic scope. The variable is
600initialized at that time and its value cannot change.
601
602Each time a dynamic scope is instantiated, it is assigned a unique ID
603number. The exactly value of the ID number is not relevant, it just
604has to be distince from any other scope ID number that currently
605exists in the state. This is the value that is assigned to the scope
606variable. Therefore, if a static scope contains a scope variable, and
607that scope is instantiated twice to form two distinct dynamic scopes,
608the values assigned to the two variables will be distinct.
609
610A pointer value is an ordered pair $\langle \delta,r \rangle$, where
611$\delta$ is a dynamic scope ID and $r$ is a reference to a memory
612location in the static scope associated to $\delta$. (We will define
613the exact form of a reference later.)
614
615When a dynamic scope is instantiated, each new variable created is
616assigned a \emph{dynamic type}. This is a refinement of the static
617type associated to the static variable. Every dynamic type
618is an instance of exactly one static type. The dynamic
619type of the newly instantiated variable is an instance of the
620static type of the static variable.
621
622The dynamic pointer types have the form
623\emph{pointer-to-$t$-in-$\delta$}, where $t$ is a dynamic type and
624$\delta$ is a dynamic scope ID. For a program to be dynamically type
625safe, such a variable should hold only values of the form $\langle
626\delta, r\rangle$. In particular, the variable should never be
627assigned a value where the dynamic scope component is a different
628instance of the static scope $s$ associated to $\delta$.
629
630\section{Pointer casts}
631
632If scope $s_1$ is contained in scope $s_2$, an expression of type
633\emph{pointer-to-$T$-in-$s_1$} can always be cast to
634\emph{pointer-to-$T$-in-$s_2$},
635 because the first is a subtype of the second. (As described above,
636the cast is unnecessary.)
637
638The cast in the other direction is also allowed, but the dynamic type
639safety of that cast will only be checked at runtime. In particular, a
640runtime error will result if the cast attempts to cast the pointer
641value to a dynamic scope which does not contain (is an ancestor of)
642the dynamic scope component of the pointer value.
643
644A type \emph{pointer-to-$T_1$-in-$s$} can be cast to a type
645\emph{pointer-to-$T_2$-in-$s$} according to the usual rules of C. In
646other words, usual casting rules apply as long as you don't change the
647scope.
648
649
650
651\section{Heaps}
652
653The standard CIVL-C library defines a type \cheap{} for explicit
654modeling of a heap. The default value of \cheap{} type is an empty
655heap, so you only need to declare a variable to have type \cheap{}
656in order to create a new heap:
657\begin{verbatim}
658 $heap h; /* a new empty heap */
659\end{verbatim}
660
661The following functions are also defined:
662\begin{verbatim}
663void* $malloc($heap *h, int size);
664void memcpy(void *p, void *q, size_t size);
665void free(void *p)
666\end{verbatim}
667The first function is like C's \texttt{malloc}, except that you
668specify the heap in which the allocation takes place by passing a
669pointer to the heap as the first argument. This modifies the
670specified heap and returns a pointer to the new object. The function
671can only occur in a context in which the type of the object is
672specified, as in:
673\begin{verbatim}
674 $heap h;
675 int n = 10;
676 double *p = (double*)$malloc(&h, n*sizeof(double));
677\end{verbatim}
678The second and third functions are exactly the same as in C. Note that
679\texttt{free} modifies the heap which was used to allocate \texttt{p}.
680
681Another pointer example:
682\begin{small}
683\begin{verbatim}
684{ $heap h;
685 { $scope s1;
686 double x;
687 { $scope s2;
688 double y;
689 double *<s1> p;
690 /* p can only point to something in s1 or descendant,
691 * for example, s2 */
692 p = &x; // fine
693 p = &y; // fine
694 p = (double*)$malloc(&h,10*sizeof(double)); // static type error
695 }
696 }
697}
698\end{verbatim}
699\end{small}
700
701\emph{Status}: Pointer type, \texttt{\&}, \texttt{*}, pointer addition
702all implemented. Type \cheap{}, \texttt{malloc}, \texttt{free}
703implemented. Scope-qualified pointers: parsed, type-checked, but
704information not currently used.
705
706\section{Scope-Parameterized Functions}
707
708Coming soon. (Parsed, type checked, not currently used otherwise.)
709
710\section{Scope-Parameterized Type Definitions}
711
712Coming soon. (Ditto.)
713
714% \chapter{Some Translation Examples}
715
716% \section{Structured parallelism}
717% Structured \verb!parbegin!/\verb!parend! statements look like this:
718% \begin{verbatim}
719% $parbegin
720% S1; S2; S2
721% $parend
722% \end{verbatim}
723% (See Dijkstra, Cooperating Sequential Processes.) The meaning is: run
724% the three statements in parallel, and block at the end until all have
725% completed.
726
727% This can be represented in CIVL-C as follows:
728
729% \begin{verbatim}
730% {
731% void f_1() {S1}
732% void f_2() {S2}
733% void f_3() {S3}
734% $proc tmp1 = $fork f_1(), tmp2=$fork f_2(), tmp3=$fork f_3();
735% $join(tmp1); $join(tmp2); $join(tmp3);
736% }
737% \end{verbatim}
738
739% \subsection{Parallel for loops}
740% The standard parallel ``for'' loop looks like
741% \begin{verbatim}
742% $parfor(T i = e; cond; inc) S
743% \end{verbatim}
744% It indicates each iteration should be run concurrently, blocking
745% at end until all complete. In CIVL-C:
746
747% \begin{verbatim}
748% {
749% void f(T i) {S}
750% T i = e;
751% int c = 0;
752% Vector<$proc> list;
753
754% while (cond) {
755% list.add($fork f());
756% c++;
757% inc;
758% }
759% for (int j=0; j<c; j++) $join(list.get(j));
760% }
761% \end{verbatim}
762
763% (This is assuming we have some sort of Vector datatype. Need to think
764% about that.)
765
766% \subsection{Message Passing}
767
768% There will be a bunch of standard libraries that can be included
769% into CIVL-C. One of these will be the message-passing library.
770% It will define a bunch of primitives that we will fill in shortly.
771% Among them will be basic send and receive functions.
772
773% The message-passing library can be defined entirely in CIVL-C.
774% (See Figure \ref{fig:mp1}.)
775
776% \begin{figure}
777% \begin{verbatim}
778% typedef struct _CIVL_Message {
779% struct _CIVL_Message *next; // next message in this queue
780% struct _CIVL_Message *prev; // previous message in this queue
781% int tag; // message tag
782% int size; // size of buffer
783% void *data; // pointer to first element
784% } *CIVL_Message;
785
786% typedef struct _CIVL_Comm {
787% $heap heap;
788% int numProcs; // number of procs in this communicator
789% $proc *procs; // array of length numProcs
790% CIVL_Message buf_front[][]; // oldest element of each queue
791% CIVL_Message buf_back[][]; // newest element of each queue
792% } *CIVL_Comm;
793% \end{verbatim}
794% \caption{CIVL Message Passing library: basic definitions}
795% \label{fig:mp1}
796% \end{figure}
797
798% Message passing functions may be defined with prototypes such as:
799% \begin{verbatim}
800% CIVL_Comm CIVL_Comm_create($proc procs[], int numProcs);
801% void CIVL_send(int src, void *buf, int size, int dest,
802% int tag, CIVL_Comm comm);
803% void CIVL_recv(int dest, void *buf, int size, int src,
804% int tag, CIVL_Comm comm);
805% \end{verbatim}
806
807% The arguments for \texttt{send} are:
808% \begin{enumerate}
809% \item rank of process issuing the send
810% \item address of buffer containing data to be sent
811% \item size of message
812% \item an integer tag
813% \item rank of destination process
814% \item communicator
815% \end{enumerate}
816
817% The arguments for \texttt{recv} are:
818% \begin{enumerate}
819% \item rank of process issuing the receive
820% \item address of receive buffer
821% \item size of receive buffer (must be large enough to hold any incoming message)
822% \item rank of source process or \code{CIVL{\U}ANY{\U}SOURCE}
823% \item tag or \code{CIVL{\U}ANY{\U}TAG}
824% \item communicator
825% \end{enumerate}
826
827% Notice one difference from MPI: we have to specify the process to
828% which the send or receive is associated in the first argument. This is
829% because we need to be more general than MPI. In MPI, that process is
830% always the MPI process invoking the send or receive. In CIVL, you
831% might want to have threads within processes (for example) and
832% associate the message to the MPI process, even though the thread is
833% actually invoking the send. Or you might want to associate it to
834% something else in some other language/library/API.
835
836% How they are implemented: \texttt{CIVL{\U}Comm{\U}create}
837% mallocs a new object of type \texttt{struct {\U}CIVL{\U}Comm} and returns
838% a pointer to it.
839
840
841\part{Semantics}
842
843\chapter{CIVL Model Syntax}
844
845\section{Notation and terminology}
846\label{sec:notation}
847
848Let $\B=\{\true,\false\}$ (the set of boolean values). Let
849$\N=\{0,1,2,\ldots\}$ (the set of natural numbers).
850
851Given a node $u$ in a tree, we let $\ancestors(u)$ denote the set of
852all ancestors of $u$, including $u$. We let $\descendants(u)$ denote
853the set of all descendants of $u$, including $u$.
854
855For any set $S$, let $S^*$ denote the set of all finite sequences of
856elements of $S$. The length of a sequence $\xi\in S^*$ is denoted
857$\len(\xi)$.
858
859% This is a lie:
860% The elements of the sequence are indexed from $0$ to
861% $\len(\xi)-1$.
862
863\section{Definition of Context}
864\label{sec:context}
865
866\begin{definition}
867 A \emph{CIVL type system} is a tuple comprising the following
868 components:
869 \begin{enumerate}
870 \item a set $\Type$ (the set of \emph{types}),
871 \item a type $\bool\in\Type$ (the \emph{boolean type}),
872 \item a type $\proc\in\Type$ (the \emph{process-reference type}),
873 \item a set $\Var$ (the set of all \emph{typed variables}),
874 \item a function $\vtype\colon \Var\ra\Type$ (which gives the
875 type of each variable),
876 \item a set $\Val$ (the set of all \emph{values}),
877 \item a function which assigns to each $t\in\Type$ a subset
878 $\Val_t\subseteq\Val$ (the set of values of type $t$)
879 and which satisfies $\Val_{\bool}=\B$ and $\Val_{\proc}=\N$,
880 \item a function which assigns to each $t\in\Type$ a value
881 $\default_t\in\Val_t$.
882 \end{enumerate}
883\end{definition}
884
885The default value will be used to give an initial value to any
886variable. It could represent something like ``an undefined value of
887type $t$'' or a reasonable initial value ($0$ for integers, etc.),
888depending on the language one is modeling.
889
890\begin{definition}
891 Given a CIVL type system, a \emph{valuation} in that system is a
892 function $\eta\colon\Var\ra\Val$ with the property that for any
893 $v\in\Var$, $\eta(v)\in\Val_{\vtype(v)}$.
894\end{definition}
895
896Given a CIVL type system, we let $\Eval$ denote the set of all
897valuations in that system.
898
899\begin{definition}
900 Given a CIVL type system, A \emph{CIVL expression system} for that
901 type system is a tuple comprising the following components:
902 \begin{enumerate}
903 \item a set $\Expr$ (the set of all \emph{typed expressions} over
904 $\Var$),
905 \item a function $\etype\colon\Expr\ra\Type$ (giving the type
906 of each expression),
907 \item a function
908 $\eval\colon\Expr\times\Eval\ra\Val$ (the \emph{evaluation
909 function}), satisyfing
910 \begin{itemize}
911 \item for any $e\in\Expr$ and $\eta\in\Eval$,
912 $\eval(e,\eta)\in\Val_{\etype(e)}$,
913 \end{itemize}
914 \item a function which associates to any $V\subseteq\Var$, a
915 subset $\Expr(V)\subseteq\Expr$ (the set of
916 \emph{expressions which involve only variables in $V$}) satisfying
917 the following:
918 \begin{itemize}
919 \item for any $V\subseteq\Var$ and $\eta,\eta'\in\Eval$, if
920 $\eta(v)=\eta'(v)$ for all $v\in V$, then for any $e\in\Expr(V)$,
921 $\eval(e,\eta)=\eval(e,\eta')$
922 \end{itemize}
923 \end{enumerate}
924\end{definition}
925
926\begin{definition}
927 A \emph{CIVL context} is a CIVL type system together with
928 a CIVL expression system for that type system.
929\end{definition}
930
931\begin{figure}
932 \notationtable
933 \caption{Table of Notation Used to Define CIVL Model Syntax}
934 \label{fig:notation}
935\end{figure}
936
937\section{Lexical scopes}
938\label{sec:scopes}
939
940\begin{definition}
941 Given a CIVL context $\mathcal{C}$, a \emph{lexical scope system}
942 over $\mathcal{C}$ is a tuple $(\Sigma,\rootscope,\sparent,\vars)$
943 consisting of
944 \begin{enumerate}
945 \item a set $\Sigma$ (the set of \emph{static scopes}),
946 \item a scope $\rootscope\in\Sigma$ (the \emph{root scope}),
947 \item a function
948 $\sparent\colon\Sigma\setminus\{\rootscope\}\rightarrow
949 \Sigma$ such that
950 \[\{(\sparent(\sigma),\sigma)\mid \sigma\in\Sigma\setminus\{\rootscope\}\}\]
951 gives $\Sigma$ the structure of a rooted tree with root $\rootscope$,
952 \item a function $\vars\colon\Sigma\rightarrow 2^{\Var}$
953 (specifying the variables \emph{declared} in each scope) satisfying
954 \begin{itemize}
955 \item $\sigma\neq\tau\implies \vars(\sigma)\cap \vars(\tau)=\emptyset$.
956 \end{itemize}
957 \end{enumerate}
958\end{definition}
959
960\begin{definition}
961 Given a CIVL context and scope $\sigma\in\Sigma$,
962 the set of \emph{visible variables} in $\sigma$
963 is $\bigcup_{\sigma'\in\ancestors(\sigma)}\vars(\sigma')$.
964\end{definition}
965
966One way this notion will be used: expressions used in a scope $\sigma$
967can only involve variables visible in $\sigma$.
968
969\section{Functions}
970\label{sec:functions}
971
972Fix a CIVL context $\mathcal{C}$ and lexical scope system
973\[\Lambda=(\Sigma,\rootscope,\sparent,\vars)\] over $\mathcal{C}$.
974
975We introduce a new type symbol $\void$, as in C, to use as the return
976type for a function that does not return a value. Let
977$\Type'=\Type\cup\{\void\}$.
978
979\begin{definition}
980 A \emph{function prototype} for $\Lambda$ is a tuple
981 $(\sigma, t, \xi)$ consisting of
982 \begin{enumerate}
983 \item a scope $\sigma\in\Sigma\setminus\{\rootscope\}$
984 (the \emph{function scope}),
985 \item a type $t\in\Type'$ (the \emph{return type}),
986 \item a finite sequence $\xi=v_1v_2\cdots v_n\in\vars(\sigma)^*$
987 consisting of variables declared in the function scope
988 (the \emph{formal parameters}).
989 \end{enumerate}
990\end{definition}
991
992\begin{definition}
993 A \emph{CIVL function prototype system} consists of
994 \begin{enumerate}
995 \item a set $\Func$ (the \emph{function symbols}),
996 \item a function which assigns to each $f\in\Func$ a
997 function prototype, denoted
998 \[
999 (\fscope(f), \returntype(f), \params(f)),
1000 \]
1001 and satisfying
1002 \begin{itemize}
1003 \item for any $\sigma\in\Sigma$, there is at most
1004 one $f\in\Func$ such that $\sigma=\fscope(f)$, and
1005 \end{itemize}
1006 \item a \emph{root function} $f_0$ with $\fscope(f_0)=\rootscope$
1007 and which is the only function with root scope.
1008 \end{enumerate}
1009\end{definition}
1010
1011
1012\begin{definition}
1013 Given a CIVL function prototype system, and function symbol
1014 $f\in\Func\setminus\{f_0\}$, the \emph{declaration scope} of $f$ is
1015 the scope $\sigma=\sparent(\fscope(f))$. We also write \emph{$f$ is
1016 declared in $\sigma$.}
1017\end{definition}
1018
1019Note the root function $f_0$ has no declaration scope.
1020
1021Just as every scope has a set of visible variables, there is also
1022a set of visible functions:
1023\begin{definition}
1024 The functions \emph{visible at scope $\sigma$} are
1025 those declared in $\sigma$ or an ancestor of $\sigma$.
1026\end{definition}
1027We will see that the variables and functions visible at $\sigma$ are
1028the only variables and functions that can be referred to by statements
1029and expressions used within $\sigma$.
1030
1031Note that only certain scopes are function scopes. There can be
1032additional scopes (intuitively corresponding to block scopes in a
1033source program). Every scope, however, must ``belong to'' exactly one
1034function. The precise definition is as follows:
1035\begin{definition}
1036 \label{def:func}
1037 Given a CIVL function prototype system, define
1038 \[
1039 \func \colon \Sigma \ra \Func
1040 \]
1041 by
1042 \[
1043 \func(\sigma)=
1044 \begin{cases}
1045 f & \text{if $\sigma=\fscope(f)$ for some $f\in\Func$}\\
1046 \func(\sparent(\sigma)) & \text{otherwise.}
1047 \end{cases}
1048 \]
1049 We say \emph{$\sigma$ belongs to $f$} when $\func(\sigma)=f$.
1050\end{definition}
1051Note that the recursion in Definition \ref{def:func} must stop as the
1052root scope belongs to the root function and the scopes form a tree.
1053
1054
1055\section{Statements}
1056
1057Fix a CIVL function prototype system. A \emph{CIVL statement} is
1058defined to be a tuple of one of the forms described below.
1059In each case, we give any restritions on the components of the tuple
1060and a brief intuition on the statement's semantics. The precise
1061semantics will be described in \S\ref{sec:semantics}.
1062
1063\begin{enumerate}
1064\item $\langle\code{parassign},V_1,V_2,\psi\rangle$
1065 \begin{itemize}
1066 \item $V_1,V_2\subseteq\Var$
1067 \item $\psi\colon V_2\ra\Expr(V_1)$ satisfying
1068 $\etype(\psi(v))=\vtype(v)$ for all $v\in V_2$
1069 \item \emph{meaning}: parallel assignment, i.e., the assignment of new
1070 values to any or all of the variables in $V_2$. For each variable
1071 in $V_2$ an expression is given which will be evaluated in the old
1072 state to compute the new value for that variable. $V_1$ contains
1073 all the variables that may be used in those expressions. Hence
1074 $V_1$ is the ``read set'' and $V_2$ is the ``write set'' for the
1075 parallel assignment.
1076 \end{itemize}
1077\item $\langle\code{assign},v,e\rangle$
1078 \begin{itemize}
1079 \item $v\in\Var$, $e\in\Expr$, $\etype(e)=\vtype(v)$
1080 \item \emph{meaning}: simple assignment: evaluate an expression $e$ and
1081 assign result to variable $v$. It is a special case of
1082 \code{parassign} but is provided for convenience.
1083 \end{itemize}
1084\item $\langle\code{call},y,f,e_1,\ldots,e_n\rangle$
1085 \begin{itemize}
1086 \item $y\in\Var$, $f\in\Func$, $e_1,\ldots,e_n\in\Expr$
1087 \item $n=\numparams(f)$
1088 \item $\etype(e_i)=\vtype(v_i)$, where $\params(f)=v_1\cdots v_n$
1089 \item $\returntype(f)=\vtype(y)$
1090 \item \emph{meaning}: evaluate expressions $e_1,\ldots,e_n$; push
1091 frame on call stack and move control to guarded transition system
1092 (see \S\ref{sec:gts}) for function $f$; when $f$ returns, pop
1093 stack and store returned result in $y$
1094 \end{itemize}
1095\item $\langle\code{call},f,e_1,\ldots,e_n\rangle$
1096 \begin{itemize}
1097 \item $f\in\Func$, $e_1,\ldots,e_n\in\Expr$
1098 \item $n=\numparams(f)$
1099 \item $\etype(e_i)=\vtype(v_i)$, where $\params(f)=v_1\cdots v_n$
1100 \item \emph{meaning}: like above, but return type may be \code{void}
1101 or returned value could just be ignored
1102 \end{itemize}
1103\item $\langle\code{fork},p,f,e_1,\ldots,e_n\rangle$
1104 \begin{itemize}
1105 \item $p\in\Var$, $f\in\Func$, $e_1,\ldots,e_n\in\Expr$
1106 \item $n=\numparams(f)$
1107 \item $\etype(e_i)=\vtype(v_i)$, where $\params(f)=v_1\cdots v_n$
1108 \item $\returntype(f)=\void$
1109 \item $\vtype(p)=\proc$
1110 \item \emph{meaning}: evaluate expressions $e_1,\ldots,e_n$;
1111 create new process and invoke function $f$ in it;
1112 return, immediately, a reference to the new process and store
1113 that reference in $p$
1114 \end{itemize}
1115\item $\langle\code{join},e\rangle$
1116 \begin{itemize}
1117 \item $e\in\Expr$
1118 \item $\etype(e)=\proc$
1119 \item \emph{meaning}: evaluate $e$ and wait for the referenced process to terminate
1120 \end{itemize}
1121\item $\langle\code{return},e\rangle$
1122 \begin{itemize}
1123 \item $e\in\Expr$
1124 \item \emph{meaning}: evaluate $e$, pop the call stack and return
1125 control, along with the value, to caller
1126 \end{itemize}
1127\item $\langle\code{return}\rangle$
1128 \begin{itemize}
1129 \item \emph{meaning}: pop the call stack and return control to caller;
1130 only to be used in functions returning \code{void}
1131 \end{itemize}
1132\item $\langle\code{write},e\rangle$
1133 \begin{itemize}
1134 \item $e\in\Expr$
1135 \item \emph{meaning}: evaluate $e$ and send result to output
1136 \end{itemize}
1137\item $\langle\code{noop}\rangle$
1138 \begin{itemize}
1139 \item \emph{meaning}: does nothing
1140 \end{itemize}
1141\item $\langle\code{assert}, e\rangle$
1142 \begin{itemize}
1143 \item $e\in\Expr$, $\vtype(e)=\bool$
1144 \item \emph{meaning}: evaluate $e$; if result is false, stop
1145 execution and report error
1146 \end{itemize}
1147\item $\langle\code{assume}, e\rangle$
1148 \begin{itemize}
1149 \item $e\in\Expr$, $\vtype(e)=\bool$
1150 \item \emph{meaning}: assume $e$ holds (i.e., if $e$ does not hold,
1151 the execution sequence is not a real execution)
1152 \end{itemize}
1153\end{enumerate}
1154
1155\section{Remarks}
1156
1157The system described is sufficiently general to model pointers. There
1158can be (one or more) pointer types and corresponding values. The
1159parallel assignment statement can be used to model statements like
1160C's \texttt{*p=e;}. In the worst case (if no information is known
1161about where \texttt{p} could point), one can let $V_2=\Var$.
1162Similarly, expressions that involve \texttt{*p} as a right-hand
1163side subexpression can always take $V_1=\Var$.
1164
1165Heaps can also be modeled. A heap type may be defined and a variable
1166of that type declared. Expressions to modify and read from the heap
1167can be defined, as can pointers into the heap.
1168
1169
1170\section{Transition system representation of functions}
1171\label{sec:gts}
1172
1173\begin{definition}
1174 Given a CIVL function prototype system and $f\in\Func$,
1175 a \emph{guarded transition system} for $f$
1176 is a tuple $(\Loc,\lscope,\start, T)$, where
1177 \begin{itemize}
1178 \item $\Loc$ is a set (the set of \emph{locations}),
1179 \item $\lscope\colon\Loc\ra\Sigma$ is a function which associates
1180 to each $l\in\Loc$ a scope $\lscope(l)\in\Sigma$ belonging to $f$,
1181 \item $\start\in\Loc$ (the \emph{start location}),
1182 \item $T$ is a set of \emph{guarded transitions}, each of which has
1183 the form $\langle l,g,s,l'\rangle$, where
1184 \begin{itemize}
1185 \item $l,l'\in\Loc$ (the \emph{source} and \emph{target}
1186 locations)
1187 \item $g\in\Expr(V)$, where $V$ is the set of variables visible at
1188 $\lscope(l)$, and $\etype(g)=\bool$ ($g$ is called the
1189 \emph{guard}),
1190 \item $s$ is a statment all of whose constituent variables,
1191 expressions, and function symbols are visible at $\lscope(l)$.
1192 \end{itemize}
1193 \end{itemize}
1194 Furthermore, if the guarded transition system contains a statement
1195 of the form $\langle\code{return}\rangle$ then
1196 $\returntype(f)=\void$. If it contains a statement of the form
1197 $\langle\code{return},e\rangle$ then $\etype(e)=\returntype(f)$.
1198\end{definition}
1199
1200\begin{definition}
1201 Given a CIVL prototype system, a \emph{CIVL model} $M$ for that
1202 system assigns, to each $f\in\Func$, a guarded transition system
1203 \[(\Loc_f,\lscope_f, \start_f,T_f)\] for $f$. Moreover, if $f\neq f'$
1204 then
1205 $\Loc_f\cap\Loc_{f'}=\emptyset$.
1206\end{definition}
1207
1208\begin{definition}
1209 Given a CIVL model $M$, let $\Loc=\bigcup_{f\in\Func}\Loc_f$.
1210\end{definition}
1211
1212\chapter{CIVL Model Semantics}
1213\label{sec:semantics}
1214
1215\section{State}
1216\label{sec:state}
1217
1218Fix a CIVL model $M$. Recall that a valuation is a type-respecting
1219function from $\Var$ to $\Val$. Given a subset $V\subseteq\Var$ of
1220variables, we define a \emph{valuation on $V$} to be a type-respecting
1221function from $V$ to $\Val$. Let $\Eval(V)$ denote the set of all
1222valuations on $V$. Note that $\Eval(\Var)=\Eval$.
1223
1224\begin{definition}
1225 \label{def:state}
1226 A \emph{state} of a CIVL model $M$ is a tuple
1227 \[
1228 s=(\Delta, \droot, \dparent, \static, \deval, P, \stack),
1229 \]
1230 where
1231 \begin{enumerate}
1232 \item $\Delta$ is a finite set (the set of \emph{dynamic scopes} in
1233 $s$),
1234 \item $\droot\in\Delta$ (the \emph{root dynamic scope}),
1235 \item $\dparent\colon \Delta\setminus\{\droot\}\ra\Delta$
1236 is a function such that the set
1237 \[
1238 \{(\dparent(\delta),\delta)\mid \delta\in
1239 \Delta\setminus\{\droot\}\}
1240 \]
1241 gives $\Delta$ the structure of a rooted tree with root $\droot$,
1242 \item $\static\colon\Delta\ra\Sigma$,
1243 \item $\static(\droot)=\rootscope$ and $\droot$ is the only
1244 $\delta\in\Delta$ satisfying $\static(\delta)=\rootscope$,
1245 \item $\static(\dparent(\delta))=\sparent(\static(\delta))$ for any
1246 $\delta\in\Delta$,
1247 \item $\deval$ is a function that assigns to each $\delta\in\Delta$
1248 a valuation $\deval(\delta)\in\Eval(\vars(\static(\delta)))$,
1249 \item $P$ (the set of \emph{process IDs} in $s$)
1250 is a finite subset of $\Val_{\proc}$, and
1251 \item $\stack\colon P\ra \Frame^*$, where
1252 \[
1253 \Frame=\{(\delta,l)\in\Delta\times\Loc\mid\lscope(l)=\static(\delta)\}.
1254 \]
1255 \end{enumerate}
1256 Let $\State$ denote the set of all states of $M$.
1257\end{definition}
1258
1259% say entrance and exit from scopes does not have to be "structured".
1260
1261Remarks:
1262\begin{enumerate}
1263\item We will also refer to dynamic scopes as \emph{dyscopes}.
1264\item The elements of $\Delta$ contain no intrinsic information.
1265 Instead, all of the information concerning dyscopes is encoded
1266 in the functions that take elements of $\Delta$ as arguments. Hence
1267 we might just as well call the elements of $\Delta$ ``dynamic scope
1268 IDs'' (just as we call the elements of $P$ ``process IDs''). One
1269 could use natural numbers for the dyscopes, just as one does
1270 for processes.
1271\item The reason for using some form of ID for dyscopes and
1272 processes, rather than just incorporating the data in the
1273 appropriate part of the state, is that both kinds of objects may be
1274 shared. There can be several components of the state that refer to
1275 the same dyscope $d$: e.g., $d$ could have several children,
1276 each of which has a parent reference to $d$, as well as a reference
1277 from a frame. A process can be referred to by any number of
1278 variables of type $\proc$.
1279\item If $\sigma=\static(\delta)$, we say that \emph{$\delta$ is an
1280 instance of $\sigma$} or \emph{$\sigma$ is the static scope
1281 associated to $\delta$}. In general, a static scope can have any
1282 number (including 0) of dynamic instances. The exception is the root
1283 scope $\rootscope$, which must have exactly one instance ($\droot$).
1284\item A valuation $\deval(\delta)$ assigns a value to each variable in
1285 the static scope associated to $\delta$. The function $\deval$
1286 thereby encodes the value of all variables ``in scope'' in state
1287 $s$.
1288\item The sequence $\stack(p)$ encodes the state of the call stack of
1289 process $p$. The elements of the sequence are called
1290 \emph{activation frames}. The first frame in the sequence, i.e.,
1291 the frame in position $0$, is the bottom of the stack; the last
1292 frame is the top of the stack.
1293\item Each frame refers to a dyscope $\delta$ and a
1294 location in the static scope associated to $\delta$.
1295\end{enumerate}
1296
1297
1298\begin{definition}
1299 A dyscope $\delta\in\Delta$ is a \emph{function node}
1300 if $\static(\delta)$ is the function scope of some function.
1301\end{definition}
1302
1303\begin{definition}
1304 Given any $\delta\in\Delta$, $\fnode(\delta)\in\Delta$ is defined as
1305 follows: if $\delta$ is a function node, then
1306 $\fnode(\delta)=\delta$, else
1307 $\fnode(\delta)=\fnode(\dparent(\delta))$. We call $\fnode(\delta)$
1308 the \emph{function node associated to $\delta$}.
1309\end{definition}
1310
1311The relation $\{(\delta,\delta')\mid \fnode(\delta)=\fnode(\delta')\}$
1312is an equivalence relation $\sim$ on $\Delta$. Let
1313$\bar{\Delta}=\Delta/\sim$ and write $[\delta]$ for the equivalence
1314class containing $\delta$.
1315
1316The set of activation frames in a state $s$ may be identified with the
1317set
1318\[
1319AF(s)=\bigcup_{p\in P}\{p\}\times\{0,\ldots,\len(\stack(p))-1\}
1320\]
1321Namely, $(p,i)$ corresponds to the $i^{\text{th}}$ entry in the call
1322stack $\stack(p)$ (where the elements of the stacks are indexed from
1323$0$).
1324
1325Define $\Psi\colon AF(s)\ra \bar{\Delta}$ as follows: given $(p,i)$,
1326let $(\delta,l)$ be the corresponding frame; set $\Psi(p,i)=[\delta]$.
1327
1328% \begin{definition}
1329% A state $s$ is \emph{well-formed} if all of the following hold:
1330% \begin{enumerate}
1331% \item for any $\delta\in\Delta$, at most one child of $\delta$ is not
1332% a function node,
1333% \item the function $\Psi$ is a one-to-one correspondence,
1334% \item any $\delta$ occurring in the top frame of a call stack
1335% is a leaf node.
1336% \end{enumerate}
1337% \end{definition}
1338
1339
1340\section{Jump protocol}
1341\label{sec:jump}
1342
1343% can only jump if \delta is a leaf node.
1344% also no other frame can point to a dyscope between \delta
1345% and the dyscope corresponding to the function scope
1346
1347% in any state, a "region" of the dyscope tree can have at
1348% most one (exactly one?) stack frame pointing into it.
1349
1350% a region in a chain of nodes starting from a dyanmic scope corresonding
1351% to a function scopes and leading down until you reach another
1352% function scope.
1353
1354% whenever you have more than one child in the dynamic tree, all but
1355% 0 or 1 children must be a function scope
1356
1357% every dyscope is owned by at most one frame
1358
1359% can a frame point only to a leaf node? No, but all of its children
1360% must be function nodes
1361
1362% to find out which frame owns which dyscopes:
1363
1364% approach 1: start from a frame. frame owns the node it points to.
1365% move up parents until you hit a function scope and stop.
1366% that is that frame's region. No other frame can point into its
1367% region. Proof: true in initial state, invariant under
1368% call and fork.
1369
1370% invariant: every leaf node in the dyscope tree is pointed
1371% to by the top frame of the call stack of some process
1372
1373% Define a \emph{well-formed state}:
1374
1375% every dyscope node has at most one child which is not a function node
1376
1377% 1-1 correspondence between leaf nodes and top frames of stacks.
1378
1379% Define regions in the dyscope tree. (each region contains one
1380% function node)
1381
1382\newcommand{\lub}{\sigma_{\textsf{lub}}}
1383
1384\begin{figure}[t]
1385 \begin{algorithm}[H]
1386 \Procedure{$\textsf{\textup{jump}}(s\colon\State, p\colon\Val_{\proc},
1387 l'\colon\Loc)\colon\State$}{%
1388 let $(\Delta, \droot, \dparent, \static, \deval, P, \stack)=s$\;
1389 let $\delta$ be the dyscope of the last frame on $\stack(p)$\;
1390 let $\sigma=\static(\delta)$\;
1391 let $\sigma'=\lscope(l')$\;
1392 let $\lub$ be the least upper bound of $\sigma$ and
1393 $\sigma'$ in the tree $\Sigma$\;
1394 let $m$ be the minimum integer such that
1395 $\sparent^m(\sigma)=\lub$\;
1396 let $\delta_{\textsf{lub}}=\dparent^m(\delta)$\;
1397 let $n$ be the minimum integer such that
1398 $\sparent^{n}(\sigma')=\lub$\;
1399 let $\delta_0,\ldots,\delta_{n-1}$ be $n$ distinct objects not in $\Delta$\;
1400 let
1401 \( \displaystyle
1402 \Delta'=\Delta
1403 \cup \{ \delta_0,\ldots,\delta_{n-1} \}
1404 %\setminus \{ \dparent^j(\delta)\mid 0\leq j<m\}
1405 \)\;
1406 define $\dparent'\colon\Delta'\setminus\{\droot\}\ra\Delta'$ by
1407 \(
1408 \dparent'(\delta')=
1409 \begin{cases}
1410 \dparent(\delta') & \text{if $\delta'\in\Delta$}\\
1411 \delta_{i+1} & \text{if $\delta'=\delta_{i}$ for some $0\leq i<n-1$}\\
1412 \delta_{\textsf{lub}} & \text{if $n\geq 1$ and $\delta'=\delta_{n-1}$}
1413 \end{cases}
1414 \)\;
1415 define $\static'\colon\Delta'\ra\Sigma$ by
1416 \(
1417 \static'(\delta')=
1418 \begin{cases}
1419 \static(\delta') & \text{if $\delta'\in\Delta$}\\
1420 \sparent^i(\sigma') & \text{if $\delta'=\delta_i$ for some $0\leq i<n$}
1421 \end{cases}
1422 \)\;
1423 for $\delta'\in\Delta'$ and $v\in\vars(\static(\delta'))$,
1424 let
1425 \(
1426 \deval'(\delta')(v) =
1427 \begin{cases}
1428 \deval(\delta')(v) & \text{if $\delta'\in\Delta$}\\
1429 \default_t & \text{otherwise}
1430 \end{cases}
1431 \)\;
1432 define $\stack'$ to be the same as $\stack$ except that
1433 the last frame on $\stack'(p)$ is replaced with
1434 $(\delta_0,l')$ if $n\geq 1$, or with $(\delta_{\textsf{lub}},l')$
1435 if $n=0$\;
1436 let $s'(\Delta',\droot,\dparent',\static',\deval',P,\stack')$\;
1437 return the result of removing all unreachable dyscopes from $s'$\;
1438 }
1439 \end{algorithm}
1440 \caption{Jump protocol: how the state changes when control moves
1441 to a new location within a function. The procedure may only
1442 be called if $\func(\sigma)=\func(\sigma')$, i.e., the jump
1443 is contained within one function.}
1444 \label{fig:jump}
1445\end{figure}
1446
1447When control moves from one location to another within a function's
1448transition system, dyscopes may be added, because you can jump out of
1449scope nests and into new scope nests. The motivating idea is that you
1450have to move up the dyscope tree every time you move past a right
1451curly brace (i.e., leave a scope) and then push on a new scope for
1452each left curly brace you move past. So there is a sequence of upward
1453moves followed by a sequence of pushes to get to the new
1454location. (And either or both sequences could be empty.) At the end,
1455if any dyscopes become unreachable, they are removed from the state.
1456
1457Note however, that we do not assume that scopes are associated to
1458locations in a nice lexical pattern (or any pattern at all). The
1459protocol described here works for any arbitrary assignment of scopes
1460to locations.
1461
1462The precise protocol is described in Figure \ref{fig:jump}. The
1463algorithm shown there takes as input a well-formed state, a process
1464ID, and a location $l'$ for the function that $p$ is currently in.
1465Say the current dyscope for $p$ is $\delta$, and $l'$ is in
1466static scope $\sigma'$. Let $\sigma=\static(\delta)$. Hence the
1467current static scope is $\sigma$ and the new static scope will be $\sigma'$.
1468
1469First, you have to find the \emph{least upper bound} $\lub$ of
1470$\sigma$ and $\sigma'$ in the static scope tree. (Hence $\lub$ is a
1471common anecestor of $\sigma$ and $\sigma'$, and if $\sigma''$ is any
1472common ancestor of $\sigma$ and $\sigma'$ then $\sigma''$ is an
1473ancestor or equal to $\lub$.) Note that the least upper bound must
1474exist since the function scope is a common ancestor of $\sigma$ and
1475$\sigma'$. There is a chain of static scopes from $\sigma$ up to
1476$\lub$ and a corresponding chain
1477$\delta,\dparent(\delta),\ldots,\dparent^m(\delta)$ in the dynamic
1478scope tree. Let $\delta_{\textsf{lub}}=\dparent^m(\delta)$. This
1479will become the least upper bound of $\delta$ and the new dynamic
1480scope corresponding to $\sigma'$ that will be added to the state.
1481
1482Next you add new dyscopes corresponding to the chain of static
1483scopes leading from $\lub$ down to $\sigma'$. The variables in the
1484new scopes are assigned the default values for their respective types.
1485The $\dparent$, $\static$, and $\deval$ maps are adjusted
1486accordingly. Finally, the stack is modified by replacing the last
1487activation frame with a frame referring to the (possibly) new dynamic
1488scope and new location $l'$.
1489
1490This protocol is executed every time control moves from one location
1491to another.
1492
1493Note that in CIVL all jumps stay within a function. There is no
1494way to jump from one function to another (without returning).
1495
1496A small variation is the protocol for moving to the start location of
1497a function when the function is first pushed on the stack. Since the
1498start location is not necessarily in the function scope (it may be a
1499proper descendant of that scope), you have to execute the second half
1500of the protocol to push a sequence of scopes from the function scope
1501to the scope of the start location.
1502
1503\section{Initial State}
1504
1505The \emph{initial state} for $M$ is obtained by creating one process
1506(let $P=\{0\}$) and having it call the root function $f_0$.
1507Hence start with the state $s$ in which $P=\{0\}$, $\ldots$.
1508The initial state is $\textsf{jump}(s,0,\start_{f_0})$.
1509
1510\section{Transitions}
1511
1512The transitions follow the usual ``interleaving'' semantics. Given a
1513state $\sigma$, one defines the set of enabled transitions in $\sigma$
1514as follows. Let $p\in P$. Look at the last frame $(d,l)$ of
1515$\stack(p)$ (i.e., the top of the call stack), assuming the stack is
1516nonempty. Look at all guarded transitions emanating from $l$. For each
1517such transition, evaluate the guard using the valuation formed by
1518taking the union of the valuations of all ancestors of $d$ (including
1519$d$). In other words, follow the standard ``lexical scoping'' protocol
1520to determine the value of any variable that could occur at this point.
1521Those transitions whose guard evaluates to $\emph{true}$ are enabled.
1522
1523For each enabled transition, a new state is generated by executing
1524the transition's statement. For the most part, the semantics are obvious,
1525but there are a few details that are a bit subtle.
1526
1527\section{Calls and Spawns}
1528
1529Both calls and forks of a function $f$ entail the creation of a new
1530frame. First, a new dyscope $d$ corresponding to $\fscope(f)$ is
1531created. To find out where to stick that new scope in the dynamic
1532scope tree, proceed as follows: begin in the dyscope for the
1533process invoking the fork or call and start moving up its parent
1534sequence until you reach the first dyscope $d'$ whose associated
1535static scope is the defining scope of $f$. (You must reach such a
1536scope, or else $f$ would not be visible, and the model would have a
1537syntax error!) Insert $d$ right under $d'$, i.e.,
1538$\dparent(d)=d'$. This preserves the required correspondence between
1539static scopes and dyscopes. Now you move to the start location,
1540using the jump protocol, which may involve the creation of additional
1541dyscopes under $d$. The new frame references the last dynamic
1542scope you created, and the location is the start location of $f$.
1543Variables are given their initial values in all the newly created
1544dyscopes (however that is done).
1545
1546All of that is the same whether the statement is a fork or call. The
1547only difference is what happens next: for a call, the new frame is
1548pushed onto the calling process' call stack. For a fork, a new process
1549is ``created'', i.e., you pick a natural number not in $P$ and
1550add it to $P$, and push the frame onto the new stack. To be totally
1551deterministic, you could pick the least natural number not in $P$.
1552
1553\section{Garbage collection}
1554
1555In a state $s$, a dyscope is unreachable if there is no path
1556from a frame in a call stack to that dyscope (following the
1557$\dparent$ edges). You can remove all unreachable dyscopes.
1558
1559If a process has terminated (has empty stack) and \emph{there are no
1560references to that process} in the state, you can just remove the process
1561from the state.
1562
1563In any state, you can renumber the processes (and update the
1564references accordingly) however you want, to get rid of gaps, put them
1565in a canonic order, etc.
1566
1567
1568\part{Tools}
1569
1570\chapter{Overiew of CIVL Tools}
1571
1572Current tools allow one to \emph{run} a CIVL program using random
1573choice to resolve nondeterministic choices; \emph{verify} a program
1574using model checking to explore all states of the program;
1575\emph{replay} a trace if an error is found.
1576
1577The properties checked are assertion violations, division by zero,
1578illegal pointer accesses, etc.
1579
1580The available tools and options are summarized by the \texttt{civl
1581 help} command:
1582
1583\begin{verbatim}
1584Usage: civl <command> <options> filename ...
1585Commands:
1586 verify : verify program filename
1587 run : run program filename
1588 help : print this message
1589 replay : replay trace for program filename
1590 parse : show result of preprocessing and parsing filename
1591 preprocess : show result of preprocessing filename
1592Options:
1593 -debug or -debug=BOOLEAN (default: false)
1594 debug mode: print very detailed information
1595 -echo or -echo=BOOLEAN (default: false)
1596 print the command line
1597 -errorBound=INTEGER (default: 1)
1598 stop after finding this many errors
1599 -guided or -guided=BOOLEAN
1600 user guided simulation; applies only to run, ignored
1601 for all other commands
1602 -id=INTEGER (default: 0)
1603 ID number of trace to replay
1604 -inputKEY=VALUE
1605 initialize input variable KEY to VALUE
1606 -maxdepth=INTEGER (default: 2147483647)
1607 bound on search depth
1608 -min or -min=BOOLEAN (default: false)
1609 search for minimal counterexample
1610 -por=STRING (default: std)
1611 partial order reduction (por) choices:
1612 std (standard por) or scp (scoped por)
1613 -random or -random=BOOLEAN
1614 select enabled transitions randomly; default for run,
1615 ignored for all other commands
1616 -saveStates or -saveStates=BOOLEAN (default: true)
1617 save states during depth-first search
1618 -seed=STRING
1619 set the random seed; applies only to run
1620 -showModel or -showModel=BOOLEAN (default: false)
1621 print the model
1622 -showProverQueries or -showProverQueries=BOOLEAN (default: false)
1623 print theorem prover queries only
1624 -showQueries or -showQueries=BOOLEAN (default: false)
1625 print all queries
1626 -showSavedStates or -showSavedStates=BOOLEAN (default: false)
1627 print saved states only
1628 -showStates or -showStates=BOOLEAN (default: false)
1629 print all states
1630 -showTransitions or -showTransitions=BOOLEAN (default: false)
1631 print transitions
1632 -simplify or -simplify=BOOLEAN (default: true)
1633 simplify states?
1634 -solve or -solve=BOOLEAN (default: false)
1635 try to solve for concrete counterexample
1636 -states=STRING (default: immutable)
1637 state implementation: immutable, transient, persistent
1638 -sysIncludePath=STRING
1639 set the system include path
1640 -trace=STRING
1641 filename of trace to replay
1642 -userIncludePath=STRING
1643 set the user include path
1644 -verbose or -verbose=BOOLEAN (default: false)
1645 verbose mode
1646\end{verbatim}
1647
1648
1649\chapter{Transitions}
1650In CIVL, a transition stands for the execution of a number of statements of a certain process from one state, and the execution of each statement is considered as one step. A transition has the following form in the output, where sid and sid' are the identifiers for the source and the target states, pid is the identifier of the process that this transition belongs to, and step 0,1 ... are the steps contained in the transitions.
1651
1652\begin{verbatim}
1653State sid, proc pid:
1654 step 0;
1655 step 1;
1656 ...
1657--> State sid'
1658\end{verbatim}
1659
1660A step of a transition has the following form in the CIVL output, where src and dst is the source and destination location of the statement executed in the step, file is the file that contains the source code of the statement, location and text are the location and summary of text of the statement in the source file.
1661
1662\begin{verbatim}
1663 src->dst: statement at file:location "text";
1664\end{verbatim}
1665
1666For example, the following is a transition from state 0 to state 1, containing 6 steps. File names are renamed with short names and the mapping of short names and the original files is presented in output as well.
1667
1668\begin{verbatim}
1669File name list:
1670f0 : atomicBlockedResume.cvl
1671
1672State 0, proc 0:
1673 0->1: x = 1 at f0:3.0-9 "int x = 1";
1674 1->2: y = 0 at f0:4.0-9 "int y = 0";
1675 2->3: z = 0 at f0:5.0-9 "int z = 0";
1676 3->6: sum = 0 at f0:6.0-11 "int sum = 0";
1677 6->8: $spawn foo(1) at f0:22.4-17 "$spawn foo(1)";
1678 8->10: $spawn foo(2) at f0:23.4-17 "$spawn foo(2)";
1679--> State 1
1680\end{verbatim}
1681
1682To make use of this feature, one needs to specify the option ``-showTransitions'' when running CIVL.
1683
1684
1685
1686% \subsection{Example 1}
1687
1688% Here is a simple example based on a tricky MPI+Pthreads example given
1689% to us once by Rajeev Thakur at Argonne. It has nondeterministic
1690% behavior which can lead to a deadlock for certain interleavings, even
1691% though it does not use wildcards (\code{ANY{\U}SOURCE}). Very subtle
1692% bug. I can show you MPI-Spin finding the bug if you are interested. I
1693% don't actually have the original code, but could probably dig it up.
1694
1695% \begin{verbatim}
1696% #include <mp.civl> /* includes basic message-passing library */
1697
1698% void System() {
1699% proc procs[2];
1700
1701% void MPI_Process(int pid) {
1702% proc threads[2];
1703
1704% void Thread(int tid) {
1705% int x=0, y=0;
1706
1707% for (int j=0; j<2; j++) {
1708% if (pid == 1) {
1709% for (int i=0; i<3; i++) send(procs[pid], &x, 1, procs[1-pid], 0);
1710% for (int i=0; i<3; i++) recv(procs[pid], &y, 1, procs[1-pid], 0);
1711% } else { /* pid==0 */
1712% for (int i=0; i<3; i++) recv(procs[pid], &y, 1, procs[1-pid], 0);
1713% for (int i=0; i<3; i++) send(procs[pid], &x, 1, procs[1-pid], 0);
1714% }
1715% }
1716% }
1717
1718% for (int i=0; i<2; i++) threads[i] = fork Thread(i);
1719% for (int i=0; i<2; i++) join threads[i];
1720% }
1721
1722% for (int i=0; i<2; i++) procs[i] = fork MPI_Process(i);
1723% for (int i=0; i<2; i++) join procs[i];
1724% }
1725% \end{verbatim}
1726
1727\appendix
1728
1729
1730\end{document}
1731
1732
1733OpenMP loop?
1734\begin{verbatim}
1735T1 x1; ... // private
1736U1 y1; ... // shared
1737#pragma omp parallel private(x1,...)
1738 S(x1,...,y1,...);
1739
1740=>
1741
1742T1 x1; ...
1743U1 y1; ...
1744{
1745 void _tmp(int _tid) {
1746 T1 _x1; ...
1747 S(_x1,...,y1,...);
1748 }
1749 int numThreads = $choose_int(THREAD_MAX);
1750 $proc _threads[numThreads];
1751 int i;
1752
1753 for (i=0; i<numThreads; i++)
1754 _threads[i] = $spawn _tmp(i);
1755 for (i=0; i<numThreads; i++)
1756 $wait _threads[i];
1757}
1758
1759--
1760
1761#pragma parallel
1762{ ...
1763 int i; ...
1764 #pragma for
1765 for (i=...) S(i)
1766}
1767
1768=>
1769
1770{
1771 void _tmp1(int _tid) {
1772 int i; ...
1773 {
1774 void _tmp2(int _i) { S(_i) }
1775 int j;
1776 for (j=...) {
1777 int w = $choose_int(numThreads);
1778 }
1779 }
1780 }
1781
1782
1783\end{verbatim}
Note: See TracBrowser for help on using the repository browser.