| 1 | \part{Language}
|
|---|
| 2 | \label{part:lang}
|
|---|
| 3 |
|
|---|
| 4 | \chapter{Overview of CIVL-C}
|
|---|
| 5 |
|
|---|
| 6 | CIVL-C is a programming language. It is an extension of a subset of
|
|---|
| 7 | the C11 dialect of C. It does not include the standard C library.
|
|---|
| 8 |
|
|---|
| 9 | A CIVL-C program should begin with the line
|
|---|
| 10 | \begin{verbatim}
|
|---|
| 11 | #include <civlc.h>
|
|---|
| 12 | \end{verbatim}
|
|---|
| 13 | which includes the main CIVL-C header file, which declares all the
|
|---|
| 14 | types and other CIVL primitives. Almost all of the CIVL-C primitives
|
|---|
| 15 | which are not already in C begin with the symbol \texttt{\$} to easily
|
|---|
| 16 | distinguish them from any reserved work or identifier in a C program.
|
|---|
| 17 |
|
|---|
| 18 | Key concepts: static scope tree, nested functions, dynamic scope tree,
|
|---|
| 19 | nested functions, processes, spawning, waiting, types, ...
|
|---|
| 20 |
|
|---|
| 21 |
|
|---|
| 22 | \chapter{Structure of a CIVL-C program}
|
|---|
| 23 |
|
|---|
| 24 | CIVL-C program may use preprocessor directives as specified in the C
|
|---|
| 25 | Standard. A source program is preprocessed, then parsed, resulting
|
|---|
| 26 | in a translation unit.
|
|---|
| 27 |
|
|---|
| 28 | A translation unit consists of a sequence of variable declarations,
|
|---|
| 29 | function prototypes, function definitions, and \emph{assume}
|
|---|
| 30 | statements.
|
|---|
| 31 |
|
|---|
| 32 | lexical scopes and the lexical scope tree
|
|---|
| 33 |
|
|---|
| 34 | naming scopes (\$scope)
|
|---|
| 35 |
|
|---|
| 36 | translation of source to model
|
|---|
| 37 |
|
|---|
| 38 | root function, root scope and the main function
|
|---|
| 39 |
|
|---|
| 40 | formal parameters to main, return value
|
|---|
| 41 |
|
|---|
| 42 |
|
|---|
| 43 | % write a grammar. Leave out type qualifiers, etc. Keep pointers.
|
|---|
| 44 | % Keep simple types? Why not keep all the standard types.
|
|---|
| 45 | % How about "symbolic types"? Make all the casts explicit.
|
|---|
| 46 | % Look at CIL?
|
|---|
| 47 |
|
|---|
| 48 | % Describe as subset of C, but leave out:... and add...
|
|---|
| 49 |
|
|---|
| 50 | % add Set<proc> and use it.
|
|---|
| 51 |
|
|---|
| 52 | \chapter{Sequential Elements}
|
|---|
| 53 |
|
|---|
| 54 | In this chapter we describe the main sequential elements of the
|
|---|
| 55 | language. For the most part these are the same as in C.
|
|---|
| 56 |
|
|---|
| 57 | \section{Types}
|
|---|
| 58 |
|
|---|
| 59 | The boolean type is denoted \verb!_Bool!, as in C. Its values are $0$
|
|---|
| 60 | and $1$, which are also denoted by $\ctrue$ and $\cfalse$,
|
|---|
| 61 | respectively.
|
|---|
| 62 |
|
|---|
| 63 | There is one integer type, corresponding to the mathematical integers.
|
|---|
| 64 | Currently, all of the C integer types \texttt{int}, \texttt{long},
|
|---|
| 65 | \texttt{unsigned\ int}, \texttt{short}, etc., are mapped to the CIVL
|
|---|
| 66 | integer type.
|
|---|
| 67 |
|
|---|
| 68 | There is one real type, corresponding to the mathematical real
|
|---|
| 69 | numbers. Currently, all of the C real types \texttt{double},
|
|---|
| 70 | \texttt{float}, etc., are mapped to the CIVL real type.
|
|---|
| 71 |
|
|---|
| 72 | Array types, \texttt{struct} and \texttt{union} types, \texttt{char},
|
|---|
| 73 | and pointer types are all exactly as in C.
|
|---|
| 74 |
|
|---|
| 75 |
|
|---|
| 76 | \section{Expressions}
|
|---|
| 77 |
|
|---|
| 78 | The following C operators are included in CIVL:
|
|---|
| 79 | \begin{itemize}
|
|---|
| 80 | \item numerical addition (\verb!+}), subtraction (\verb!-!), multiplication
|
|---|
| 81 | (\verb!*!), division (\verb!/!), unary minus (\verb!-!),
|
|---|
| 82 | integer division (\verb!/!) and modulus (\verb!%!), all with
|
|---|
| 83 | their ideal mathematical interpretations;
|
|---|
| 84 | \item address-of (\verb!&!), pointer dereference(\verb!*!),
|
|---|
| 85 | pointer addition (\verb!+!) and subtraction (\verb!-!)
|
|---|
| 86 | \item numerical comparators \verb!==!, \verb!>=!, \verb!<=!, \verb!<!, \verb!>!,
|
|---|
| 87 | with exact real semantics
|
|---|
| 88 | \item boolean operators \verb~!~, \verb!&&!, \verb!||!
|
|---|
| 89 | \item \verb!sizeof!
|
|---|
| 90 | \item assignments (\verb!=!)
|
|---|
| 91 | \item function calls: \verb!f(e1,...,en)!
|
|---|
| 92 | \item conditional: \verb!b ? e : f!
|
|---|
| 93 | \end{itemize}
|
|---|
| 94 |
|
|---|
| 95 | Bit-wise operations are not yet supported.
|
|---|
| 96 |
|
|---|
| 97 | \section{Statements}
|
|---|
| 98 |
|
|---|
| 99 | Usual C statements are supported:
|
|---|
| 100 | \begin{itemize}
|
|---|
| 101 | \item expression statements
|
|---|
| 102 | \item labeled statements
|
|---|
| 103 | \item \texttt{for}, \texttt{while} loops
|
|---|
| 104 | \item compound statement: \lb \ldots \rb
|
|---|
| 105 | \item \texttt{if} and \verb!if! \ldots \verb!else!
|
|---|
| 106 | \item \verb!goto!
|
|---|
| 107 | \item \verb!switch!
|
|---|
| 108 | \item \verb!break!
|
|---|
| 109 | \item \verb!continue!
|
|---|
| 110 | \end{itemize}
|
|---|
| 111 |
|
|---|
| 112 | \section{Nondeterminism}
|
|---|
| 113 |
|
|---|
| 114 | \cchoose
|
|---|
| 115 |
|
|---|
| 116 |
|
|---|
| 117 |
|
|---|
| 118 | \chapter{Concurrency}
|
|---|
| 119 |
|
|---|
| 120 | \section{Process creation and management}
|
|---|
| 121 |
|
|---|
| 122 | \section{Dynamic scopes, revisited}
|
|---|
| 123 |
|
|---|
| 124 | \section{Atomicity}
|
|---|
| 125 |
|
|---|
| 126 | \section{Message Passing}
|
|---|
| 127 |
|
|---|
| 128 | \chapter{Specification}
|
|---|
| 129 |
|
|---|
| 130 | \section{Overview}
|
|---|
| 131 |
|
|---|
| 132 | \section{Input-output signature}
|
|---|
| 133 |
|
|---|
| 134 | \section{Assertions and assumptions}
|
|---|
| 135 |
|
|---|
| 136 | \section{Formulas}
|
|---|
| 137 |
|
|---|
| 138 | boolean expressions, forall, exists, implies
|
|---|
| 139 |
|
|---|
| 140 | \section{Procedure contracts}
|
|---|
| 141 |
|
|---|
| 142 | \section{Concurrency specification}
|
|---|
| 143 |
|
|---|
| 144 | remote expressions, collection expressions
|
|---|
| 145 |
|
|---|
| 146 | \chapter{Pointers and Heaps}
|
|---|
| 147 |
|
|---|
| 148 | \chapter{Libraries}
|
|---|
| 149 |
|
|---|
| 150 |
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 |
|
|---|
| 154 |
|
|---|
| 155 |
|
|---|
| 156 |
|
|---|
| 157 |
|
|---|
| 158 |
|
|---|
| 159 |
|
|---|
| 160 |
|
|---|
| 161 |
|
|---|
| 162 |
|
|---|
| 163 | \section{Detailed descriptions of primitives}
|
|---|
| 164 |
|
|---|
| 165 | \subsection{\cproc} This is a primitive object type and functions like
|
|---|
| 166 | any other primitive C type (e.g., \texttt{int}). An object of this
|
|---|
| 167 | type refers to a process. It can be thought of as a process ID, but
|
|---|
| 168 | it is not an integer and cannot be cast to one. Certain expressions
|
|---|
| 169 | take an argument of \cproc{} type and some return something of
|
|---|
| 170 | \cproc{} type.
|
|---|
| 171 |
|
|---|
| 172 | \subsection{\cassert} This is an assertion statement. It takes as its
|
|---|
| 173 | sole argument an expression of boolean type. The expressions have a
|
|---|
| 174 | richer syntax than C expressions. During verification, the assertion
|
|---|
| 175 | is checked. If it does not hold, a violation is reported.
|
|---|
| 176 | \begin{verbatim}
|
|---|
| 177 | $assert ( expr ) ;
|
|---|
| 178 | \end{verbatim}
|
|---|
| 179 | Boolean values \ctrue{} and \cfalse{} may be used in assertions
|
|---|
| 180 | and assumptions.
|
|---|
| 181 |
|
|---|
| 182 | The assertion statement may take additional optional arguments
|
|---|
| 183 | used to print a specific message if the assertion is violated.
|
|---|
| 184 | These additional arguments are similar in form to those used
|
|---|
| 185 | in C's \texttt{printf} statement: a format string, followed by
|
|---|
| 186 | some number of arguments which are evaluated and substituted
|
|---|
| 187 | for successive codes in the format string. For example,
|
|---|
| 188 | \begin{verbatim}
|
|---|
| 189 | $assert(x<=B, "x-coordinate %f exceeds bound %f", x, B);
|
|---|
| 190 | \end{verbatim}
|
|---|
| 191 |
|
|---|
| 192 |
|
|---|
| 193 | \subsection{\cassume} As \emph{assume statement} has the form
|
|---|
| 194 | \begin{verbatim}
|
|---|
| 195 | $assume expr;
|
|---|
| 196 | \end{verbatim}
|
|---|
| 197 | During verification, the assumed expression is assumed to hold. If
|
|---|
| 198 | this leads to a contradiction on some execution, that execution is
|
|---|
| 199 | simply ignored. It never reports a violation, it only restricts the
|
|---|
| 200 | set of possible executions that will be explored by the verification
|
|---|
| 201 | algorithm.
|
|---|
| 202 |
|
|---|
| 203 | Like as assertion statement, as assume statement can be used any place
|
|---|
| 204 | a statement is expected. In addition, as assume statement can be used
|
|---|
| 205 | in file scope to place restrictions on the global variables of the
|
|---|
| 206 | programs. For example,
|
|---|
| 207 | \begin{verbatim}
|
|---|
| 208 | $input int B;
|
|---|
| 209 | $input int N;
|
|---|
| 210 | $assume 0<=N && N<=B;
|
|---|
| 211 | \end{verbatim}
|
|---|
| 212 | declares \texttt{N} and \texttt{B} to be integer inputs and restricts
|
|---|
| 213 | consideration to inputs satisfying $0\leq\texttt{N}\leq\texttt{B}$.
|
|---|
| 214 |
|
|---|
| 215 | \subsection{\catom} This defines a number of statements to be executed
|
|---|
| 216 | as a single atomic transition. An \catom~block has the following
|
|---|
| 217 | form:
|
|---|
| 218 | \begin{verbatim}
|
|---|
| 219 | $atom {
|
|---|
| 220 | stmt1;
|
|---|
| 221 | stmt2;
|
|---|
| 222 | ...
|
|---|
| 223 | }
|
|---|
| 224 | \end{verbatim}
|
|---|
| 225 |
|
|---|
| 226 | The statements inside an \catom\ block are to be executed as one
|
|---|
| 227 | transition. It is required that the execution of the statements in an
|
|---|
| 228 | \catom\ block satisfy all of the following properties:
|
|---|
| 229 | \begin{enumerate}
|
|---|
| 230 | \item \emph{deterministic}: at each step in the execution of the atom
|
|---|
| 231 | block, there must be at most one enabled statement;
|
|---|
| 232 | \item \emph{nonblocking}: at each step in the execution, there must be
|
|---|
| 233 | at least one enabled statement, hence, together with (1), there must
|
|---|
| 234 | be exactly one enabled statement;
|
|---|
| 235 | \item \emph{finite}: the execution of the atom block must terminate
|
|---|
| 236 | after a finite number of steps; and
|
|---|
| 237 | \item \emph{isolated}: there are no jumps from outside the atom block
|
|---|
| 238 | to inside the atom block, or from inside the atomc block to outside
|
|---|
| 239 | of it.
|
|---|
| 240 | \end{enumerate}
|
|---|
| 241 |
|
|---|
| 242 | Violations of the \emph{deterministic}, \emph{nonblocking}, or
|
|---|
| 243 | \emph{isolated} properties will be reported either statically or
|
|---|
| 244 | dynamically. If the \emph{finite} property is violated, the
|
|---|
| 245 | verification may just run forever.
|
|---|
| 246 |
|
|---|
| 247 | Once the process enters an \catom\ block is said to be \emph{executing
|
|---|
| 248 | atomly}. The process remains executing atomly until it reaches the
|
|---|
| 249 | terminating right brace of the block. Hence \emph{executing atomly}
|
|---|
| 250 | is a dynamic, not static condition. For example, the block might
|
|---|
| 251 | contain a function call which takes the process to a point in code
|
|---|
| 252 | which is not statically contained in an atom block; that process is
|
|---|
| 253 | nevertheless still executing atomly and is subject to the rules above.
|
|---|
| 254 | The process only stops executing atomly when that function call
|
|---|
| 255 | returns and control finally reaches the right curly brace at the end
|
|---|
| 256 | of the atom block (assuming the block is not contained in another atom
|
|---|
| 257 | block).
|
|---|
| 258 |
|
|---|
| 259 | \emph{Note:} \cwait\ statements are not allowed in \catom\ blocks.
|
|---|
| 260 | The rationale for this is that there is never a way to know for
|
|---|
| 261 | certain that another process has terminated (until \cwait\ has
|
|---|
| 262 | returned) so there is never a way to be certain the \cwait\ statement
|
|---|
| 263 | will not block. If one does occur in an \catom\ block, an error will
|
|---|
| 264 | be reported statically (if it can be detected statically) or
|
|---|
| 265 | dynamically (otherwise). Note that it is not always possible to
|
|---|
| 266 | detect this statically because the \catom\ block may contain a
|
|---|
| 267 | function call, and the function may contain the \cwait\ statement.
|
|---|
| 268 |
|
|---|
| 269 | \subsection{\catomic} The statements in an \emph{atomic} block
|
|---|
| 270 | will be executed without other processes interleaving, to
|
|---|
| 271 | the extent possible. It has the form:
|
|---|
| 272 | \begin{verbatim}
|
|---|
| 273 | $atomic {
|
|---|
| 274 | stmt1;
|
|---|
| 275 | stmt2;
|
|---|
| 276 | ...
|
|---|
| 277 | }
|
|---|
| 278 | \end{verbatim}
|
|---|
| 279 | It is essentially a weaker form of \catom. Unlike \catom, there are
|
|---|
| 280 | no restrictions on the statements that can go inside an \catomic\
|
|---|
| 281 | block. A process executing an \catomic~block will try to execute the
|
|---|
| 282 | statements without interleaving with other processes, unless it
|
|---|
| 283 | becomes blocked. Unlike an \catom, the statements in an atomic block
|
|---|
| 284 | do not necessarily execute as a single transition; they may be spread
|
|---|
| 285 | out over multiple transitions.
|
|---|
| 286 |
|
|---|
| 287 | When no statement is enabled, the execution of the \catomic\ block
|
|---|
| 288 | will be interrupted. At this point, other processes are allowed to
|
|---|
| 289 | execute. Eventually, if the original process becomes enabled due to
|
|---|
| 290 | the actions of other processes, it may be scheduled again, in which
|
|---|
| 291 | case it regains atomicity and continues where it left off. For
|
|---|
| 292 | example, after executing the first loop, the process executing the
|
|---|
| 293 | following code will become blocked at the first \cwait\ statement:
|
|---|
| 294 | \begin{verbatim}
|
|---|
| 295 | $atomic{
|
|---|
| 296 | for(int i = 0; i < 5; i++) p[i] = $spawn foo(i);
|
|---|
| 297 | for(int i = 0; i < 5; i++) $wait p[i];
|
|---|
| 298 | }
|
|---|
| 299 | \end{verbatim}
|
|---|
| 300 | Other processes will then execute. Eventually, if the process being
|
|---|
| 301 | waited on terminates, the original process becomes enabled and may be
|
|---|
| 302 | scheduled, in which case it regain atomicity, increments \texttt{i}
|
|---|
| 303 | and proceeds to the next $\cwait$ statement. This is in fact a common
|
|---|
| 304 | idiom for spawning and waiting on a set of processes.
|
|---|
| 305 |
|
|---|
| 306 | A process that enters an $\catomic$ block is said to be
|
|---|
| 307 | \emph{executing atomically}; it remains executing atomically until it
|
|---|
| 308 | reaches the closing curly brace.
|
|---|
| 309 |
|
|---|
| 310 | Both $\catom$ and $\catomic$ blocks can be nested arbitrarily, but
|
|---|
| 311 | $\catom$ overrides $\catomic$: a process that is executing atomly will
|
|---|
| 312 | continue executing atomly if it encounters an $\catomic$ statement;
|
|---|
| 313 | but a process executing atomically that encounters an $\catom$ will
|
|---|
| 314 | begin executing atomly.
|
|---|
| 315 |
|
|---|
| 316 | The atomic semantics are defined more precisely as follows: there is a
|
|---|
| 317 | single global variable called the \emph{atomic lock}. This variable
|
|---|
| 318 | can either be null (meaning the atomic lock is ``free''), or it can
|
|---|
| 319 | hold the PID of a process; that process is said to ``hold'' the atomic
|
|---|
| 320 | lock. Moreover, each process contains a special integer variable, its
|
|---|
| 321 | \emph{atomic counter}, which is initially 0. Every time a process
|
|---|
| 322 | enters an atomic block, it increments its atomic counter; every time
|
|---|
| 323 | it exits an atomic block, it decrements its counter. In order to
|
|---|
| 324 | increment its counter from $0$ to $1$, it must first wait for the
|
|---|
| 325 | atomic lock to become free, and then take the lock. When it
|
|---|
| 326 | decrements its counter from $1$ to $0$, it releases the atomic lock.
|
|---|
| 327 | When a process executing atomically becomes blocked, it releases the
|
|---|
| 328 | lock (without changing the value of its atomic counter).
|
|---|
| 329 |
|
|---|
| 330 | \subsection{\cchoose} A \cchoose{} statement has the form
|
|---|
| 331 | \begin{verbatim}
|
|---|
| 332 | $choose {
|
|---|
| 333 | stmt1;
|
|---|
| 334 | stmt2;
|
|---|
| 335 | ...
|
|---|
| 336 | default: stmt
|
|---|
| 337 | }
|
|---|
| 338 | \end{verbatim}
|
|---|
| 339 | The \texttt{default} clause is optional.
|
|---|
| 340 |
|
|---|
| 341 | The guards of the statements are evaluated and among those that are
|
|---|
| 342 | \emph{true}, one is chosen nondeterministically and executed. If none
|
|---|
| 343 | are \emph{true} and the \texttt{default} clause is present, it is
|
|---|
| 344 | chosen. The \texttt{default} clause will only be selected if all
|
|---|
| 345 | guards are \emph{false}. If no \texttt{default} clause is present and
|
|---|
| 346 | all guards are \emph{false}, the statement blocks. Hence the implicit
|
|---|
| 347 | guard of the \cchoose{} statement without a \texttt{default} clause is
|
|---|
| 348 | the disjunction of the guards of its sub-statements. The implicit
|
|---|
| 349 | guard of the \cchoose{} statement with a default clause is
|
|---|
| 350 | \emph{true}.
|
|---|
| 351 |
|
|---|
| 352 | Example: this shows how to encode a ``low-level'' CIVL guarded
|
|---|
| 353 | transition system:
|
|---|
| 354 |
|
|---|
| 355 | \begin{verbatim}
|
|---|
| 356 | l1: $choose {
|
|---|
| 357 | $when (x>0) {x--; goto l2;}
|
|---|
| 358 | $when (x==0) {y=1; goto l3;}
|
|---|
| 359 | default: {z=1; goto l4;}
|
|---|
| 360 | }
|
|---|
| 361 | l2: $choose {
|
|---|
| 362 | ...
|
|---|
| 363 | }
|
|---|
| 364 | l3: $choose {
|
|---|
| 365 | ...
|
|---|
| 366 | }
|
|---|
| 367 | \end{verbatim}
|
|---|
| 368 |
|
|---|
| 369 |
|
|---|
| 370 | \subsection{\cinput} A variable in the root scope only may be declared
|
|---|
| 371 | with this type modifier indicating it is an ``input'' variable, as in
|
|---|
| 372 | \begin{verbatim}
|
|---|
| 373 | $input int n;
|
|---|
| 374 | \end{verbatim}
|
|---|
| 375 | As explained above, the variable becomes a parameter to the root
|
|---|
| 376 | procedure. This is used when comparing two programs for functional
|
|---|
| 377 | equivalence. The two programs are functionally equivalent if,
|
|---|
| 378 | whenever they are given the same inputs (i.e., corresponding \cinput{}
|
|---|
| 379 | variables are initialized with the same values) they will produce the
|
|---|
| 380 | same outputs (i.e., corresponding \coutput{} variables will end up
|
|---|
| 381 | with the same values at termination). Input variables can also be
|
|---|
| 382 | assigned a concrete value on the command line.
|
|---|
| 383 |
|
|---|
| 384 | \subsection{\cinvariant} This indicates a loop invariant. Each C loop
|
|---|
| 385 | construct has an optional invariant clause as follows:
|
|---|
| 386 | \begin{verbatim}
|
|---|
| 387 | while (expr) $invariant (expr) stmt
|
|---|
| 388 | for (e1; e2; e3) $invariant (expr) stmt
|
|---|
| 389 | do stmt while (expr) $invariant (expr) ;
|
|---|
| 390 | \end{verbatim}
|
|---|
| 391 | The invariant encodes the claim that if \texttt{expr} holds upon
|
|---|
| 392 | entering the loop and the loop condition holds, then it will hold
|
|---|
| 393 | after completion of execution of the loop body. The invariant is used
|
|---|
| 394 | by certain verification techniques.
|
|---|
| 395 |
|
|---|
| 396 | \emph{Status:} parsed, but nothing is currently done with this
|
|---|
| 397 | information.
|
|---|
| 398 |
|
|---|
| 399 | \subsection{\coutput} A variable in the root scope may be declared
|
|---|
| 400 | with this type modifier to declare it to be an output variable.
|
|---|
| 401 |
|
|---|
| 402 | \subsection{\cself} This is a constant of type \cproc. It can be used
|
|---|
| 403 | wherever an argument of type \cproc{} is called for. It refers to the
|
|---|
| 404 | process that is evaluating the expression containing ``\cself''.
|
|---|
| 405 |
|
|---|
| 406 | \subsection{\cspawn} This is an expression with side-effects. It
|
|---|
| 407 | spawns a new process and returns a reference to the new process, i.e.,
|
|---|
| 408 | an object of type \cproc. The syntax is the same as a procedure
|
|---|
| 409 | invocation with the keyword ``\cspawn'' inserted in front:
|
|---|
| 410 | \begin{verbatim}
|
|---|
| 411 | $spawn f(expr1, ..., exprn)
|
|---|
| 412 | \end{verbatim}
|
|---|
| 413 | Typically the returned value is assigned to a variable, e.g.,
|
|---|
| 414 | \begin{verbatim}
|
|---|
| 415 | $proc p = $spawn f(i);
|
|---|
| 416 | \end{verbatim}
|
|---|
| 417 | If the invoked function \texttt{f} returns a value, that value is
|
|---|
| 418 | simply ignored.
|
|---|
| 419 |
|
|---|
| 420 | \subsection{\cwait} This is a statement that takes an argument of type
|
|---|
| 421 | \cproc{} and blocks until the referenced process terminates:
|
|---|
| 422 | \begin{verbatim}
|
|---|
| 423 | $wait expr;
|
|---|
| 424 | \end{verbatim}
|
|---|
| 425 |
|
|---|
| 426 | \subsection{\cwhen} This represents a guarded command:
|
|---|
| 427 | \begin{verbatim}
|
|---|
| 428 | $when (expr) stmt;
|
|---|
| 429 | \end{verbatim}
|
|---|
| 430 | All statements have a guard, either implicit or explicit. For most
|
|---|
| 431 | statements, the guard is \ctrue. The \cwhen{} statement allows one to
|
|---|
| 432 | attach an explicit guard to a statement.
|
|---|
| 433 |
|
|---|
| 434 | When \texttt{expr} is \emph{true}, the statement is enabled, otherwise
|
|---|
| 435 | it is disabled. A disabled statement is \emph{blocked}---it will not
|
|---|
| 436 | be scheduled for execution. When it is enabled, it may execute by
|
|---|
| 437 | moving control to the \texttt{stmt} and executing the first atomic
|
|---|
| 438 | action in the \texttt{stmt}.
|
|---|
| 439 |
|
|---|
| 440 | If \texttt{stmt} itself has a non-trivial guard, the guard of the
|
|---|
| 441 | \cwhen{} statement is effectively the conjunction of the \texttt{expr}
|
|---|
| 442 | and the guard of \texttt{stmt}.
|
|---|
| 443 |
|
|---|
| 444 | The evaluation of \texttt{expr} and the first atomic action of
|
|---|
| 445 | \texttt{stmt} effectively occur as a single atomic action. There is
|
|---|
| 446 | no guarantee that execution of \texttt{stmt} will continue atomically
|
|---|
| 447 | if it contains more than one atomic action, i.e., other processes may
|
|---|
| 448 | be scheduled.
|
|---|
| 449 |
|
|---|
| 450 | Examples:
|
|---|
| 451 | \begin{verbatim}
|
|---|
| 452 | $when (s>0) s--;
|
|---|
| 453 | \end{verbatim}
|
|---|
| 454 | This will block until \texttt{s} is positive and then decrement
|
|---|
| 455 | \texttt{s}. The execution of \texttt{s--} is guaranteed to take place
|
|---|
| 456 | in an environment in which \texttt{s} is positive.
|
|---|
| 457 |
|
|---|
| 458 | \begin{verbatim}
|
|---|
| 459 | $when (s>0) {s--; t++}
|
|---|
| 460 | \end{verbatim}
|
|---|
| 461 | The execution of \texttt{s--} must happen when \texttt{s>0}, but
|
|---|
| 462 | between \texttt{s--} and \texttt{t++}, other processes may execute.
|
|---|
| 463 |
|
|---|
| 464 | \begin{verbatim}
|
|---|
| 465 | $when (s>0) $when (t>0) x=y*t;
|
|---|
| 466 | \end{verbatim}
|
|---|
| 467 | This blocks until both \texttt{x} and \texttt{t} are positive then
|
|---|
| 468 | executes the assignment in that state. It is equivalent to
|
|---|
| 469 | \begin{verbatim}
|
|---|
| 470 | $when (s>0 && t>0) x=y*t;
|
|---|
| 471 | \end{verbatim}
|
|---|
| 472 |
|
|---|
| 473 | \subsection{Procedure contracts}
|
|---|
| 474 | The \crequires{} and \censures{} primitives are used to encode
|
|---|
| 475 | procedure contracts. There are optional
|
|---|
| 476 | elements that may occur in a procedure declaration or definition,
|
|---|
| 477 | as follows. For a function prototype:
|
|---|
| 478 | \begin{verbatim}
|
|---|
| 479 | T f(...)
|
|---|
| 480 | $requires expr;
|
|---|
| 481 | $ensures expr;
|
|---|
| 482 | ;
|
|---|
| 483 | \end{verbatim}
|
|---|
| 484 | For a function definition:
|
|---|
| 485 | \begin{verbatim}
|
|---|
| 486 | T f(...)
|
|---|
| 487 | $requires expr;
|
|---|
| 488 | $ensures expr;
|
|---|
| 489 | {
|
|---|
| 490 | ...
|
|---|
| 491 | }
|
|---|
| 492 | \end{verbatim}
|
|---|
| 493 | The value \cresult{} may be used in post-conditions to refer
|
|---|
| 494 | to the result returned by a procedure.
|
|---|
| 495 |
|
|---|
| 496 | \emph{Status}: parsed, but nothing is currently done with this
|
|---|
| 497 | information.
|
|---|
| 498 |
|
|---|
| 499 | \subsection{Remote expressions}. These have the form \verb!expr@x!
|
|---|
| 500 | and refer to a variable in another process, e.g., \verb!procs[i]@x!.
|
|---|
| 501 | This special kind of expression is used in collective expressions,
|
|---|
| 502 | which are used to formulate collective assertions and invariants.
|
|---|
| 503 |
|
|---|
| 504 | The expression \verb!expr! must have \cproc{} type. The variable
|
|---|
| 505 | \texttt{x} must be a statically visible variable in the context in
|
|---|
| 506 | which it is occurs. When this expression is evaluated, the evaluation
|
|---|
| 507 | context will be shifted to the process referred to by \texttt{expr}.
|
|---|
| 508 |
|
|---|
| 509 | \emph{Status}: not implemented.
|
|---|
| 510 |
|
|---|
| 511 | \subsection{Collective expressions}. These have the form
|
|---|
| 512 | \begin{verbatim}
|
|---|
| 513 | $collective(proc_expr, int_expr) expr
|
|---|
| 514 | \end{verbatim}
|
|---|
| 515 | This is a collective expression over a set of processes. The
|
|---|
| 516 | expression \texttt{proc{\U}expr} yields a pointer to the first element
|
|---|
| 517 | of an array of \cproc. The expression \texttt{int{\U}expr} gives the
|
|---|
| 518 | length of that array, i.e., the number of processes. Expression
|
|---|
| 519 | \texttt{expr} is a boolean-valued expression; it may use remote
|
|---|
| 520 | expressions to refer to variables in the processes specified in the
|
|---|
| 521 | array. Example:
|
|---|
| 522 | \begin{verbatim}
|
|---|
| 523 | $proc procs[N];
|
|---|
| 524 | ...
|
|---|
| 525 | $assert $collective(procs, N) i==procs[(pid+1)%N]@i ;
|
|---|
| 526 | \end{verbatim}
|
|---|
| 527 |
|
|---|
| 528 | \emph{Status}: not implemented.
|
|---|
| 529 |
|
|---|
| 530 | \chapter{Pointers and heaps}
|
|---|
| 531 |
|
|---|
| 532 | CIVL-C supports pointers, using the same operators with the same
|
|---|
| 533 | meanings as C (\texttt{\&}, \texttt{*}, pointer arithmetic).
|
|---|
| 534 | As mentioned above, there is also a heap type \cheap{}, which can
|
|---|
| 535 | be used to declare multiple heaps in a CIVL-C program. The
|
|---|
| 536 | interaction between pointers, heaps, and scopes is an important
|
|---|
| 537 | aspect of CIVL-C.
|
|---|
| 538 |
|
|---|
| 539 | \section{Pointer types}
|
|---|
| 540 |
|
|---|
| 541 | Given any object type $T$ and a static scope $s$ in a CIVL-C program,
|
|---|
| 542 | there is a type \emph{pointer-to-$T$-in-$s$}. The type is used to
|
|---|
| 543 | represent a pointer to a memory location of type $T$ in scope $s$ or a
|
|---|
| 544 | descendant of $s$ (i.e., some scope contained in $s$).
|
|---|
| 545 |
|
|---|
| 546 | If scope $s_1$ is a descendant of $s_2$ (i.e., $s_1$ is lexically
|
|---|
| 547 | contained in $s_2$), the type \emph{pointer-to-$T$-in-$s_1$} is a
|
|---|
| 548 | subtype of \emph{pointer-to-$T$-in-$s_2$}. This means that any
|
|---|
| 549 | expression of the first type can be used wherever an object of the
|
|---|
| 550 | second type is expected. In particular, any expression $e$ of the
|
|---|
| 551 | subtype can be assigned to a left-hand-side expression of the
|
|---|
| 552 | supertype without explicit casts; also $e$ can be used as an argument
|
|---|
| 553 | to a function for which the corresponding parameter has the supertype.
|
|---|
| 554 |
|
|---|
| 555 | The syntax for denoting this type adheres to the usual C syntax for
|
|---|
| 556 | denoting the type \emph{pointer-to-$T$} with the addition of a scope
|
|---|
| 557 | parameter within angular brackets immediately following the \texttt{*}
|
|---|
| 558 | token. For example, to declare a variable \texttt{p} of type
|
|---|
| 559 | \emph{pointer-to-$T$-in-$s$}, one writes
|
|---|
| 560 | \begin{verbatim}
|
|---|
| 561 | int *<s> p;
|
|---|
| 562 | \end{verbatim}
|
|---|
| 563 | If the scope modifier \texttt{<...>} is absent, the scope is taken to
|
|---|
| 564 | be the root scope $s_0$. The object has type
|
|---|
| 565 | \emph{pointer-to-$T$-in-$s_0$}, which is abreviated as
|
|---|
| 566 | \emph{pointer-to-$T$}. In this way, stanard C programs can be
|
|---|
| 567 | interpreted as CIVL-C programs.
|
|---|
| 568 |
|
|---|
| 569 | \section{Address-of operator}
|
|---|
| 570 |
|
|---|
| 571 | The address-of operator \texttt{\&} returns a pointer of the
|
|---|
| 572 | appropriate subtype using the innermost scope in which its left-hand-side
|
|---|
| 573 | argument is declared. For example
|
|---|
| 574 |
|
|---|
| 575 | \begin{verbatim}
|
|---|
| 576 | {
|
|---|
| 577 | $scope s1;
|
|---|
| 578 | int x;
|
|---|
| 579 | double a[N];
|
|---|
| 580 | int *<s1> p = &x;
|
|---|
| 581 | double *<s1> q = &a[2];
|
|---|
| 582 | }
|
|---|
| 583 | \end{verbatim}
|
|---|
| 584 | is correct (in particular, it is type-correct) because \texttt{\&x}
|
|---|
| 585 | has type \emph{pointer-to-\texttt{int}-in-\texttt{s1}}, since
|
|---|
| 586 | \texttt{s1} is the scope in which \texttt{x} is declared.
|
|---|
| 587 |
|
|---|
| 588 | \section{Pointer addition and subtractions}
|
|---|
| 589 |
|
|---|
| 590 | If \texttt{e} is an expression of type \emph{pointer-to-$T$-in-$s$}
|
|---|
| 591 | and \texttt{i} is an expression of integer type then \texttt{e+i} also
|
|---|
| 592 | has type \emph{pointer-to-$T$-in-$s$}. In other words, pointer
|
|---|
| 593 | addition cannot leave the scope of the original pointer. This
|
|---|
| 594 | reflects the fact that every object is contained in one scope, and
|
|---|
| 595 | pointer addition cannot leave the object.
|
|---|
| 596 |
|
|---|
| 597 |
|
|---|
| 598 | Pointer subtraction is defined on two pointers of the same type, where
|
|---|
| 599 | ``same'' includes the scope. That is checked statically. As in C, it
|
|---|
| 600 | is only defined if the two pointers point to the same object. In
|
|---|
| 601 | CIVL-C, a runtime error will be thrown if they do not point to the
|
|---|
| 602 | same object.
|
|---|
| 603 |
|
|---|
| 604 | \section{Semantics of scopes and pointer types}
|
|---|
| 605 |
|
|---|
| 606 | A variable of type \cscope{} is treated like any other variable.
|
|---|
| 607 | It becomes part of the state when the scope in which it is declared
|
|---|
| 608 | is instantiated to form a dynamic scope. The variable is
|
|---|
| 609 | initialized at that time and its value cannot change.
|
|---|
| 610 |
|
|---|
| 611 | Each time a dynamic scope is instantiated, it is assigned a unique ID
|
|---|
| 612 | number. The exactly value of the ID number is not relevant, it just
|
|---|
| 613 | has to be distince from any other scope ID number that currently
|
|---|
| 614 | exists in the state. This is the value that is assigned to the scope
|
|---|
| 615 | variable. Therefore, if a static scope contains a scope variable, and
|
|---|
| 616 | that scope is instantiated twice to form two distinct dynamic scopes,
|
|---|
| 617 | the values assigned to the two variables will be distinct.
|
|---|
| 618 |
|
|---|
| 619 | A pointer value is an ordered pair $\langle \delta,r \rangle$, where
|
|---|
| 620 | $\delta$ is a dynamic scope ID and $r$ is a reference to a memory
|
|---|
| 621 | location in the static scope associated to $\delta$. (We will define
|
|---|
| 622 | the exact form of a reference later.)
|
|---|
| 623 |
|
|---|
| 624 | When a dynamic scope is instantiated, each new variable created is
|
|---|
| 625 | assigned a \emph{dynamic type}. This is a refinement of the static
|
|---|
| 626 | type associated to the static variable. Every dynamic type
|
|---|
| 627 | is an instance of exactly one static type. The dynamic
|
|---|
| 628 | type of the newly instantiated variable is an instance of the
|
|---|
| 629 | static type of the static variable.
|
|---|
| 630 |
|
|---|
| 631 | The dynamic pointer types have the form
|
|---|
| 632 | \emph{pointer-to-$t$-in-$\delta$}, where $t$ is a dynamic type and
|
|---|
| 633 | $\delta$ is a dynamic scope ID. For a program to be dynamically type
|
|---|
| 634 | safe, such a variable should hold only values of the form $\langle
|
|---|
| 635 | \delta, r\rangle$. In particular, the variable should never be
|
|---|
| 636 | assigned a value where the dynamic scope component is a different
|
|---|
| 637 | instance of the static scope $s$ associated to $\delta$.
|
|---|
| 638 |
|
|---|
| 639 | \section{Pointer casts}
|
|---|
| 640 |
|
|---|
| 641 | If scope $s_1$ is contained in scope $s_2$, an expression of type
|
|---|
| 642 | \emph{pointer-to-$T$-in-$s_1$} can always be cast to
|
|---|
| 643 | \emph{pointer-to-$T$-in-$s_2$},
|
|---|
| 644 | because the first is a subtype of the second. (As described above,
|
|---|
| 645 | the cast is unnecessary.)
|
|---|
| 646 |
|
|---|
| 647 | The cast in the other direction is also allowed, but the dynamic type
|
|---|
| 648 | safety of that cast will only be checked at runtime. In particular, a
|
|---|
| 649 | runtime error will result if the cast attempts to cast the pointer
|
|---|
| 650 | value to a dynamic scope which does not contain (is an ancestor of)
|
|---|
| 651 | the dynamic scope component of the pointer value.
|
|---|
| 652 |
|
|---|
| 653 | A type \emph{pointer-to-$T_1$-in-$s$} can be cast to a type
|
|---|
| 654 | \emph{pointer-to-$T_2$-in-$s$} according to the usual rules of C. In
|
|---|
| 655 | other words, usual casting rules apply as long as you don't change the
|
|---|
| 656 | scope.
|
|---|
| 657 |
|
|---|
| 658 |
|
|---|
| 659 |
|
|---|
| 660 | \section{Heaps}
|
|---|
| 661 |
|
|---|
| 662 | The standard CIVL-C library defines a type \cheap{} for explicit
|
|---|
| 663 | modeling of a heap. The default value of \cheap{} type is an empty
|
|---|
| 664 | heap, so you only need to declare a variable to have type \cheap{}
|
|---|
| 665 | in order to create a new heap:
|
|---|
| 666 | \begin{verbatim}
|
|---|
| 667 | $heap h; /* a new empty heap */
|
|---|
| 668 | \end{verbatim}
|
|---|
| 669 |
|
|---|
| 670 | The following functions are also defined:
|
|---|
| 671 | \begin{verbatim}
|
|---|
| 672 | void* $malloc($heap *h, int size);
|
|---|
| 673 | void memcpy(void *p, void *q, size_t size);
|
|---|
| 674 | void free(void *p)
|
|---|
| 675 | \end{verbatim}
|
|---|
| 676 | The first function is like C's \texttt{malloc}, except that you
|
|---|
| 677 | specify the heap in which the allocation takes place by passing a
|
|---|
| 678 | pointer to the heap as the first argument. This modifies the
|
|---|
| 679 | specified heap and returns a pointer to the new object. The function
|
|---|
| 680 | can only occur in a context in which the type of the object is
|
|---|
| 681 | specified, as in:
|
|---|
| 682 | \begin{verbatim}
|
|---|
| 683 | $heap h;
|
|---|
| 684 | int n = 10;
|
|---|
| 685 | double *p = (double*)$malloc(&h, n*sizeof(double));
|
|---|
| 686 | \end{verbatim}
|
|---|
| 687 | The second and third functions are exactly the same as in C. Note that
|
|---|
| 688 | \texttt{free} modifies the heap which was used to allocate \texttt{p}.
|
|---|
| 689 |
|
|---|
| 690 | Another pointer example:
|
|---|
| 691 | \begin{small}
|
|---|
| 692 | \begin{verbatim}
|
|---|
| 693 | { $heap h;
|
|---|
| 694 | { $scope s1;
|
|---|
| 695 | double x;
|
|---|
| 696 | { $scope s2;
|
|---|
| 697 | double y;
|
|---|
| 698 | double *<s1> p;
|
|---|
| 699 | /* p can only point to something in s1 or descendant,
|
|---|
| 700 | * for example, s2 */
|
|---|
| 701 | p = &x; // fine
|
|---|
| 702 | p = &y; // fine
|
|---|
| 703 | p = (double*)$malloc(&h,10*sizeof(double)); // static type error
|
|---|
| 704 | }
|
|---|
| 705 | }
|
|---|
| 706 | }
|
|---|
| 707 | \end{verbatim}
|
|---|
| 708 | \end{small}
|
|---|
| 709 |
|
|---|
| 710 | \emph{Status}: Pointer type, \texttt{\&}, \texttt{*}, pointer addition
|
|---|
| 711 | all implemented. Type \cheap{}, \texttt{malloc}, \texttt{free}
|
|---|
| 712 | implemented. Scope-qualified pointers: parsed, type-checked, but
|
|---|
| 713 | information not currently used.
|
|---|
| 714 |
|
|---|
| 715 | \section{Scope-Parameterized Functions}
|
|---|
| 716 |
|
|---|
| 717 | Coming soon. (Parsed, type checked, not currently used otherwise.)
|
|---|
| 718 |
|
|---|
| 719 | \section{Scope-Parameterized Type Definitions}
|
|---|
| 720 |
|
|---|
| 721 | Coming soon. (Ditto.)
|
|---|
| 722 |
|
|---|
| 723 | \chapter{Library}
|
|---|
| 724 |
|
|---|
| 725 | The standard CIVL-C library is included into a program automtically
|
|---|
| 726 | with \texttt{civlc.h}. The library defines a number of additional
|
|---|
| 727 | functions, types, and constants.
|
|---|
| 728 |
|
|---|
| 729 | \section{Misc. functions}
|
|---|
| 730 |
|
|---|
| 731 | \subsection{\cexit} This function takes no arguments. It causes the
|
|---|
| 732 | calling process to terminate immediately, regardless of the state of
|
|---|
| 733 | its call stack:
|
|---|
| 734 | \begin{verbatim}
|
|---|
| 735 | void $exit(void);
|
|---|
| 736 | \end{verbatim}
|
|---|
| 737 |
|
|---|
| 738 | \subsection{\cchooseint} This is a function with the following
|
|---|
| 739 | prototype:
|
|---|
| 740 | \begin{verbatim}
|
|---|
| 741 | int $choose_int(int n);
|
|---|
| 742 | \end{verbatim}
|
|---|
| 743 | It takes as input a positive integer \texttt{n} and
|
|---|
| 744 | nondeterministicaly returns an integer in the range
|
|---|
| 745 | $[0,\texttt{n}-1]$.
|
|---|
| 746 |
|
|---|
| 747 |
|
|---|
| 748 | \section{Bundles}
|
|---|
| 749 |
|
|---|
| 750 | The library defines a type called \cbundle. A bundle is basically a
|
|---|
| 751 | bunch of data, wrapped into an atomic package. A bundle is created
|
|---|
| 752 | using a function that specifies a region of memory. One can create a
|
|---|
| 753 | bundle from an array of integers, and another bundle from an array of
|
|---|
| 754 | reals. Both bundles have the same type, \cbundle. They can therfore
|
|---|
| 755 | be entered into an array of \cbundle, for example. Hence bundles are
|
|---|
| 756 | useful for mixing objects of different (even statically unknown) types
|
|---|
| 757 | into a single data structure. Later, the contents of a bundle can be
|
|---|
| 758 | extracted with another function that specifies a region of memory into
|
|---|
| 759 | which to unpack the bundle; if that memory does not have the right
|
|---|
| 760 | type to receive the contents of the bundle, a runtime error is
|
|---|
| 761 | generated.
|
|---|
| 762 |
|
|---|
| 763 | \begin{figure}
|
|---|
| 764 | \begin{verbatim}
|
|---|
| 765 | /* Creates a bundle from the memory region specified by
|
|---|
| 766 | * ptr and size, copying the data into the new bundle */
|
|---|
| 767 | $bundle $bundle_pack(void *ptr, int size);
|
|---|
| 768 |
|
|---|
| 769 | /* Returns the size (number of bytes) of the bundle */
|
|---|
| 770 | int $bundle_size($bundle b);
|
|---|
| 771 |
|
|---|
| 772 | /* Copies the data out of the bundle into the region
|
|---|
| 773 | * specified */
|
|---|
| 774 | void $bundle_unpack($bundle bundle, void *ptr);
|
|---|
| 775 | \end{verbatim}
|
|---|
| 776 | \caption{The \emph{bundle} abstract data type}
|
|---|
| 777 | \label{fig:bundle}
|
|---|
| 778 | \end{figure}
|
|---|
| 779 |
|
|---|
| 780 | The relevant functions for creating and manipulating bundles
|
|---|
| 781 | are given in Figure \ref{fig:bundle}.
|
|---|
| 782 |
|
|---|
| 783 | \section{Message Passing}
|
|---|
| 784 |
|
|---|
| 785 | The library defines a number of additional primitives useful for
|
|---|
| 786 | modeling message-passing systems. This part of the library is built
|
|---|
| 787 | in two layers: the lower layer defines an abstract data type for
|
|---|
| 788 | representing messages; the higher layer defines an abstract data type
|
|---|
| 789 | of \emph{communicators} for managing sets of messages being
|
|---|
| 790 | transferred among some set of processes.
|
|---|
| 791 |
|
|---|
| 792 | \subsection{Messages}
|
|---|
| 793 |
|
|---|
| 794 | Messages are similar to bundles, but with some additional
|
|---|
| 795 | ``meta-data''. The \emph{data} component of the message is the
|
|---|
| 796 | ``contents'' of the message and is formed and extracted much like a
|
|---|
| 797 | bundle. The meta-data consists of an integer identifier for the
|
|---|
| 798 | \emph{source} (sender) of the message, an integer identifier for the
|
|---|
| 799 | message \emph{destination} (receiver), and integer \emph{tag} which
|
|---|
| 800 | can be used by the received to discriminate among messages for
|
|---|
| 801 | reception. This is very similar to MPI.
|
|---|
| 802 |
|
|---|
| 803 | \begin{figure}
|
|---|
| 804 | \begin{verbatim}
|
|---|
| 805 | /* creates a new message, copying data from the specified buffer */
|
|---|
| 806 | $message $message_pack(int source, int dest, int tag,
|
|---|
| 807 | void *data, int size);
|
|---|
| 808 |
|
|---|
| 809 | /* returns the message source */
|
|---|
| 810 | int $message_source($message message);
|
|---|
| 811 |
|
|---|
| 812 | /* returns the message tag */
|
|---|
| 813 | int $message_tag($message message);
|
|---|
| 814 |
|
|---|
| 815 | /* returns the message destination */
|
|---|
| 816 | int $message_dest($message message);
|
|---|
| 817 |
|
|---|
| 818 | /* returns the message size */
|
|---|
| 819 | int $message_size($message message);
|
|---|
| 820 |
|
|---|
| 821 | /* transfers message data to buf, throwing exception if message
|
|---|
| 822 | * size exceeds specified size */
|
|---|
| 823 | void $message_unpack($message message, void *buf, int size);
|
|---|
| 824 | \end{verbatim}
|
|---|
| 825 | \caption{The \emph{message} abstract data type}
|
|---|
| 826 | \label{fig:message}
|
|---|
| 827 | \end{figure}
|
|---|
| 828 |
|
|---|
| 829 | The functions for creating, and extracting information from, messages
|
|---|
| 830 | are given in Figure \ref{fig:message}.
|
|---|
| 831 |
|
|---|
| 832 | \subsection{Communicators}
|
|---|
| 833 |
|
|---|
| 834 | The library defines a \emph{communicator} type $\ccomm$. As in MPI, a
|
|---|
| 835 | communicator is an abstraction for a ``communication universe'' that
|
|---|
| 836 | comprises a finite, fixed sequence of distinct processes and a
|
|---|
| 837 | collection of buffered messages that are being transmitted from one of
|
|---|
| 838 | those processes to another.
|
|---|
| 839 |
|
|---|
| 840 | \begin{figure}
|
|---|
| 841 | \begin{verbatim}
|
|---|
| 842 | /* creates a new comm from the given sequence of processes,
|
|---|
| 843 | * by allocating memory and copying the process sequence;
|
|---|
| 844 | * the new comm has no messages */
|
|---|
| 845 | $comm $comm_create(int nprocs, $proc * procs);
|
|---|
| 846 |
|
|---|
| 847 | /* returns the number of processes associated to the comm */
|
|---|
| 848 | int $comm_nprocs($comm * comm);
|
|---|
| 849 |
|
|---|
| 850 | /* adds the message to the comm */
|
|---|
| 851 | void $comm_enqueue($comm * comm, $message message);
|
|---|
| 852 |
|
|---|
| 853 | /* returns true iff a matching message exists in comm */
|
|---|
| 854 | _Bool $comm_probe($comm * comm, int source, int dest, int tag);
|
|---|
| 855 |
|
|---|
| 856 | /* finds the first matching message and returns pointer
|
|---|
| 857 | * to it without modifying comm */
|
|---|
| 858 | $message * $comm_seek($comm * comm, int source, int dest, int tag);
|
|---|
| 859 |
|
|---|
| 860 | /* finds the first matching message, removes it from
|
|---|
| 861 | * comm, and returns pointer to message */
|
|---|
| 862 | $message $comm_dequeue($comm * comm, int source, int dest, int tag);
|
|---|
| 863 |
|
|---|
| 864 | /* returns the number of messages from source to dest stored
|
|---|
| 865 | * in comm */
|
|---|
| 866 | int $comm_chan_size($comm * comm, int source, int dest);
|
|---|
| 867 |
|
|---|
| 868 | /* returns the total number of messages in the comm */
|
|---|
| 869 | int $comm_total_size($comm * comm);
|
|---|
| 870 | \end{verbatim}
|
|---|
| 871 | \caption{The \emph{communicator} abstract data type}
|
|---|
| 872 | \label{fig:comm}
|
|---|
| 873 | \end{figure}
|
|---|
| 874 |
|
|---|
| 875 | The functions for creating and modifying a communicator are
|
|---|
| 876 | specified in Figure \ref{fig:comm}.
|
|---|
| 877 |
|
|---|
| 878 | % \chapter{Some Translation Examples}
|
|---|
| 879 |
|
|---|
| 880 | % \section{Structured parallelism}
|
|---|
| 881 | % Structured \verb!parbegin!/\verb!parend! statements look like this:
|
|---|
| 882 | % \begin{verbatim}
|
|---|
| 883 | % $parbegin
|
|---|
| 884 | % S1; S2; S2
|
|---|
| 885 | % $parend
|
|---|
| 886 | % \end{verbatim}
|
|---|
| 887 | % (See Dijkstra, Cooperating Sequential Processes.) The meaning is: run
|
|---|
| 888 | % the three statements in parallel, and block at the end until all have
|
|---|
| 889 | % completed.
|
|---|
| 890 |
|
|---|
| 891 | % This can be represented in CIVL-C as follows:
|
|---|
| 892 |
|
|---|
| 893 | % \begin{verbatim}
|
|---|
| 894 | % {
|
|---|
| 895 | % void f_1() {S1}
|
|---|
| 896 | % void f_2() {S2}
|
|---|
| 897 | % void f_3() {S3}
|
|---|
| 898 | % $proc tmp1 = $fork f_1(), tmp2=$fork f_2(), tmp3=$fork f_3();
|
|---|
| 899 | % $join(tmp1); $join(tmp2); $join(tmp3);
|
|---|
| 900 | % }
|
|---|
| 901 | % \end{verbatim}
|
|---|
| 902 |
|
|---|
| 903 | % \subsection{Parallel for loops}
|
|---|
| 904 | % The standard parallel ``for'' loop looks like
|
|---|
| 905 | % \begin{verbatim}
|
|---|
| 906 | % $parfor(T i = e; cond; inc) S
|
|---|
| 907 | % \end{verbatim}
|
|---|
| 908 | % It indicates each iteration should be run concurrently, blocking
|
|---|
| 909 | % at end until all complete. In CIVL-C:
|
|---|
| 910 |
|
|---|
| 911 | % \begin{verbatim}
|
|---|
| 912 | % {
|
|---|
| 913 | % void f(T i) {S}
|
|---|
| 914 | % T i = e;
|
|---|
| 915 | % int c = 0;
|
|---|
| 916 | % Vector<$proc> list;
|
|---|
| 917 |
|
|---|
| 918 | % while (cond) {
|
|---|
| 919 | % list.add($fork f());
|
|---|
| 920 | % c++;
|
|---|
| 921 | % inc;
|
|---|
| 922 | % }
|
|---|
| 923 | % for (int j=0; j<c; j++) $join(list.get(j));
|
|---|
| 924 | % }
|
|---|
| 925 | % \end{verbatim}
|
|---|
| 926 |
|
|---|
| 927 | % (This is assuming we have some sort of Vector datatype. Need to think
|
|---|
| 928 | % about that.)
|
|---|
| 929 |
|
|---|
| 930 | % \subsection{Message Passing}
|
|---|
| 931 |
|
|---|
| 932 | % There will be a bunch of standard libraries that can be included
|
|---|
| 933 | % into CIVL-C. One of these will be the message-passing library.
|
|---|
| 934 | % It will define a bunch of primitives that we will fill in shortly.
|
|---|
| 935 | % Among them will be basic send and receive functions.
|
|---|
| 936 |
|
|---|
| 937 | % The message-passing library can be defined entirely in CIVL-C.
|
|---|
| 938 | % (See Figure \ref{fig:mp1}.)
|
|---|
| 939 |
|
|---|
| 940 | % \begin{figure}
|
|---|
| 941 | % \begin{verbatim}
|
|---|
| 942 | % typedef struct _CIVL_Message {
|
|---|
| 943 | % struct _CIVL_Message *next; // next message in this queue
|
|---|
| 944 | % struct _CIVL_Message *prev; // previous message in this queue
|
|---|
| 945 | % int tag; // message tag
|
|---|
| 946 | % int size; // size of buffer
|
|---|
| 947 | % void *data; // pointer to first element
|
|---|
| 948 | % } *CIVL_Message;
|
|---|
| 949 |
|
|---|
| 950 | % typedef struct _CIVL_Comm {
|
|---|
| 951 | % $heap heap;
|
|---|
| 952 | % int numProcs; // number of procs in this communicator
|
|---|
| 953 | % $proc *procs; // array of length numProcs
|
|---|
| 954 | % CIVL_Message buf_front[][]; // oldest element of each queue
|
|---|
| 955 | % CIVL_Message buf_back[][]; // newest element of each queue
|
|---|
| 956 | % } *CIVL_Comm;
|
|---|
| 957 | % \end{verbatim}
|
|---|
| 958 | % \caption{CIVL Message Passing library: basic definitions}
|
|---|
| 959 | % \label{fig:mp1}
|
|---|
| 960 | % \end{figure}
|
|---|
| 961 |
|
|---|
| 962 | % Message passing functions may be defined with prototypes such as:
|
|---|
| 963 | % \begin{verbatim}
|
|---|
| 964 | % CIVL_Comm CIVL_Comm_create($proc procs[], int numProcs);
|
|---|
| 965 | % void CIVL_send(int src, void *buf, int size, int dest,
|
|---|
| 966 | % int tag, CIVL_Comm comm);
|
|---|
| 967 | % void CIVL_recv(int dest, void *buf, int size, int src,
|
|---|
| 968 | % int tag, CIVL_Comm comm);
|
|---|
| 969 | % \end{verbatim}
|
|---|
| 970 |
|
|---|
| 971 | % The arguments for \texttt{send} are:
|
|---|
| 972 | % \begin{enumerate}
|
|---|
| 973 | % \item rank of process issuing the send
|
|---|
| 974 | % \item address of buffer containing data to be sent
|
|---|
| 975 | % \item size of message
|
|---|
| 976 | % \item an integer tag
|
|---|
| 977 | % \item rank of destination process
|
|---|
| 978 | % \item communicator
|
|---|
| 979 | % \end{enumerate}
|
|---|
| 980 |
|
|---|
| 981 | % The arguments for \texttt{recv} are:
|
|---|
| 982 | % \begin{enumerate}
|
|---|
| 983 | % \item rank of process issuing the receive
|
|---|
| 984 | % \item address of receive buffer
|
|---|
| 985 | % \item size of receive buffer (must be large enough to hold any incoming message)
|
|---|
| 986 | % \item rank of source process or \code{CIVL{\U}ANY{\U}SOURCE}
|
|---|
| 987 | % \item tag or \code{CIVL{\U}ANY{\U}TAG}
|
|---|
| 988 | % \item communicator
|
|---|
| 989 | % \end{enumerate}
|
|---|
| 990 |
|
|---|
| 991 | % Notice one difference from MPI: we have to specify the process to
|
|---|
| 992 | % which the send or receive is associated in the first argument. This is
|
|---|
| 993 | % because we need to be more general than MPI. In MPI, that process is
|
|---|
| 994 | % always the MPI process invoking the send or receive. In CIVL, you
|
|---|
| 995 | % might want to have threads within processes (for example) and
|
|---|
| 996 | % associate the message to the MPI process, even though the thread is
|
|---|
| 997 | % actually invoking the send. Or you might want to associate it to
|
|---|
| 998 | % something else in some other language/library/API.
|
|---|
| 999 |
|
|---|
| 1000 | % How they are implemented: \texttt{CIVL{\U}Comm{\U}create}
|
|---|
| 1001 | % mallocs a new object of type \texttt{struct {\U}CIVL{\U}Comm} and returns
|
|---|
| 1002 | % a pointer to it.
|
|---|
| 1003 |
|
|---|