| [135e8cf] | 1 | # CIVL-C Language Manual
|
|---|
| 2 |
|
|---|
| 3 | ## Types {#sec:types}
|
|---|
| 4 |
|
|---|
| 5 | ### The Boolean type {#boolean-type}
|
|---|
| 6 |
|
|---|
| 7 | The boolean type is denoted `_Bool`, as in C. Its values are 0 and 1, which are also denoted by `$false` and `$true`, respectively.
|
|---|
| 8 | One may also include the standard C header `stdbool.h`, which defines `false` and `true` (also as 0 and 1), and defines the type
|
|---|
| 9 | `bool` to be an alias for `_Bool`.
|
|---|
| 10 |
|
|---|
| 11 | ### The integer type {#int-types}
|
|---|
| 12 |
|
|---|
| 13 | There is one integer type, corresponding to the mathematical integers.
|
|---|
| 14 | Currently, all of the C integer types `int`, `long`, `unsigned int`, `short`, etc., are mapped to the CIVL integer type.
|
|---|
| 15 | [This is expected to change.]
|
|---|
| 16 |
|
|---|
| 17 | ### The real type {#real-types}
|
|---|
| 18 |
|
|---|
| 19 | There is one real type, corresponding to the mathematical real numbers. Currently, all of the C real types `double`, `float`, etc., are mapped to the CIVL real type.
|
|---|
| 20 | [This is expected to change.]
|
|---|
| 21 |
|
|---|
| 22 | ### The process type `$proc` {#proc-type}
|
|---|
| 23 |
|
|---|
| 24 | This is a primitive object type and functions like any other primitive C type (e.g., `int`).
|
|---|
| 25 | An object of this type refers to a process. It can be thought of as a process ID, but it is not an integer and cannot be cast to one.
|
|---|
| 26 | Certain expressions take an argument of `$proc` type and some return something of `$proc` type.
|
|---|
| 27 | The operators `==` and `!=` may be used with two arguments of type `$proc` to determine whether the two arguments refer to the same process.
|
|---|
| 28 | The constant `$self` has `$proc` type and refers to the process evaluating this expression; constant `$proc_null` has `$proc` type and refers to no process.
|
|---|
| 29 |
|
|---|
| 30 | ### The scope type `$scope` {#scope-type}
|
|---|
| 31 |
|
|---|
| 32 | An object of this type is a reference to a dynamic scope.
|
|---|
| 33 | Several constants, expressions, and functions dealing with the `$scope` type are also provided.
|
|---|
| 34 | The `$scope` type is like any other object type.
|
|---|
| 35 | It may be used as the element type of an array, a field in a structure or union, and so on.
|
|---|
| 36 | Expressions of type `$scope` may occur on the left or right-hand sides of assignments and as arguments in function calls just like any other expression.
|
|---|
| 37 | Two different variables of type `$scope` may be aliased, i.e., they may refer to the same dynamic scope.
|
|---|
| 38 |
|
|---|
| 39 | ### Domain types: `$domain` and `$domain(n)` {#domain-type}
|
|---|
| 40 |
|
|---|
| 41 | A domain type is used to represent a set of tuples of integer values.
|
|---|
| 42 | Every tuple in a domain object has the same arity (i.e., number of components).
|
|---|
| 43 | The arity must be at least 1, and is called the dimension of the domain object.
|
|---|
| 44 | For each integer constant expression n, there is a type `$domain(n)`, representing domains of dimension n.
|
|---|
| 45 | The universal domain type, denoted `$domain`, represents domains of all positive dimensions, i.e., it is the union over all n ≥ 1 of `$domain(n)`.
|
|---|
| 46 | In particular, each `$domain(n)` is a subtype of `$domain`.
|
|---|
| 47 | There are expressions for specifying domain values.
|
|---|
| 48 | Certain statements use domains, such as the [domain iteration statement](#for) `$for`.
|
|---|
| 49 |
|
|---|
| 50 | ### The range type `$range` {#range-type}
|
|---|
| 51 |
|
|---|
| 52 | An object of this type represents an ordered set of integers.
|
|---|
| 53 | Ranges are typically used as a step in constructing domains.
|
|---|
| 54 | They can also be used in quantified expressions to specify the domain of a bound variable (see [$forall and $exists](#boolean-expressions)).
|
|---|
| 55 |
|
|---|
| 56 | ## Type qualifiers {#qualifiers}
|
|---|
| 57 |
|
|---|
| 58 | ### Declaring input and output variables: `$input` and `$output` {#input-output}
|
|---|
| 59 |
|
|---|
| 60 | The declaration of a variable in the root scope may include the type qualifier `$input`, e.g.,
|
|---|
| 61 | ```civl
|
|---|
| 62 | $input int N;
|
|---|
| 63 | ```
|
|---|
| 64 | This declares the variable to be an input variable, i.e., one which is considered to be an input to the program.
|
|---|
| 65 | Such a variable is initialized with an arbitrary (unconstrained) value of its type.
|
|---|
| 66 | When using symbolic execution to verify a program, such a variable will be assigned a unique symbolic constant of its type.
|
|---|
| 67 | In contrast, variables in the root scope which are not input variables will instead be initialized with the “undefined” value.
|
|---|
| 68 | Reading an undefined value is erroneous.
|
|---|
| 69 |
|
|---|
| 70 | !!! note
|
|---|
| 71 |
|
|---|
| 72 | The model checker attempts to catch such errors but currently
|
|---|
| 73 | does not do so for arrays, which are always initialized with unconstrained values.
|
|---|
| 74 |
|
|---|
| 75 | In addition, input variables may only be read, never written to; an attempt to write to an input variable is also flagged as an error.
|
|---|
| 76 |
|
|---|
| 77 | Alternatively, it is possible to specify a particular concrete value for an input variable, either on the command line, e.g.,
|
|---|
| 78 | ```sh
|
|---|
| 79 | civl verify -inputN=8 ...
|
|---|
| 80 | ```
|
|---|
| 81 | or by including an initializer in the declaration, e.g.
|
|---|
| 82 | ```civl
|
|---|
| 83 | $input int N=8;
|
|---|
| 84 | ```
|
|---|
| 85 | The protocol for initializing an input variable is the following: if a command line value is specified, it is used.
|
|---|
| 86 | Otherwise, if an initializer is present, it is used. Otherwise, the variable is assigned an arbitrary value of its type.
|
|---|
| 87 |
|
|---|
| 88 | A variable in the root scope may be declared with `$output` to declare it to be an output variable.
|
|---|
| 89 | Output variables may only be written to, never read.
|
|---|
| 90 | They are used primarily in functional equivalence checking.
|
|---|
| 91 |
|
|---|
| 92 | Input and output variables play a key role when determining whether two programs are functionally equivalent.
|
|---|
| 93 | Two programs are considered functionally equivalent if, whenever they are given the same inputs (i.e., corresponding `$input`
|
|---|
| 94 | variables are initialized with the same values) they will produce the same outputs (i.e., corresponding `$output` variables will
|
|---|
| 95 | end up with the same values at termination).
|
|---|
| 96 |
|
|---|
| 97 | ### Abstract (uninterpreted) functions: `$abstract` {#abstract}
|
|---|
| 98 |
|
|---|
| 99 | An abstract function declares a function without a body.
|
|---|
| 100 | An abstract function is declared using a standard function prototype with the function qualifier `$abstract`, e.g.,
|
|---|
| 101 | ```civl
|
|---|
| 102 | $abstract int f(int x);
|
|---|
| 103 | ```
|
|---|
| 104 | An abstract function must have a non-`void` return type and take at least one parameter.
|
|---|
| 105 | An invocation of an abstract function is an expression and can be used anywhere an expression is allowed.
|
|---|
| 106 | The interpretation is an "uninterpreted function".
|
|---|
| 107 | A unique symbolic constant of function type will be created, corresponding to the abstract function, and invocations are represented
|
|---|
| 108 | as applications of the uninterpreted function to the arguments.
|
|---|
| 109 |
|
|---|
| 110 | ### Atomic functions: `$atomic_f` {#atomic_f}
|
|---|
| 111 |
|
|---|
| 112 | A function is declared atomic using the function qualifier `$atomic_f`, e.g.,
|
|---|
| 113 | ```civl
|
|---|
| 114 | $atomic_f int f(int x) {
|
|---|
| 115 | ...
|
|---|
| 116 | }
|
|---|
| 117 | ```
|
|---|
| 118 | A call to such a function executes as a single atomic step, i.e., without interleaving from other processes.
|
|---|
| 119 | Hence, this is only relevant for concurrent programs.
|
|---|
| 120 | Declaring a function to be atomic is almost equivalent to placing `$atomic{ ... }` around the function body.
|
|---|
| 121 | The difference is that in the latter case, the call to the function and the execution of the body are executed in two atomic steps, i.e.,
|
|---|
| 122 | after the activation frame is pushed onto the call stack, another process could execute before the first process obtains the atomic lock and executes its body.
|
|---|
| 123 | For an atomic function, the entire sequence of events happens in one atomic step.
|
|---|
| 124 |
|
|---|
| 125 | An atomic function must have a definition; in particular, neither a system function nor an abstract function may be declared using `$atomic_f`.
|
|---|
| 126 |
|
|---|
| 127 | The guard of an atomic function is taken to be the guard of the function's body. For example, if `f` is defined
|
|---|
| 128 | ```civl
|
|---|
| 129 | $atomic_f int f(int x) {
|
|---|
| 130 | $when (x>0);
|
|---|
| 131 | ...
|
|---|
| 132 | }
|
|---|
| 133 | ```
|
|---|
| 134 | then a call to `f` will block if the argument used in the call is not positive—no activation frame is pushed onto the stack unless the guard is true.
|
|---|
| 135 |
|
|---|
| 136 | ### System functions: `$system` {#system}
|
|---|
| 137 |
|
|---|
| 138 | A system function is one in which the definition of the function is not provided in CIVL-C code, but is implemented instead in a certain Java class.
|
|---|
| 139 | A system function is declared by adding the function qualifier `$system` to a function prototype.
|
|---|
| 140 | Invocation of a system function always takes place in a single atomic step.
|
|---|
| 141 |
|
|---|
| 142 | A system function may have a guard, which is specified in the function contract using a `$executes_when` clause.
|
|---|
| 143 | Unless constrained by its contract or other qualifiers, a system function may modify the state in an arbitrary way.
|
|---|
| 144 |
|
|---|
| 145 | ### Pure functions: `$pure` {#pure}
|
|---|
| 146 |
|
|---|
| 147 | A system or atomic function may be declared to be `$pure`, e.g.,
|
|---|
| 148 | ```civl
|
|---|
| 149 | $pure $system double sin(double x);
|
|---|
| 150 | $pure $atomic_f double mysin(double x) {
|
|---|
| 151 | return x - x*x*x/6.;
|
|---|
| 152 | }
|
|---|
| 153 | ```
|
|---|
| 154 | This means that the function is a mathematical function of its arguments only.
|
|---|
| 155 | I.e., an invocation of the function has no side-effects and the return value depends on the arguments only.
|
|---|
| 156 | (If called twice with the same arguments, it will return the same value, regardless of any differences in the state).
|
|---|
| 157 | The user is responsible for ensuring that a function declared pure actually is pure.
|
|---|
| 158 | If this is not the case, the model checker may produce incorrect results.
|
|---|
| 159 |
|
|---|
| 160 | ## Expressions {#expressions}
|
|---|
| 161 |
|
|---|
| 162 | ### Boolean expressions, `=>`, `$forall`, `$exists` {#boolean-expressions}
|
|---|
| 163 |
|
|---|
| 164 | CIVL-C provides the boolean constants `$true` and `$false`, which are simply defined as 1 and 0, respectively.
|
|---|
| 165 | CIVL-C is, after all, an extension of C.
|
|---|
| 166 | A program may also include the standard C library header file `stdbool.h`, which defines `true` and `false` in the exact same way.
|
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 | In addition to the standard logical operators `&&`, `|`, and `!`, CIVL-C provides `=>` (implies).
|
|---|
| 170 | `p => q` is equivalent to `!(p) | q` (and has the same short-circuit semantics).
|
|---|
| 171 |
|
|---|
| 172 | A universally quantified formula has the form
|
|---|
| 173 |
|
|---|
| 174 | > `$forall` `(` *variable-decls* (`;` *variable-decls* )\* (`|` *restriction*)? `)` *expr*
|
|---|
| 175 |
|
|---|
| 176 | where
|
|---|
| 177 |
|
|---|
| 178 | * *variable-decls* has one of the forms
|
|---|
| 179 | - *type* *identifier* (`,` *identifier*)\*
|
|---|
| 180 | - `int` *identifier* `:` *range*
|
|---|
| 181 | * *type* is a type name (e.g., `int` or `double`),
|
|---|
| 182 | * *identifier* is the name of a bound variable,
|
|---|
| 183 | * *range* is an expression of `$range` type,
|
|---|
| 184 | * *restriction* is a formula (boolean expression) which expresses some restriction on the values that the bound variable can take, and
|
|---|
| 185 | * *expr* is a formula.
|
|---|
| 186 | The syntax for existential quantification is the same, with `$exists` in place of `$forall`.
|
|---|
| 187 |
|
|---|
| 188 | We will call any assignment of values to the bound variables of a quantified expression a "candidate assignment" if it satisfies *restriction* and each bound variable with an associated *range* is given a value contained in this *range*. The universally quantified formula holds iff *expr* holds under all candidate assignments. Similarly, the existentially quantified formula holds iff there exists a candidate assignment for which *expr* holds.
|
|---|
| 189 |
|
|---|
| 190 | Examples:
|
|---|
| 191 | ```civl
|
|---|
| 192 | int a[3], b[3][2];
|
|---|
| 193 | int main() {
|
|---|
| 194 | int n=3, m=2;
|
|---|
| 195 | $assert($forall (int i | 0<=i && i<n) a[i]==0); // all elements of a are 0
|
|---|
| 196 | $assert($forall (int i: 0..n-1) a[i]==0); // same as above
|
|---|
| 197 | $assert($forall (int i: 0..n-1 | i%2==0) a[i]==0); // even elements are 0
|
|---|
| 198 | $assert($forall (int i: 0..n-1#2) a[i]==0); // same as above
|
|---|
| 199 | $assert($forall (int i: 0..n-1; int j: 0..m-1) b[i][j]==0); // all elements of b are 0
|
|---|
| 200 | $assert($forall (int i: 0..n-1; int j | 0<=j && j<m) b[i][j]==0); // same
|
|---|
| 201 | $assert($forall (int i: 0..n-1; int j: 0..m-1 | i<j ) b[i][j]==0); // lower triangle is 0
|
|---|
| 202 | $assert($forall (int i,j | 0<=i && i<n && 0<=j && j<m) b[i][j]==0); // all elements of b are 0
|
|---|
| 203 | $assert($exists (int i | 0<=i && i<n) a[i]==0); // existential: some element of a is 0
|
|---|
| 204 | $assert($forall (int i: 0..n-1) $exists (int j: 0..i) a[j]<=a[i]); // nested quantification
|
|---|
| 205 | }
|
|---|
| 206 | ```
|
|---|
| 207 |
|
|---|
| 208 | ### Domain literals {#domain-literals}
|
|---|
| 209 |
|
|---|
| 210 | An expression of the form
|
|---|
| 211 |
|
|---|
| 212 | > `(` `$domain` `)` `{` $r_{1}$ `,` ... `,` $r_{n}$ `}`
|
|---|
| 213 |
|
|---|
| 214 | where $r_{1}$, ..., $r_{n}$ are *n* expressions of type `$range`, is a *Cartesian domain expression*.
|
|---|
| 215 | It represents the domain of dimension *n* which is the Cartesian product of the *n* ranges,
|
|---|
| 216 | i.e., it consists of all *n*-tuples ($x_{1}$, ..., $x_{n}$) where $x_{1} \in r_{1}$, ..., $x_{n} \in r_{n}$.
|
|---|
| 217 | The order on the domain is the dictionary order on tuples.
|
|---|
| 218 | The type of this expression is `$domain(n)`.
|
|---|
| 219 | When a Cartesian domain expression is used to initialize an object of domain type, the `($domain)` may be omitted.
|
|---|
| 220 | For example:
|
|---|
| 221 | ```civl
|
|---|
| 222 | $domain(3) dom = { 0..3, r2, 10..2#-2 };
|
|---|
| 223 | ```
|
|---|
| 224 |
|
|---|
| 225 | ### This scope: the `$here` scope expression {#here}
|
|---|
| 226 | Expression of type `$scope`, evaluating to the dynamic scope in which the evaluation takes place.
|
|---|
| 227 |
|
|---|
| 228 | ### The null process reference: `$proc_null` {#proc_null}
|
|---|
| 229 | The null process constant.
|
|---|
| 230 | Similar to the NULL pointer, this gives an object of `$proc` type a defined value, and can be used in `==` and `!=` expressions.
|
|---|
| 231 | It cannot be used as the argument to `$wait` or `$waitall`.
|
|---|
| 232 |
|
|---|
| 233 | ### The root scope constant: `$root` {#root}
|
|---|
| 234 | Constant of type `$scope`, the root dynamic scope.
|
|---|
| 235 |
|
|---|
| 236 | ### Range literals: *a*`..`*b* and *a*`..`*b*`#`*c* {#range-literals}
|
|---|
| 237 |
|
|---|
| 238 | A range literal has the form
|
|---|
| 239 |
|
|---|
| 240 | > *expr* `..` *expr* ( `#` *expr* )?
|
|---|
| 241 |
|
|---|
| 242 | The two or three sub-expressions (the third is optional) have integer type and the type of the entire expression is `$range`.
|
|---|
| 243 |
|
|---|
| 244 | The range literal *a*`..`*b* represents the range consisting of the integers *a*, *a*+1, ..., *b* (in that order).
|
|---|
| 245 |
|
|---|
| 246 | The range literal *a*`..`*b*`#`*c* is interpreted as follows.
|
|---|
| 247 | If *c* is positive, it represents the range consisting of *a*, *a*+*c*, *a*+2*c*, ..., up to and possibly including *b*.
|
|---|
| 248 | To be precise, the infinite sequence is intersected with the set of integers less than or equal to *b*.
|
|---|
| 249 | If *c* is negative, the expression represents the range consisting of *b*, *b*+*c*, *b*+2*c*, ..., down to and possibly including *a*.
|
|---|
| 250 | Precisely, the infinite sequence is intersected with the set of integers greater than or equal to *a*.
|
|---|
| 251 |
|
|---|
| 252 | ### The scope of an expression: `$scopeof` {#scopeof}
|
|---|
| 253 |
|
|---|
| 254 | The syntax is
|
|---|
| 255 |
|
|---|
| 256 | > `$scopeof` `(` *expr* `)`
|
|---|
| 257 |
|
|---|
| 258 | where *expr* is an expression that can occur on the left hand side of an assignment operator (i.e., an lvalue).
|
|---|
| 259 | It evaluates to the dynamic scope containing the object specified by *expr*.
|
|---|
| 260 | The following example illustrates the semantics of the `$scopeof` operator. All of the assertions hold:
|
|---|
| 261 | ```civl
|
|---|
| 262 | {
|
|---|
| 263 | $scope s1 = $here;
|
|---|
| 264 | int x;
|
|---|
| 265 | double a[10];
|
|---|
| 266 | {
|
|---|
| 267 | $scope s2 = $here;
|
|---|
| 268 | int *p = &x;
|
|---|
| 269 | double *q = &a[4];
|
|---|
| 270 | assert($scopeof(x)==s1);
|
|---|
| 271 | assert($scopeof(p)==s2);
|
|---|
| 272 | assert($scopeof(*p)==s1);
|
|---|
| 273 | assert($scopeof(a)==s1);
|
|---|
| 274 | assert($scopeof(a[5])==s1);
|
|---|
| 275 | assert($scopeof(q)==s2);
|
|---|
| 276 | assert($scopeof(*q)==s1);
|
|---|
| 277 | }
|
|---|
| 278 | }
|
|---|
| 279 | ```
|
|---|
| 280 |
|
|---|
| 281 | ### Scope expressions {#scope-expressions}
|
|---|
| 282 |
|
|---|
| 283 | Let $s_{1}$ and $s_{2}$ be expressions of [type $scope](#scope-type). The following are all CIVL-C expressions of boolean type:
|
|---|
| 284 |
|
|---|
| 285 | * $s_{1}$`==`$s_{2}$ holds iff $s_{1}$ and $s_{2}$ refer to the same dynamic scope.
|
|---|
| 286 | * $s_{1}$`!=`$s_{2}$ holds iff $s_{1}$ and $s_{2}$ refer to different dynamic scopes.
|
|---|
| 287 | * $s_{1}$`<=`$s_{2}$ holds iff $s_{1}$ is equal to or a descendant of $s_{2}$, i.e., $s_{1}$ is equal to or contained in $s_{2}$.
|
|---|
| 288 | * $s_{1}$`<`$s_{2}$ holds iff $s_{1}$ is a strict descendant of $s_{2}$, i.e., $s_{1}$ is contained in $s_{2}$ and is not equal to $s_{2}$.
|
|---|
| 289 | * $s_{1}$`>`$s_{2}$ is equivalent to $s_{2}$`<`$s_{1}$.
|
|---|
| 290 | * $s_{1}$`>=`$s_{2}$ is equivalent to $s_{2}$`<=`$s_{1}$.
|
|---|
| 291 |
|
|---|
| 292 | The expression $s_{1}$`+`$s_{2}$ evaluates to the lowest common ancestor of $s_{1}$ and $s_{2}$ in the dynamic scope tree.
|
|---|
| 293 | This is the smallest dynamic scope containing both $s_{1}$ and $s_{2}$.
|
|---|
| 294 |
|
|---|
| 295 | Each of these expressions is erroneous if $s_{1}$ or $s_{2}$ is undefined.
|
|---|
| 296 | This error is reported by the model checker.
|
|---|
| 297 |
|
|---|
| 298 | ### This process: `$self` {#self}
|
|---|
| 299 |
|
|---|
| 300 | This expression of `$proc` type returns a reference to the process which is evaluating this expression.
|
|---|
| 301 | It provides a way for code to obtain the identity of the process executing the code.
|
|---|
| 302 |
|
|---|
| 303 | ### Spawning a new process: `$spawn` {#spawn}
|
|---|
| 304 |
|
|---|
| 305 | A spawn expression is an expression with side-effects.
|
|---|
| 306 | It spawns a new process and returns a reference to the new process, i.e., an object of [type $proc](#proc-type).
|
|---|
| 307 | The syntax is the same as a function call with the keyword `$spawn` inserted in front:
|
|---|
| 308 |
|
|---|
| 309 | > `$spawn` *function-expr* `(` ( *expr* ( `,` expr )\* )? `)`
|
|---|
| 310 |
|
|---|
| 311 | Example:
|
|---|
| 312 | ```civl
|
|---|
| 313 | $spawn f(3.14, x+2*y)
|
|---|
| 314 | ```
|
|---|
| 315 |
|
|---|
| 316 | Typically the returned value is assigned to a variable, e.g.,
|
|---|
| 317 | ```civl
|
|---|
| 318 | $proc p = $spawn f(i);
|
|---|
| 319 | ```
|
|---|
| 320 | If the function `f` returns a value, that value is ignored.
|
|---|
| 321 |
|
|---|
| 322 | ## Statements {#statements}
|
|---|
| 323 |
|
|---|
| 324 | ### Atomic statements: `$atomic` {#atomic}
|
|---|
| 325 |
|
|---|
| 326 | An atomic statement has syntax
|
|---|
| 327 |
|
|---|
| 328 | > `$atomic` *stmt*
|
|---|
| 329 |
|
|---|
| 330 | It indicates that *stmt* should be executed without the intervention of other processes.
|
|---|
| 331 | For example,
|
|---|
| 332 | ```civl
|
|---|
| 333 | $atomic {
|
|---|
| 334 | x=x+1;
|
|---|
| 335 | y=2*x+y;
|
|---|
| 336 | }
|
|---|
| 337 | ```
|
|---|
| 338 | In this example, *stmt* is a compound statement `{` ... `}`. This is usually the case.
|
|---|
| 339 |
|
|---|
| 340 | Semantics: there is a global atomic lock which is initially free.
|
|---|
| 341 | The global atomic lock can be obtained by a process by entering an atomic statement.
|
|---|
| 342 | Whenever the lock is held by some process, all other processes must wait until the atomic lock becomes free to continue execution.
|
|---|
| 343 | The guard of an atomic statement is simply the guard of the first sub-statement of the atomic statement.
|
|---|
| 344 | So, a process may only enter an atomic statement if the lock is free (or if the process already owns the lock) and the guard holds.
|
|---|
| 345 | The process may not necessarily enter the atomic statement as soon as these conditions hold, because some other enabled process may be scheduled first.
|
|---|
| 346 | In fact, some other process may obtain the atomic lock.
|
|---|
| 347 | But if the enabling conditions hold and this process is scheduled, it will obtain the atomic lock and begin executing *stmt* without other processes executing.
|
|---|
| 348 | Upon reaching the end of *stmt*, the process releases the atomic lock and exits *stmt*.
|
|---|
| 349 |
|
|---|
| 350 | There is an exception to atomicity: if the process executing inside the atomic statement calls the [$yield function](#yield), it releases the atomic lock.
|
|---|
| 351 | This allows other processes to execute, and even obtain the lock.
|
|---|
| 352 | At any point at which the atomic lock is free and the first statement following the `$yield` is enabled, the original process may re-obtain
|
|---|
| 353 | the atomic lock and continue executing atomically.
|
|---|
| 354 |
|
|---|
| 355 | If a statement inside an atomic statement blocks, so that the process executing the atomic statement has no enabled statement, execution deadlocks.
|
|---|
| 356 | The exception to this rule is that the first sub-statement in the atomic statement, and the first statement after a `$yield`, as described above,
|
|---|
| 357 | may block, without necessarily causing deadlock.
|
|---|
| 358 |
|
|---|
| 359 | Atomic blocks may be nested.
|
|---|
| 360 | The semantics are as follows.
|
|---|
| 361 | Each process maintains a counter which records the multiplicity with which it owns the atomic lock.
|
|---|
| 362 | These counters are initially 0.
|
|---|
| 363 | When a process acquires the lock, the counter is set to 1.
|
|---|
| 364 | Each time the process attempts to enter an atomic statement when it already owns the lock, it succeeds immediately and the counter is incremented.
|
|---|
| 365 | Each time the process leaves an atomic statement, the counter is decremented.
|
|---|
| 366 | When the counter reaches 0, the lock is released.
|
|---|
| 367 |
|
|---|
| 368 | Execution of a `$yield` does not change the multiplicity counter; the process releases the lock but maintains the multiplicity,
|
|---|
| 369 | so that when the lock is re-obtained, the original multiplicity is still in place.
|
|---|
| 370 |
|
|---|
| 371 | ### Nondeterministic selection statement `$choose` {#choose}
|
|---|
| 372 |
|
|---|
| 373 | A `$choose` statement has the form
|
|---|
| 374 |
|
|---|
| 375 | > `$choose` `{` *stmt*+ ( `default` `:` *stmt* )? `}`
|
|---|
| 376 |
|
|---|
| 377 | For example,
|
|---|
| 378 |
|
|---|
| 379 | ```civl
|
|---|
| 380 | $choose {
|
|---|
| 381 | $when (x<n) x++;
|
|---|
| 382 | $when (s>0) s--;
|
|---|
| 383 | $default: c++;
|
|---|
| 384 | }
|
|---|
| 385 | ```
|
|---|
| 386 | The default clause is optional.
|
|---|
| 387 |
|
|---|
| 388 | The guards of the statements are evaluated and among those that are true, one is chosen non-deterministically and executed.
|
|---|
| 389 | If none are true and the default clause is present, it is chosen.
|
|---|
| 390 | The default clause will only be selected if all guards are false.
|
|---|
| 391 | If no default clause is present and all guards are false, the statement blocks.
|
|---|
| 392 | Hence the implicit guard of the `$choose` statement without a default clause is the disjunction of the guards of its sub-statements.
|
|---|
| 393 | The implicit guard of the `$choose` statement with a default clause is *true*.
|
|---|
| 394 |
|
|---|
| 395 | #### Example
|
|---|
| 396 | This shows how to encode a “low-level” guarded transition system:
|
|---|
| 397 | ```civl
|
|---|
| 398 | l1:
|
|---|
| 399 | $choose {
|
|---|
| 400 | $when (x>0) {x--; goto l2;}
|
|---|
| 401 | $when (x==0) {y=1; goto l3;}
|
|---|
| 402 | default: {z=1; goto l4;}
|
|---|
| 403 | }
|
|---|
| 404 | l2:
|
|---|
| 405 | $choose {
|
|---|
| 406 | ...
|
|---|
| 407 | }
|
|---|
| 408 | l3:
|
|---|
| 409 | $choose {
|
|---|
| 410 | ...
|
|---|
| 411 | }
|
|---|
| 412 | ```
|
|---|
| 413 |
|
|---|
| 414 | ### Domain iteration statement: `$for` {#for}
|
|---|
| 415 |
|
|---|
| 416 | A domain iteration statement has the form
|
|---|
| 417 |
|
|---|
| 418 | > `$for` `(` `int` $i_{1}$ `,` ...`,` $i_{n}$ `:` *dom*`)` *S*
|
|---|
| 419 |
|
|---|
| 420 | where $i_{1}$, ..., $i_{n}$ are *n* identifiers, *dom* is an expression of [type $domain(n)](#domain-type), and *S* is a statement.
|
|---|
| 421 | The identifiers declare *n* variables of integer type.
|
|---|
| 422 | Control iterates over the values of the domain, assigning the integer variables the components of the current tuple in the domain at the start of each iteration.
|
|---|
| 423 | The scope of the variables extends to the end of *S*.
|
|---|
| 424 | The iterations takes place in the order specified by the domain, e.g., dictionary order for a Cartesian domain.
|
|---|
| 425 | Note that if a range expression can be used as *dom* here, it will be automatically converted to a one-dimensional domain.
|
|---|
| 426 | For example,
|
|---|
| 427 | ```civl
|
|---|
| 428 | $for (int i: 0..10) S
|
|---|
| 429 | ```
|
|---|
| 430 | is equivalent to
|
|---|
| 431 | ```civl
|
|---|
| 432 | $for (int i: ($domain(1)){0..10}) S
|
|---|
| 433 | ```
|
|---|
| 434 |
|
|---|
| 435 | There is a also a parallel version of this construct, [$parfor](#parfor).
|
|---|
| 436 |
|
|---|
| 437 | ### Parallel for loop: `$parfor` {#parfor}
|
|---|
| 438 |
|
|---|
| 439 | A parallel for loop statement has the form
|
|---|
| 440 |
|
|---|
| 441 | > `$parfor` `(` `int` $i_{1}$ `,` ...`,` $i_{n}$ `:` *dom*`)` *S*
|
|---|
| 442 |
|
|---|
| 443 | The syntax is exactly the same as that for the sequential [domain iteration statement $for](#for), only with `$parfor` replacing `$for`.
|
|---|
| 444 |
|
|---|
| 445 | The semantics are as follows: when control reaches the loop, one process is spawned for each element of the domain.
|
|---|
| 446 | That process has local variables corresponding to the iteration variables, and those local variables are initialized with the components
|
|---|
| 447 | of the tuple for the element of the domain that process is assigned.
|
|---|
| 448 | Each process executes the statement *S* in this context.
|
|---|
| 449 | Finally, each of these processes is waited on at the end.
|
|---|
| 450 | In particular, there is an effective barrier at the end of the loop, and all the spawned processes disappear after this point.
|
|---|
| 451 |
|
|---|
| 452 | ### Guarded commands: `$when` {#when}
|
|---|
| 453 |
|
|---|
| 454 | A guarded command is encoded in CIVL-C using a `$when` statement:
|
|---|
| 455 |
|
|---|
| 456 | > `$when` `(` *expr* `)` *stmt*
|
|---|
| 457 |
|
|---|
| 458 | Semantics: all CIVL-C statements have a guard, either implicit or explicit, which specifies when the statement is enabled.
|
|---|
| 459 | For most statements (e.g., assignments), the guard is implicitly *true*.
|
|---|
| 460 | The `$when` statement allows one to attach an explicit guard to a statement.
|
|---|
| 461 |
|
|---|
| 462 | At a state in which the guard evaluates to *true*, the statement is enabled, otherwise it is disabled.
|
|---|
| 463 | A disabled statement is blocked—it will not be scheduled for execution.
|
|---|
| 464 | When a `$when` statement is enabled and scheduled for execution, it executes by moving control to *stmt* and executing the first atomic action in *stmt*.
|
|---|
| 465 |
|
|---|
| 466 | If *stmt* itself has a non-trivial guard, the guard of the `$when` statement is the conjunction of *expr* and the guard of *stmt*.
|
|---|
| 467 |
|
|---|
| 468 | The evaluation of *expr* and the first atomic action of *stmt* occur as a single atomic action.
|
|---|
| 469 | There is no guarantee that execution of *stmt* will continue atomically if it contains more than one atomic action, i.e., other processes may be scheduled.
|
|---|
| 470 |
|
|---|
| 471 | #### Example
|
|---|
| 472 |
|
|---|
| 473 | ```civl
|
|---|
| 474 | $when (s>0) s--;
|
|---|
| 475 | ```
|
|---|
| 476 | This will block until `s` is positive and then decrement `s`.
|
|---|
| 477 | The execution of `s--` is guaranteed to take place in an environment in which `s` is positive.
|
|---|
| 478 |
|
|---|
| 479 | #### Example
|
|---|
| 480 |
|
|---|
| 481 | ```civl
|
|---|
| 482 | $when (s>0) { s--; t++; }
|
|---|
| 483 | ```
|
|---|
| 484 | The execution of `s--` must happen when `s>0`, but between `s--` and `t++`, other processes may execute.
|
|---|
| 485 | The curly braces in the code above do not accomplish anything---the code is equivalent to
|
|---|
| 486 | ```civl
|
|---|
| 487 | $when (s>0) s--; t++;
|
|---|
| 488 | ```
|
|---|
| 489 | To make the entire statement atomic, one must use an [$atomic statement](#atomic); see the following example.
|
|---|
| 490 |
|
|---|
| 491 | #### Example
|
|---|
| 492 |
|
|---|
| 493 | The following statements are all equivalent:
|
|---|
| 494 | ```civl
|
|---|
| 495 | $when (s>0) $atomic{ s--; t++; }
|
|---|
| 496 | $atomic{ $when(s>0); s--; t++; }
|
|---|
| 497 | $atomic{ $when(s>0) { s--; t++; } }
|
|---|
| 498 | ```
|
|---|
| 499 | Each of these waits until `s` is positive, then from such a state, decrements `s` and increments `t` without the intervention of other processes.
|
|---|
| 500 |
|
|---|
| 501 | #### Example
|
|---|
| 502 |
|
|---|
| 503 | ```civl
|
|---|
| 504 | $when (s>0) $when (t>0) x=y*t;
|
|---|
| 505 | ```
|
|---|
| 506 | This blocks until both `x` and `t` are positive then executes the assignment in that state.
|
|---|
| 507 | It is equivalent to
|
|---|
| 508 | ```civl
|
|---|
| 509 | $when (s>0 && t>0) x=y*t;
|
|---|
| 510 | ```
|
|---|
| 511 |
|
|---|
| 512 |
|
|---|
| 513 | ## Functions {#functions}
|
|---|
| 514 |
|
|---|
| 515 | ### Assertions: `$assert` {#assert}
|
|---|
| 516 |
|
|---|
| 517 | The system function `$assert` has the signature
|
|---|
| 518 | ```civl
|
|---|
| 519 | $system void $assert(_Bool expr, ...);
|
|---|
| 520 | ```
|
|---|
| 521 | It consumes a boolean expression and any number of optional expressions which are used to construct an error message.
|
|---|
| 522 | Note that CIVL-C boolean expressions have a richer syntax than C expressions, and may include universal or existential quantifiers.
|
|---|
| 523 | During verification, the assertion is checked.
|
|---|
| 524 | If it cannot be proved that it must hold, a violation is reported, and, if additional arguments are present, a specific message is printed.
|
|---|
| 525 | These additional arguments are similar in form to those used in C’s `printf` statement:
|
|---|
| 526 | a format string, followed by some number of arguments which are evaluated and substituted for successive codes in the format string.
|
|---|
| 527 | For example,
|
|---|
| 528 | ```civl
|
|---|
| 529 | $assert(x<=B, "x-coordinate %f exceeds bound %f", x, B);
|
|---|
| 530 | ```
|
|---|
| 531 | If x=3 and B=2, the assertion is violated and CIVL prints the error message “x-coordinate 3 exceeds bound 2”.
|
|---|
| 532 |
|
|---|
| 533 | ### Assumptions: `$assume` {#assume}
|
|---|
| 534 |
|
|---|
| 535 | The system function `$assume` has signature
|
|---|
| 536 | ```civl
|
|---|
| 537 | $system void $assume(_Bool expr);
|
|---|
| 538 | ```
|
|---|
| 539 | During verification, the given expression is assumed to hold. If this leads to a contradiction on some execution, that execution is simply ignored.
|
|---|
| 540 | It never reports a violation, it only restricts the set of possible executions that will be explored by the verification algorithm.
|
|---|
| 541 | Like an assertion call, an assume call can be used any place a statement is expected.
|
|---|
| 542 | In addition, an assume call can be used in file scope to place restrictions on the global variables of the programs.
|
|---|
| 543 | For example,
|
|---|
| 544 | ```civl
|
|---|
| 545 | $input int B, N;
|
|---|
| 546 | $assume(1<=N && N<=B);
|
|---|
| 547 | ```
|
|---|
| 548 | declares `N` and `B` to be integer inputs and restricts consideration to inputs satisfying 1 ≤ `N` ≤ `B`.
|
|---|
| 549 |
|
|---|
| 550 | ### Temporary assumptions: `$assume_push` and `$assume_pop` {#temp-assumptions}
|
|---|
| 551 |
|
|---|
| 552 | These functions have signatures:
|
|---|
| 553 | ```civl
|
|---|
| 554 | $system void $assume_push(_Bool pred);
|
|---|
| 555 | $system void $assume_pop();
|
|---|
| 556 | ```
|
|---|
| 557 | In the concrete semantics, `$assume_push` has the same semantics as `$assume`, and `$assume_pop` is a no-op.
|
|---|
| 558 |
|
|---|
| 559 | In the symbolic semantics, they behave as follows: each process maintains a stack of boolean symbolic expressions known as the temporary assumption stack.
|
|---|
| 560 | At any state, the *effective path condition* is the conjunction of the permanent path condition, and the conjunction,
|
|---|
| 561 | over all processes *p*, of all entries in the temporary assumption stack of *p*.
|
|---|
| 562 | A call to `$assume_push` pushes a new assumption onto the temporary assumption stack of the process making the call.
|
|---|
| 563 | A call to `$assume_pop` pops the stack of that process.
|
|---|
| 564 | This allows prior assumptions to be removed.
|
|---|
| 565 | This mechanism is consistent with the concrete semantics in that it yields an over-approximation of the set of reachable concrete states.
|
|---|
| 566 | Specifically, removing a clause from the effective path condition can only increase the set of concrete states represented by a symbolic state.
|
|---|
| 567 | This mechanism serves as a "widening operator" (in the sense of abstract interpretation), which enables symbolic execution to converge.
|
|---|
| 568 |
|
|---|
| 569 | ### Nondeterministic choice of integer: `$choose_int` {#choose_int}
|
|---|
| 570 |
|
|---|
| 571 | This function has signature
|
|---|
| 572 | ```civl
|
|---|
| 573 | $system int $choose_int(int n);
|
|---|
| 574 | ```
|
|---|
| 575 | and returns an arbitrary integer in $[0, n - 1]$. In verification mode, all possible choices are enumerated and explored. Note that $n$ is not required to be concrete. However, if it is not concrete CIVL may run forever in this case.
|
|---|
| 576 |
|
|---|
| 577 | ### Initialization by default value: `$default_value` {#default_value}
|
|---|
| 578 |
|
|---|
| 579 | Assigns an object the default value of its type. Signature:
|
|---|
| 580 | ```civl
|
|---|
| 581 | $system void $default_value(void *ptr);
|
|---|
| 582 | ```
|
|---|
| 583 | Assigns the default value to the object pointed to by `ptr`.
|
|---|
| 584 | The default value is determined under the assumption that the object has static storage duration.
|
|---|
| 585 | These default values are specified by the C standard for C types.
|
|---|
| 586 | For example, 0 is the default value for a numeric type.
|
|---|
| 587 |
|
|---|
| 588 | ### Explicit elaboration of a domain: `$elaborate_domain` {#elaborate_domain}
|
|---|
| 589 |
|
|---|
| 590 | Forces explicit enumeration of the elements of a finite [domain](#domain-type). Signature
|
|---|
| 591 | ```civl
|
|---|
| 592 | $system void $elaborate_domain($domain d);
|
|---|
| 593 | ```
|
|---|
| 594 | In the concrete semantics, this is a no-op.
|
|---|
| 595 |
|
|---|
| 596 | ### Process exit: `$exit` {#exit}
|
|---|
| 597 |
|
|---|
| 598 | Terminates the calling process. Signature:
|
|---|
| 599 | ```civl
|
|---|
| 600 | $system void $exit(void);
|
|---|
| 601 | ```
|
|---|
| 602 |
|
|---|
| 603 | ### Assignment of arbitrary value: `$havoc` {#havoc}
|
|---|
| 604 |
|
|---|
| 605 | Assigns an arbitrary value of the object's type to an object. Signature:
|
|---|
| 606 | ```civl
|
|---|
| 607 | $system void $havoc(void *ptr);
|
|---|
| 608 | ```
|
|---|
| 609 | In the concrete semantics, this function assigns an arbitrary value of the appropriate type to the object pointed to by `ptr`.
|
|---|
| 610 |
|
|---|
| 611 | In the symbolic semantics, this function assigns a fresh symbolic constant of the appropriate type to the object pointed to by `ptr`.
|
|---|
| 612 |
|
|---|
| 613 | ### Hiding pointers: `$hide`, `$reveal`, and `$hidden` (*experimental*) {#hide-reveal-hidden}
|
|---|
| 614 |
|
|---|
| 615 | The partial order reduction algorithm used by the CIVL Model Checker computes the set of memory locations that a process *p* can reach.
|
|---|
| 616 | This is an analysis performed at a state.
|
|---|
| 617 | The starting point of this analysis is the set of variables in the dynamic scopes referenced from *p* 's call stack, and the ancestors of those dyscopes.
|
|---|
| 618 | There is an edge from one object to another if the first contains a pointer into the second. All objects reachable from the initial objects in this directed
|
|---|
| 619 | graph are the reachable objects of *p*.
|
|---|
| 620 |
|
|---|
| 621 | There are times when one wants to modify this directed graph by ignoring some edge.
|
|---|
| 622 | The purpose of these functions is to provide a way to do this from CIVL-C code.
|
|---|
| 623 | The signatures are:
|
|---|
| 624 | ```civl
|
|---|
| 625 | $abstract void* $hide(const void* ptr);
|
|---|
| 626 | $system void* $reveal(const void* ptr);
|
|---|
| 627 | $system _Bool $hidden(const void* ptr);
|
|---|
| 628 | ```
|
|---|
| 629 | Function `$hide` wraps a pointer object in another object which is opaque to the reachability analyzer, i.e., the analyzer will not look inside
|
|---|
| 630 | this object and therefore will not find the hidden pointer.
|
|---|
| 631 | Nothing can be done with this hidden pointer until it is "revealed", i.e., extracted from the opaque object.
|
|---|
| 632 | The function `$hidden` tells whether its argument is a value returned by `$hide`.
|
|---|
| 633 |
|
|---|
| 634 | !!! note
|
|---|
| 635 |
|
|---|
| 636 | This is an experimental and generally unsound feature meant for developers. Use with caution.
|
|---|
| 637 |
|
|---|
| 638 | ### Checking pointer safety: `$is_derefable` {#is_derefable}
|
|---|
| 639 |
|
|---|
| 640 | This function has signature
|
|---|
| 641 | ```civl
|
|---|
| 642 | $system $state_f _Bool $is_derefable(void * ptr);
|
|---|
| 643 | ```
|
|---|
| 644 | and determines if it is safe to evaluate (read) `*ptr`.
|
|---|
| 645 | This means `ptr` points to a memory location that is capable of and is currently holding a value of type T, where T is the type of `*ptr`.
|
|---|
| 646 |
|
|---|
| 647 | ### Checking process termination: `$is_terminated` {#is_terminated}
|
|---|
| 648 |
|
|---|
| 649 | Signature:
|
|---|
| 650 | ```civl
|
|---|
| 651 | $system _Bool $is_terminated($proc p);
|
|---|
| 652 | ```
|
|---|
| 653 | Determines whether `p` identifies a process that has terminated.
|
|---|
| 654 | If `p` is undefined or `$proc_null`, returns 0.
|
|---|
| 655 |
|
|---|
| 656 | ### Specifying local regions: `$local_start` and `$local_end` {#local}
|
|---|
| 657 |
|
|---|
| 658 | ```civl
|
|---|
| 659 | $system void $local_start();
|
|---|
| 660 | $system void $local_end();
|
|---|
| 661 | ```
|
|---|
| 662 |
|
|---|
| 663 | These primitives constrain the interleaving semantics of a program, similar to [the atomic statement](#atomic).
|
|---|
| 664 | As with `$atomic`, `$local_start` obtains the atomic lock and/or increments the multiplicity;
|
|---|
| 665 | `$local_end` decrements the multiplicity and/or releases the atomic lock.
|
|---|
| 666 | At any state, if there is a process *t* that owns the atomic lock, only *t* is enabled.
|
|---|
| 667 |
|
|---|
| 668 | The difference is as follows: when the atomic lock is free, if there is some process at a `$local_start` statement
|
|---|
| 669 | and the first statement following `$local_start` is enabled,
|
|---|
| 670 | then among such processes, the process with lowest PID is the only enabled process; that process executes `$local_start` and obtains the lock.
|
|---|
| 671 | When *t* invokes `$local_end`, *t* decrements the atomic multiplicity, and if that multiplicity reaches 0, *t* relinquishes the atomic lock.
|
|---|
| 672 | Intuitively, this specifies a block of code to be executed atomically by one process, and also declares that the block should be treated as a local statement,
|
|---|
| 673 | in the sense that it is not necessary to explore all interleavings from the state where the local is enabled.
|
|---|
| 674 |
|
|---|
| 675 | #### Example
|
|---|
| 676 |
|
|---|
| 677 | The following illustrates the difference between local and atomic regions.
|
|---|
| 678 | ```civl
|
|---|
| 679 | int x = 0;
|
|---|
| 680 | void thread(int tid) {
|
|---|
| 681 | $atomic {
|
|---|
| 682 | x = tid;
|
|---|
| 683 | }
|
|---|
| 684 | }
|
|---|
| 685 | int main() {
|
|---|
| 686 | $parfor (int i:1..2) thread(i);
|
|---|
| 687 | $assert(x==2); // violated
|
|---|
| 688 | }
|
|---|
| 689 | ```
|
|---|
| 690 | The program above spawns two "threads", each of which writes to shared variable `x` in an atomic block.
|
|---|
| 691 | The program has two possible executions: in one, thread 1 writes first, then thread 2 writes; in the other, thread 2 writes first, then thread 1 writes.
|
|---|
| 692 | The assertion is violated on the second execution.
|
|---|
| 693 | Running `civl verify` on this code will report a violation.
|
|---|
| 694 |
|
|---|
| 695 | ```civl
|
|---|
| 696 | int x = 0;
|
|---|
| 697 | void thread(int tid) {
|
|---|
| 698 | $local_start();
|
|---|
| 699 | x = tid;
|
|---|
| 700 | $local_end();
|
|---|
| 701 | }
|
|---|
| 702 | int main() {
|
|---|
| 703 | $parfor (int i:1..2) thread(i);
|
|---|
| 704 | $assert(x==2); // valid
|
|---|
| 705 | }
|
|---|
| 706 | ```
|
|---|
| 707 | In this program, the threads write to `x` within a local region.
|
|---|
| 708 | This program has only one execution: first thread 1 executes the complete local region, then thread 2 executes the complete local region.
|
|---|
| 709 | Running `civl verify` on this code yields "all properties hold".
|
|---|
| 710 |
|
|---|
| 711 | #### Example
|
|---|
| 712 |
|
|---|
| 713 | The code
|
|---|
| 714 | ```civl
|
|---|
| 715 | void thread(int tid) {
|
|---|
| 716 | $local_start();
|
|---|
| 717 | ...A...
|
|---|
| 718 | $local_end();
|
|---|
| 719 | $local_start();
|
|---|
| 720 | ...B...
|
|---|
| 721 | $local_end()
|
|---|
| 722 | }
|
|---|
| 723 | int main() {
|
|---|
| 724 | $parfor (int i:1..2) thread(i);
|
|---|
| 725 | }
|
|---|
| 726 | ```
|
|---|
| 727 | also has only one execution.
|
|---|
| 728 | Thread 1 will execute local block A and then release the atomic lock.
|
|---|
| 729 | But at that point, thread 1 will again be the thread of lowest PID at a `$local_start` and therefore will be the only enabled thread.
|
|---|
| 730 | It will execute local block B, and only then will thread 2 execute.
|
|---|
| 731 | The code above is equivalent to
|
|---|
| 732 | ```civl
|
|---|
| 733 | void thread(int tid) {
|
|---|
| 734 | $local_start();
|
|---|
| 735 | ...A...
|
|---|
| 736 | ...B...
|
|---|
| 737 | $local_end()
|
|---|
| 738 | }
|
|---|
| 739 | int main() {
|
|---|
| 740 | $parfor (int i:1..2) thread(i);
|
|---|
| 741 | }
|
|---|
| 742 | ```
|
|---|
| 743 |
|
|---|
| 744 | #### Use of `$yield` within a local region {#local-yield}
|
|---|
| 745 |
|
|---|
| 746 | Local blocks can also be broken up at specified points using function `$yield`.
|
|---|
| 747 | If *t* owns the atomic lock and calls `$yield`, then *t* relinquishes the lock and does not immediately return from the call.
|
|---|
| 748 | When the atomic lock is free, there is no thread at a `$local_start`, a thread *t* is in a `$yield`, and the first statement following the `$yield` is enabled,
|
|---|
| 749 | then *t* may return from the `$yield` call and re-obtain the atomic lock.
|
|---|
| 750 |
|
|---|
| 751 | Note that a thread waiting to return from a `$yield` has no special priority, even if that `$yield` is inside at local region.
|
|---|
| 752 | Only [$local_start](#local) grants a thread a special priority.
|
|---|
| 753 |
|
|---|
| 754 | ### Heap memory allocation: `$malloc` and `$free` {#malloc-free}
|
|---|
| 755 |
|
|---|
| 756 | Allocate and deallocate heap memory. Signatures:
|
|---|
| 757 | ```civl
|
|---|
| 758 | $system void* $malloc($scope s, int size);
|
|---|
| 759 | $system void $free(void *p);
|
|---|
| 760 | ```
|
|---|
| 761 | Each dynamic scope has a heap.
|
|---|
| 762 | Function `$malloc` allocates `size` bytes in the heap of scope `s`.
|
|---|
| 763 | Unlike C's `malloc`, `$malloc` cannot fail.
|
|---|
| 764 | Note that `malloc` is implemented as `$malloc($root, size)`.
|
|---|
| 765 |
|
|---|
| 766 | Function `$free` deallocates the object pointed to by `p`, which should be a pointer that was returned by an earlier call to `$malloc`.
|
|---|
| 767 | An error is generated if the pointer is not one that was returned by `$malloc`, or if it was already freed.
|
|---|
| 768 |
|
|---|
| 769 | ### Print the path condition: `$pathCondition` {#print-path-condition}
|
|---|
| 770 |
|
|---|
| 771 | Prints the current effective path condition.
|
|---|
| 772 | ```civl
|
|---|
| 773 | $system void $pathCondition(void);
|
|---|
| 774 | ```
|
|---|
| 775 |
|
|---|
| 776 | ### Power function: `$pow` {#pow}
|
|---|
| 777 |
|
|---|
| 778 | Computes $x^{y}$.
|
|---|
| 779 | ```civl
|
|---|
| 780 | $system double $pow(double base, double exp);
|
|---|
| 781 | ```
|
|---|
| 782 |
|
|---|
| 783 | ### Waiting for process termination: `$wait` and `$waitall` {#wait}
|
|---|
| 784 |
|
|---|
| 785 | ```civl
|
|---|
| 786 | $system void $wait($proc p);
|
|---|
| 787 | $system void $waitall($proc *procs, int numProcs);
|
|---|
| 788 | ```
|
|---|
| 789 |
|
|---|
| 790 | Calling `$wait(p)` blocks the calling process until process `p` has terminated.
|
|---|
| 791 | Calling `$waitall(procs, n)` blocks the calling process until all processes `procs[0]`, ...,`procs[n-1]` have terminated.
|
|---|
| 792 | All the process arguments must refer to valid processes, i.e., they cannot be undefined or `$proc_null`.
|
|---|
| 793 | It is OK if a process argument refers to a process that has already terminated.
|
|---|
| 794 |
|
|---|
| 795 | ### Yielding atomicity: `$yield` {#yield}
|
|---|
| 796 |
|
|---|
| 797 | ```civl
|
|---|
| 798 | $system void $yield();
|
|---|
| 799 | ```
|
|---|
| 800 |
|
|---|
| 801 | The yield function is used inside an [atomic](#atomic) or [local](#local) region to release the atomic lock so that other processes may execute.
|
|---|
| 802 | The yielding process retains its current atomic lock multiplicity, so that if and when it regains the atomic lock, it proceeds executing
|
|---|
| 803 | with the same multiplicity it had before the yield.
|
|---|
| 804 | In order for the yielding process to return from the call to `$yield`, and thereby regain the atomic lock, the first statement following
|
|---|
| 805 | `$yield` must be enabled.
|
|---|
| 806 | This statement behaves as a guard for regaining the atomic lock, just as the first statement of an atomic block, or the first statement
|
|---|
| 807 | following `$local_start`, acts as a guard for entering an atomic or local region.
|
|---|
| 808 | The yielding process competes with other processes to obtain the lock; it does not have any special priority.
|
|---|
| 809 | In particular, if the lock is available and there is a process at a `$local_start` call (and the first statement following the call is enabled), one such a process is guaranteed to obtain the lock.
|
|---|
| 810 |
|
|---|
| 811 | ## Macros {#macros}
|
|---|
| 812 |
|
|---|
| 813 | ### Elaboration of integer value: `$elaborate` {#elaborate}
|
|---|
| 814 |
|
|---|
| 815 | This is a function-like macro of one argument.
|
|---|
| 816 | The argument should be a side-effect-free expression of integer type.
|
|---|
| 817 | The macro expands to text which, when followed by `;`, yields a statement.
|
|---|
| 818 | The definition is:
|
|---|
| 819 | ```civl
|
|---|
| 820 | #define $elaborate(x) for(int _i = 0; _i < (x); _i++)
|
|---|
| 821 | ```
|
|---|
| 822 | In the concrete semantics, this is no-op.
|
|---|
| 823 | However, in the symbolic semantics, it has the effect of forcing $x$ to take on a concrete value.
|
|---|
| 824 | Let us assume $x \ge 0$ is implied by the path condition.
|
|---|
| 825 | Then, each time the process completes one iteration of this loop, a nondeterministic choice is made to decide $n < x$, where $n$ is the current concrete value of `_i`.
|
|---|
| 826 | If the true branch is taken, then $x > n$ is recorded in the path condition and control moves to the next iteration.
|
|---|
| 827 | If the false branch is taken, then $x = n$ is recorded and control exits the loop with $x$ now assigned a concrete value.
|
|---|
| 828 | Hence this effectively enumerates all possible concrete values of $x$.
|
|---|
| 829 | As long as the path condition implies some concrete upper bound on $x$, this will be a finite enumeration.
|
|---|
| 830 | If there is no such bound, the symbolic state space will be infinite, since the loop can iterate indefinitely.
|
|---|
| 831 |
|
|---|
| 832 | ## Contract Annotations {#contracts}
|
|---|
| 833 |
|
|---|
| 834 | Function contracts can be specified as annotations---formatted comments---preceding a function prototype or definition.
|
|---|
| 835 | The language for these annotations is based on the specification language [ACSL](https://frama-c.com/html/acsl.html) used by Frama-C.
|
|---|
| 836 | A translation unit must include the following pragma to inform CIVL that it should parse the ACSL annotations in that translation unit:
|
|---|
| 837 | ```c
|
|---|
| 838 | #pragma CIVL ACSL
|
|---|
| 839 | ```
|
|---|
| 840 | If this line is not present, the annotations will be ignored.
|
|---|
| 841 |
|
|---|
| 842 | The high-level syntax for a procedure contract is
|
|---|
| 843 |
|
|---|
| 844 | > `/*@` *clause*\* `*/`
|
|---|
| 845 |
|
|---|
| 846 | Optionally, any line after the first line (which begins with `/*@`) in the contract may have `*` as its first non-white-space character;
|
|---|
| 847 | this character is ignored.
|
|---|
| 848 |
|
|---|
| 849 | There are clauses for preconditions, postconditions, and other concepts.
|
|---|
| 850 | These are used in various experimental extensions of CIVL.
|
|---|
| 851 | Here we describe only the clauses which are fully supported and used by the core CIVL model checker.
|
|---|
| 852 |
|
|---|
| 853 | ### Specifying a guard: `executes_when`
|
|---|
| 854 |
|
|---|
| 855 | This clause has syntax
|
|---|
| 856 |
|
|---|
| 857 | > `executes_when` *expr* `;`
|
|---|
| 858 |
|
|---|
| 859 | It may be used with a [system function](#system).
|
|---|
| 860 | (For all other functions, this clause is ignored.)
|
|---|
| 861 | This clause specifies a guard that applies whenever the function is called.
|
|---|
| 862 | The *expr* is an ACSL expression and may use the formal parameters of the function as well as any other variables that are in scope.
|
|---|
| 863 | Whenever control in a process is at a call to the function, the call will be enabled only if the guard evaluates to *true*.
|
|---|
| 864 | To evaluate the guard, the actual arguments used in the call are substituted for the formal parameters in the guard expression.
|
|---|
| 865 |
|
|---|
| 866 | Note that `\true` should be used for the Boolean constant *true* in the ACSL expression. E.g.,
|
|---|
| 867 | ```civl
|
|---|
| 868 | \*@ executes_when \true; */
|
|---|
| 869 | $system void f(int x);
|
|---|
| 870 | ```
|
|---|
| 871 |
|
|---|
| 872 | !!! note
|
|---|
| 873 |
|
|---|
| 874 | if the actual arguments have side-effects, the code is automatically refactored so that the side-effects occur once, before the call.
|
|---|
| 875 | I.e., the call
|
|---|
| 876 |
|
|---|
| 877 | > *f*`(`*expr1*`,` *expr2*`,` ...`)`
|
|---|
| 878 |
|
|---|
| 879 | is semantically equivalent to
|
|---|
| 880 | > `t1 =` *expr1*`;`
|
|---|
| 881 | >
|
|---|
| 882 | > `t2 =` *expr2*`;`
|
|---|
| 883 | >
|
|---|
| 884 | > ...
|
|---|
| 885 | >
|
|---|
| 886 | > *f*`(t1, t2,` ... `)`
|
|---|
| 887 |
|
|---|
| 888 | Hence the guard may be evaluated any number of times without causing additional side-effects.
|
|---|
| 889 |
|
|---|
| 890 | ### Specifying dependencies: `depends_on` {#depends_on}
|
|---|
| 891 |
|
|---|
| 892 | A depends_on clause may be used with a system or atomic function and has the form
|
|---|
| 893 |
|
|---|
| 894 | > `depends_on` ( `\nothing` | *access-list* ) `;`
|
|---|
| 895 |
|
|---|
| 896 | where *access-list* has the form
|
|---|
| 897 | > `\access` `(` *expr* ( `,` *expr* )\* `)`
|
|---|
| 898 |
|
|---|
| 899 | Each expression in the access list shall have a pointer type.
|
|---|
| 900 |
|
|---|
| 901 | The clause specifies the dependency relation for the system or atomic function.
|
|---|
| 902 | This dependency information is used by the model checker's partial order reduction algorithm to restrict the interleavings explored.
|
|---|
| 903 |
|
|---|
| 904 | The precise semantics: for a process that is at a state from which a call to the function is enabled:
|
|---|
| 905 | any transition from another process that does not access any object pointed to by an expression in the access list
|
|---|
| 906 | will be independent of the function call.
|
|---|
| 907 |
|
|---|
| 908 | (Two transitions are independent if, from any state in which both are enabled, neither can disable the other, and the two transitions commute,
|
|---|
| 909 | i.e., executing the fist and then the second results in the same state as executing the second and then the first.)
|
|---|
| 910 |
|
|---|
| 911 | This clause should be used with care: it is possible to specify a depends-on clause which is not sound, i.e.,
|
|---|
| 912 | the clause may declare that two transitions are independent when they are not.
|
|---|
| 913 | In this case, the model checker may skip some interleaving on which a violation occurs, and report that a program is correct when it is not.
|
|---|
| 914 | This mechanism is intended for use by expert library developers.
|
|---|