List proofs and signoff (#194)
parent
6d35a38bdd
commit
669084ee8f
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIST_H
|
||||
#define LIST_H
|
||||
|
||||
#define VERIFAST
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
//@#include "common.gh"
|
||||
|
||||
typedef size_t TickType_t;
|
||||
typedef size_t UBaseType_t;
|
||||
typedef ssize_t BaseType_t;
|
||||
|
||||
#define pdTRUE 1
|
||||
#define pdFALSE 0
|
||||
|
||||
/* Empty/no-op macros */
|
||||
#define mtCOVERAGE_TEST_MARKER()
|
||||
#define mtCOVERAGE_TEST_DELAY()
|
||||
#define listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList )
|
||||
#define listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList )
|
||||
#define listTEST_LIST_INTEGRITY( pxList )
|
||||
#define listTEST_LIST_ITEM_INTEGRITY( pxListItem )
|
||||
#define listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxListItem )
|
||||
#define listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxListItem )
|
||||
|
||||
/* Max value stored in sentinel xListEnd element */
|
||||
#define portMAX_DELAY UINT_MAX
|
||||
|
||||
struct xLIST;
|
||||
|
||||
struct xLIST_ITEM {
|
||||
TickType_t xItemValue;
|
||||
struct xLIST_ITEM * pxNext;
|
||||
struct xLIST_ITEM * pxPrevious;
|
||||
void * pvOwner;
|
||||
struct xLIST *pxContainer;
|
||||
};
|
||||
typedef struct xLIST_ITEM ListItem_t;
|
||||
|
||||
typedef struct xLIST {
|
||||
UBaseType_t uxNumberOfItems;
|
||||
struct xLIST_ITEM *pxIndex;
|
||||
#ifdef VERIFAST /*< ***change MiniList_t to ListItem_t*** */
|
||||
struct xLIST_ITEM xListEnd;
|
||||
#else
|
||||
MiniListItem_t xListEnd;
|
||||
#endif
|
||||
} List_t;
|
||||
|
||||
/*@
|
||||
predicate xLIST_ITEM(
|
||||
struct xLIST_ITEM *n,
|
||||
TickType_t xItemValue,
|
||||
struct xLIST_ITEM *pxNext,
|
||||
struct xLIST_ITEM *pxPrevious,
|
||||
struct xLIST *pxContainer;) =
|
||||
n->xItemValue |-> xItemValue &*&
|
||||
n->pxNext |-> pxNext &*&
|
||||
n->pxPrevious |-> pxPrevious &*&
|
||||
n->pvOwner |-> _ &*&
|
||||
n->pxContainer |-> pxContainer;
|
||||
@*/
|
||||
|
||||
/* Ferreira et al. (STTT'14) doubly-linked list segment (DLS). */
|
||||
/*@
|
||||
predicate DLS(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *nprev,
|
||||
struct xLIST_ITEM *mnext,
|
||||
struct xLIST_ITEM *m,
|
||||
list<struct xLIST_ITEM * > cells,
|
||||
list<TickType_t > vals,
|
||||
struct xLIST *pxContainer) =
|
||||
n == m
|
||||
? cells == cons(n, nil) &*&
|
||||
vals == cons(?v, nil) &*&
|
||||
xLIST_ITEM(n, v, mnext, nprev, pxContainer)
|
||||
: cells == cons(n, ?cells0) &*&
|
||||
vals == cons(?v, ?vals0) &*&
|
||||
xLIST_ITEM(n, v, ?o, nprev, pxContainer) &*& DLS(o, n, mnext, m, cells0, vals0, pxContainer);
|
||||
|
||||
lemma void dls_star_item(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *m,
|
||||
struct xLIST_ITEM *o)
|
||||
requires DLS(n, ?nprev, ?mnext, m, ?cells, ?vals, ?l) &*& xLIST_ITEM(o, ?v, ?onext, ?oprev, ?l2);
|
||||
ensures DLS(n, nprev, mnext, m, cells, vals, l) &*& xLIST_ITEM(o, v, onext, oprev, l2) &*& mem(o, cells) == false;
|
||||
{
|
||||
open DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
if (n == m) {
|
||||
assert xLIST_ITEM(n, _, _, _, _);
|
||||
open xLIST_ITEM(n, _, _, _, _);
|
||||
open xLIST_ITEM(o, _, _, _, _);
|
||||
assert n != o;
|
||||
close xLIST_ITEM(o, _, _, _, _);
|
||||
close xLIST_ITEM(n, _, _, _, _);
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
}
|
||||
else {
|
||||
assert DLS(?nnext, n, mnext, m, tail(cells), tail(vals), l);
|
||||
dls_star_item(nnext, m, o);
|
||||
open xLIST_ITEM(n, _, _, _, _);
|
||||
open xLIST_ITEM(o, _, _, _, _);
|
||||
assert n != o;
|
||||
close xLIST_ITEM(o, _, _, _, _);
|
||||
close xLIST_ITEM(n, _, _, _, _);
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
}
|
||||
}
|
||||
|
||||
lemma void dls_distinct(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *nprev,
|
||||
struct xLIST_ITEM *mnext,
|
||||
struct xLIST_ITEM *m,
|
||||
list<struct xLIST_ITEM * > cells)
|
||||
requires DLS(n, nprev, mnext, m, cells, ?vals, ?l);
|
||||
ensures DLS(n, nprev, mnext, m, cells, vals, l) &*& distinct(cells) == true;
|
||||
{
|
||||
if (n == m) {
|
||||
open DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
} else {
|
||||
open DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
assert DLS(?nnext, n, mnext, m, tail(cells), tail(vals), l);
|
||||
dls_distinct(nnext, n, mnext, m, tail(cells));
|
||||
dls_star_item(nnext, m, n);
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
}
|
||||
}
|
||||
|
||||
predicate xLIST(
|
||||
struct xLIST *l,
|
||||
int uxNumberOfItems,
|
||||
struct xLIST_ITEM *pxIndex,
|
||||
struct xLIST_ITEM *xListEnd,
|
||||
list<struct xLIST_ITEM *>cells,
|
||||
list<TickType_t >vals) =
|
||||
l->uxNumberOfItems |-> uxNumberOfItems &*&
|
||||
l->pxIndex |-> pxIndex &*&
|
||||
mem(pxIndex, cells) == true &*&
|
||||
xListEnd == &(l->xListEnd) &*&
|
||||
xListEnd == head(cells) &*&
|
||||
portMAX_DELAY == head(vals) &*&
|
||||
struct_xLIST_ITEM_padding(&l->xListEnd) &*&
|
||||
length(cells) == length(vals) &*&
|
||||
uxNumberOfItems + 1 == length(cells) &*&
|
||||
DLS(xListEnd, ?endprev, xListEnd, endprev, cells, vals, l);
|
||||
|
||||
lemma void xLIST_distinct_cells(struct xLIST *l)
|
||||
requires xLIST(l, ?n, ?idx, ?end, ?cells, ?vals);
|
||||
ensures xLIST(l, n, idx, end, cells, vals) &*& distinct(cells) == true;
|
||||
{
|
||||
open xLIST(l, n, idx, end, cells, vals);
|
||||
assert DLS(end, ?endprev, end, _, cells, vals, l);
|
||||
dls_distinct(end, endprev, end, endprev, cells);
|
||||
close xLIST(l, n, idx, end, cells, vals);
|
||||
}
|
||||
|
||||
lemma void xLIST_star_item(struct xLIST *l, struct xLIST_ITEM *x)
|
||||
requires xLIST(l, ?n, ?idx, ?end, ?cells, ?vals) &*& xLIST_ITEM(x, ?v, ?xnext, ?xprev, ?l2);
|
||||
ensures xLIST(l, n, idx, end, cells, vals) &*& xLIST_ITEM(x, v, xnext, xprev, l2) &*& mem(x, cells) == false;
|
||||
{
|
||||
open xLIST(l, n, idx, end, cells, vals);
|
||||
assert DLS(end, ?endprev, end, _, cells, vals, l);
|
||||
dls_distinct(end, endprev, end, endprev, cells);
|
||||
dls_star_item(end, endprev, x);
|
||||
close xLIST(l, n, idx, end, cells, vals);
|
||||
}
|
||||
|
||||
lemma void dls_first_mem(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *nprev,
|
||||
struct xLIST_ITEM *mnext,
|
||||
struct xLIST_ITEM *m,
|
||||
list<struct xLIST_ITEM * > cells)
|
||||
requires DLS(n, nprev, mnext, m, cells, ?vals, ?l);
|
||||
ensures DLS(n, nprev, mnext, m, cells, vals, l) &*& mem(n, cells) == true &*& index_of(n, cells) == 0;
|
||||
{
|
||||
open DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
if (n == m) {
|
||||
assert cells == cons(n, nil);
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
} else {
|
||||
assert cells == cons(n, ?tail);
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
}
|
||||
}
|
||||
|
||||
lemma void dls_not_empty(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *m,
|
||||
list<struct xLIST_ITEM * > cells,
|
||||
struct xLIST_ITEM *x)
|
||||
requires DLS(n, m, n, m, cells, ?vals, ?l) &*& mem(x, cells) == true &*& x != n;
|
||||
ensures DLS(n, m, n, m, cells, vals, l) &*& n != m;
|
||||
{
|
||||
open DLS(n, m, n, m, cells, vals, l);
|
||||
close DLS(n, m, n, m, cells, vals, l);
|
||||
}
|
||||
|
||||
lemma void dls_last_mem(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *nprev,
|
||||
struct xLIST_ITEM *mnext,
|
||||
struct xLIST_ITEM *m,
|
||||
list<struct xLIST_ITEM * > cells)
|
||||
requires DLS(n, nprev, mnext, m, cells, ?vals, ?l);
|
||||
ensures DLS(n, nprev, mnext, m, cells, vals, l) &*& mem(m, cells) == true &*& index_of(m, cells) == length(cells) - 1;
|
||||
{
|
||||
open DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
if (n == m) {
|
||||
// trivial
|
||||
} else {
|
||||
open xLIST_ITEM(n, _, ?nnext, _, l);
|
||||
assert DLS(?o, n, mnext, m, tail(cells), tail(vals), l);
|
||||
dls_last_mem(o, n, mnext, m, tail(cells));
|
||||
close xLIST_ITEM(n, _, nnext, _, l);
|
||||
}
|
||||
close DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
}
|
||||
|
||||
lemma void split(
|
||||
struct xLIST_ITEM *n,
|
||||
struct xLIST_ITEM *nprev,
|
||||
struct xLIST_ITEM *mnext,
|
||||
struct xLIST_ITEM *m,
|
||||
list<struct xLIST_ITEM * > cells,
|
||||
list<TickType_t > vals,
|
||||
struct xLIST_ITEM *x,
|
||||
int i)
|
||||
requires DLS(n, nprev, mnext, m, cells, vals, ?l) &*& x != n &*& mem(x, cells) == true &*& index_of(x,cells) == i;
|
||||
ensures DLS(n, nprev, x, ?xprev, take(i, cells), take(i, vals), l) &*& DLS(x, xprev, mnext, m, drop(i, cells), drop(i, vals), l) &*& xprev == nth(i-1, cells);
|
||||
{
|
||||
open DLS(n, nprev, mnext, m, cells, vals, l);
|
||||
assert n != m;
|
||||
assert xLIST_ITEM(n, ?v, ?nnext, _, _);
|
||||
assert DLS(nnext, n, mnext, m, tail(cells), tail(vals), l);
|
||||
if (nnext == x) {
|
||||
close DLS(n, nprev, x, n, singleton(n), singleton(v), l);
|
||||
open DLS(x, n, mnext, m, tail(cells), tail(vals), l);
|
||||
open xLIST_ITEM(x, _, ?xnext, ?xprev, l);
|
||||
close xLIST_ITEM(x, _, xnext, xprev, l);
|
||||
close DLS(x, n, mnext, m, tail(cells), tail(vals), l);
|
||||
} else {
|
||||
assert nnext != x;
|
||||
split(nnext, n, mnext, m, tail(cells), tail(vals), x, i - 1);
|
||||
assert DLS(nnext, n, x, ?xprev, take(i-1, tail(cells)), take(i-1, tail(vals)), l);
|
||||
dls_distinct(nnext, n, x, xprev, take(i-1, tail(cells)));
|
||||
dls_star_item(nnext, xprev, n);
|
||||
dls_last_mem(nnext, n, x, xprev, take(i-1, tail(cells)));
|
||||
assert n != xprev;
|
||||
close DLS(n, nprev, x, xprev, take(i, cells), take(i, vals), l);
|
||||
}
|
||||
}
|
||||
|
||||
lemma void join(
|
||||
struct xLIST_ITEM *n1,
|
||||
struct xLIST_ITEM *nprev1,
|
||||
struct xLIST_ITEM *mnext1,
|
||||
struct xLIST_ITEM *m1,
|
||||
list<struct xLIST_ITEM * > cells1,
|
||||
list<TickType_t > vals1,
|
||||
struct xLIST_ITEM *n2,
|
||||
struct xLIST_ITEM *nprev2,
|
||||
struct xLIST_ITEM *mnext2,
|
||||
struct xLIST_ITEM *m2,
|
||||
list<struct xLIST_ITEM * > cells2,
|
||||
list<TickType_t > vals2)
|
||||
requires
|
||||
DLS(n1, nprev1, mnext1, m1, cells1, vals1, ?l) &*&
|
||||
DLS(n2, nprev2, mnext2, m2, cells2, vals2, l) &*&
|
||||
mnext1 == n2 &*& m1 == nprev2;
|
||||
ensures DLS(n1, nprev1, mnext2, m2, append(cells1, cells2), append(vals1, vals2), l);
|
||||
{
|
||||
if (n1 == m1) {
|
||||
dls_first_mem(n1, nprev1, mnext1, m1, cells1);
|
||||
dls_last_mem(n2, nprev2, mnext2, m2, cells2);
|
||||
open DLS(n1, nprev1, mnext1, m1, cells1, vals1, l);
|
||||
dls_star_item(n2, m2, n1);
|
||||
close DLS(n1, nprev1, mnext2, m2, append(singleton(n1), cells2), append(vals1, vals2), l);
|
||||
} else {
|
||||
open DLS(n1, nprev1, mnext1, m1, cells1, vals1, l);
|
||||
assert DLS(?o, n1, mnext1, m1, ?cells1_tail, ?vals1_tail, l);
|
||||
join(o, n1, mnext1, m1, cells1_tail, vals1_tail,
|
||||
n2, nprev2, mnext2, m2, cells2, vals2);
|
||||
assert DLS(o, n1, mnext2, m2, append(cells1_tail, cells2), append(vals1_tail, vals2), l);
|
||||
dls_last_mem(o, n1, mnext2, m2, append(cells1_tail, cells2));
|
||||
dls_star_item(o, m2, n1);
|
||||
close DLS(n1, nprev1, mnext2, m2, append(cells1, cells2), append(vals1, vals2), l);
|
||||
}
|
||||
}
|
||||
|
||||
lemma void idx_remains_in_list<t>(
|
||||
list<t> cells,
|
||||
t idx,
|
||||
t x,
|
||||
int ix)
|
||||
requires
|
||||
idx != x &*&
|
||||
mem(idx, cells) == true &*&
|
||||
mem(x, cells) == true &*&
|
||||
index_of(x, cells) == ix;
|
||||
ensures mem(idx, remove_nth(ix, cells)) == true;
|
||||
{
|
||||
neq_mem_remove(idx, x, cells);
|
||||
remove_remove_nth(cells, x);
|
||||
}
|
||||
@*/
|
||||
|
||||
/* Following lemma from `verifast/examples/shared_boxes/concurrentqueue.c`.
|
||||
Used in the uxListRemove proof to show that the item to remove `x` must
|
||||
have value `nth(i, vals)` where `i == index_of(x, cells)`. */
|
||||
/*@
|
||||
lemma void drop_nth_index_of<t>(list<t> vs, int i)
|
||||
requires
|
||||
0 <= i && i < length(vs);
|
||||
ensures
|
||||
head(drop(i , vs)) == nth(i, vs);
|
||||
{
|
||||
switch(vs) {
|
||||
case nil:
|
||||
case cons(h, t):
|
||||
if (i == 0) {
|
||||
// trivial
|
||||
} else {
|
||||
drop_nth_index_of(t, i - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@*/
|
||||
|
||||
/*@
|
||||
lemma void remove_append<t>(t x, list<t> l1, list<t> l2)
|
||||
requires mem(x, l1) == false;
|
||||
ensures remove(x, append(l1, l2)) == append(l1, remove(x, l2));
|
||||
{
|
||||
switch(l1) {
|
||||
case nil:
|
||||
case cons(h1, t1):
|
||||
remove_append(x, t1, l2);
|
||||
}
|
||||
}
|
||||
@*/
|
||||
|
||||
#endif /* LIST_H */
|
@ -0,0 +1,69 @@
|
||||
# FreeRTOS list proofs
|
||||
|
||||
The list predicates and proofs are inspired by and based on the work from
|
||||
Ferreira et al. (STTT'14).
|
||||
|
||||
The main shape predicate is a doubly-linked list segment (DLS), as defined
|
||||
by Ferreira et al. in Fig 15. A DLS is defined by two `xLIST_ITEM` struct
|
||||
pointers `n` and `m` (possibly pointing to the same item) which are the start
|
||||
and end of the segment. We track the item pointers and values within the DLS in
|
||||
the lists `cells` and `vals`, respectively. Therefore `n` and `m` are the first
|
||||
and last items of `cells`.
|
||||
|
||||
```
|
||||
+--+ +--+
|
||||
-----n-> |*n| ... |*m| -mnext->
|
||||
<-nprev- | | | | <-m-----
|
||||
+--+ +--+
|
||||
^-----------^
|
||||
DLS(n, nprev, mnext, m)
|
||||
```
|
||||
|
||||
With base case: `n == m` (single item case)
|
||||
|
||||
```
|
||||
+--+
|
||||
-----n-> |*n| -mnext->
|
||||
<-nprev- | | <-n-----
|
||||
+--+
|
||||
^--^
|
||||
xLIST_ITEM
|
||||
DLS(n, nprev, mnext, n)
|
||||
```
|
||||
|
||||
Cons case:
|
||||
|
||||
```
|
||||
+--+ +--+ +--+
|
||||
-----n-> |*n| -o-> |*o| ... |*m| -mnext->
|
||||
<-nprev- | | <-n- | | | | <-m-----
|
||||
+--+ +--+ +--+
|
||||
^--^ ^-----------^
|
||||
xLIST_ITEM DLS(o, n, mnext, m)
|
||||
|
||||
^---------------------^
|
||||
DLS(n, nprev, mnext, m)
|
||||
```
|
||||
|
||||
A DLS can be made into a well-formed list by joining `n` and `m` into a cycle.
|
||||
Note that unlike Ferreira et al.'s list shape predicate, we always start with
|
||||
the sentinel end item to avoid a top-level case-split. So in the following
|
||||
diagram the start and end of the DLS are `end` and the item-before-end
|
||||
`endprev`.
|
||||
|
||||
```
|
||||
.-----------------------------------.
|
||||
| +--------+ +--------+ |
|
||||
`--> |*end | ... |*endprev| ----'
|
||||
.---- | | | | <---.
|
||||
| +--------+ +--------+ |
|
||||
`----------------------------------'
|
||||
^-----------------------^
|
||||
DLS(end, endprev, end, endprev)
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- Automated Verification of the FreeRTOS Scheduler in HIP/SLEEK\
|
||||
João F. Ferreira, Cristian Gherghina, Guanhua He, Shengchao Qin, Wei-Ngan Chin\
|
||||
https://joaoff.com/publication/2014/sttt/
|
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "proof/list.h"
|
||||
|
||||
/* Wrap the macro in a function call so we can give a function contract */
|
||||
#define listLIST_IS_EMPTY( pxList ) ( ( ( pxList )->uxNumberOfItems == ( UBaseType_t ) 0 ) ? pdTRUE : pdFALSE )
|
||||
|
||||
BaseType_t wrapper_listLIST_IS_EMPTY( List_t * pxList )
|
||||
/*@requires xLIST(pxList, ?len, ?idx, ?end, ?cells, ?vals);@*/
|
||||
/*@ensures xLIST(pxList, len, idx, end, cells, vals) &*&
|
||||
result == ((len == 0) ? pdTRUE : pdFALSE); @*/
|
||||
{
|
||||
/*@open xLIST(pxList, len, _, _, _, _);@*/
|
||||
return listLIST_IS_EMPTY( pxList );
|
||||
/*@close xLIST(pxList, len, _, _, cells, vals);@*/
|
||||
}
|
@ -0,0 +1,306 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "proof/list.h"
|
||||
|
||||
UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
|
||||
/*@requires
|
||||
exists<struct xLIST * >(?l) &*&
|
||||
xLIST(l, ?len, ?idx, ?end, ?cells, ?vals) &*&
|
||||
end != pxItemToRemove &*&
|
||||
mem(pxItemToRemove, cells) == true;@*/
|
||||
/*@ensures
|
||||
result == len-1 &*&
|
||||
xLIST_ITEM(pxItemToRemove, nth(index_of(pxItemToRemove, cells), vals), _, ?pxItemToRemovePrevious, NULL) &*&
|
||||
pxItemToRemovePrevious == nth(index_of(pxItemToRemove, cells)-1, cells) &*&
|
||||
xLIST(l, result, idx == pxItemToRemove ? pxItemToRemovePrevious : idx, end, remove(pxItemToRemove, cells), remove_nth(index_of(pxItemToRemove, cells), vals));@*/
|
||||
{
|
||||
/* For brevity we alias x to pxItemToRemove */
|
||||
/*@struct xLIST_ITEM *x = pxItemToRemove;@*/
|
||||
|
||||
/* Start by establishing that the list must be non-empty since x != end */
|
||||
/*@open xLIST(l, len, idx, end, cells, vals);@*/
|
||||
/*@assert DLS(end, ?endprev, end, _, cells, vals, l);@*/
|
||||
/*@assert vals == cons(portMAX_DELAY, _);@*/
|
||||
/*@dls_not_empty(end, endprev, cells, x);@*/
|
||||
|
||||
/* We know the xLIST is a DLS: end...endprev
|
||||
Split this into DLS1:end...xprev and DLS2:x...endprev */
|
||||
/*@int i = index_of(x, cells);@*/
|
||||
/*@split(end, endprev, end, endprev, cells, vals, x, i);@*/
|
||||
/*@list<struct xLIST_ITEM *> ys = take(i, cells);@*/
|
||||
/*@list<struct xLIST_ITEM *> zs = drop(i, cells);@*/
|
||||
/*@list<TickType_t> vs = take(i, vals);@*/
|
||||
/*@list<TickType_t> ws = drop(i, vals);@*/
|
||||
/*@assert length(ys) == length(vs);@*/
|
||||
/*@assert length(zs) == length(ws);@*/
|
||||
/*@assert DLS(end, endprev, x, ?xprev, ys, vs, l);@*/ /*< DLS1 (ys, vs) */
|
||||
/*@assert DLS(x, xprev, end, endprev, zs, ws, l);@*/ /*< DLS2 (zs, ws) */
|
||||
|
||||
/* Now case split to open DLS1 and DLS2 appropriately */
|
||||
/*@
|
||||
if (end == xprev)
|
||||
{
|
||||
if (x == endprev)
|
||||
{
|
||||
//Case A
|
||||
//DLS1: extract end=prev=next
|
||||
open DLS(end, endprev, x, xprev, ys, vs, l);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, x, endprev, l);
|
||||
//DLS2: extract x
|
||||
open DLS(x, xprev, end, endprev, zs, ws, l);
|
||||
//Lengths
|
||||
assert length(ys) == 1;
|
||||
assert length(zs) == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Case B
|
||||
//DLS1: extract end=prev
|
||||
open DLS(end, endprev, x, xprev, ys, vs, l);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, x, endprev, l);
|
||||
//DLS2: extract next and x
|
||||
open DLS(x, end, end, endprev, zs, ws, l);
|
||||
assert DLS(?xnext, x, end, endprev, tail(zs), tail(ws), l);
|
||||
open DLS(xnext, x, end, endprev, tail(zs), tail(ws), l);
|
||||
open xLIST_ITEM(xnext, _, _, x, l);
|
||||
//Lengths
|
||||
assert length(ys) == 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x == endprev)
|
||||
{
|
||||
//Case C
|
||||
//DLS1: extract end=next and prev
|
||||
dls_last_mem(end, endprev, x, xprev, ys);
|
||||
assert mem(xprev, ys) == true;
|
||||
open DLS(end, endprev, x, xprev, ys, vs, l);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, ?endnext, endprev, l);
|
||||
if (endnext == xprev)
|
||||
{
|
||||
open DLS(endnext, end, x, xprev, tail(ys), tail(vs), l);
|
||||
open xLIST_ITEM(xprev, _, x, _, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(endnext, end, x, xprev, tail(ys), tail(vs), l);
|
||||
int k = index_of(xprev, tail(ys));
|
||||
dls_last_mem(endnext, end, x, xprev, tail(ys));
|
||||
split(endnext, end, x, xprev, tail(ys), tail(vs), xprev, k);
|
||||
open DLS(xprev, _, x, xprev, _, _, l);
|
||||
open xLIST_ITEM(xprev, _, x, _, l);
|
||||
}
|
||||
//DLS2: extract x
|
||||
open DLS(x, xprev, end, endprev, zs, ws, l);
|
||||
//Lengths
|
||||
assert length(zs) == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Case D
|
||||
//DLS1: extract prev
|
||||
dls_last_mem(end, endprev, x, xprev, ys);
|
||||
int j = index_of(xprev, ys);
|
||||
open DLS(end, endprev, x, xprev, ys, vs, l);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, ?endnext, endprev, l);
|
||||
if (endnext == xprev)
|
||||
{
|
||||
open DLS(endnext, end, x, xprev, tail(ys), tail(vs), l);
|
||||
assert tail(ys) == singleton(xprev);
|
||||
open xLIST_ITEM(xprev, _, x, _, l);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(endnext, end, x, xprev, tail(ys), tail(vs), l);
|
||||
int k = index_of(xprev, tail(ys));
|
||||
dls_last_mem(endnext, end, x, xprev, tail(ys));
|
||||
split(endnext, end, x, xprev, tail(ys), tail(vs), xprev, k);
|
||||
open DLS(xprev, _, x, xprev, _, _, l);
|
||||
open xLIST_ITEM(xprev, _, x, _, l);
|
||||
}
|
||||
//DLS2: extract next and x
|
||||
open DLS(x, xprev, end, endprev, zs, ws, l);
|
||||
assert xLIST_ITEM(x, _, ?xnext, _, l);
|
||||
open DLS(xnext, x, end, endprev, tail(zs), tail(ws), l);
|
||||
open xLIST_ITEM(xnext, _, _, x, l);
|
||||
}
|
||||
}
|
||||
@*/
|
||||
/*@drop_nth_index_of(vals, i);@*/
|
||||
/*@open xLIST_ITEM(x, nth(i, vals), ?xnext, xprev, l);@*/
|
||||
|
||||
/* The list item knows which list it is in. Obtain the list from the list
|
||||
* item. */
|
||||
#ifdef VERIFAST /*< const pointer declaration */
|
||||
List_t * pxList = pxItemToRemove->pxContainer;
|
||||
#else
|
||||
List_t * const pxList = pxItemToRemove->pxContainer;
|
||||
#endif
|
||||
|
||||
pxItemToRemove->pxNext->pxPrevious = pxItemToRemove->pxPrevious;
|
||||
pxItemToRemove->pxPrevious->pxNext = pxItemToRemove->pxNext;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
/* Make sure the index is left pointing to a valid item. */
|
||||
if( pxList->pxIndex == pxItemToRemove )
|
||||
{
|
||||
pxList->pxIndex = pxItemToRemove->pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
mtCOVERAGE_TEST_MARKER();
|
||||
}
|
||||
|
||||
pxItemToRemove->pxContainer = NULL;
|
||||
( pxList->uxNumberOfItems )--;
|
||||
|
||||
return pxList->uxNumberOfItems;
|
||||
|
||||
/*@
|
||||
// Reassemble DLS1 and a modified DLS2, which no longer includes x
|
||||
if (end == xprev)
|
||||
{
|
||||
if (x == endprev)
|
||||
{
|
||||
//Case A
|
||||
close xLIST_ITEM(end, portMAX_DELAY, _, _, _);
|
||||
close DLS(end, end, end, end, singleton(end), singleton(portMAX_DELAY), l);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Case B
|
||||
close xLIST_ITEM(xprev, _, xnext, endprev, l);
|
||||
close DLS(end, endprev, xnext, xprev, singleton(end), singleton(portMAX_DELAY), l);
|
||||
close xLIST_ITEM(xnext, _, _, xprev, l);
|
||||
close DLS(xnext, xprev, end, endprev, tail(zs), tail(ws), l);
|
||||
join(end, endprev, xnext, xprev, singleton(end), singleton(portMAX_DELAY),
|
||||
xnext, xprev, end, endprev, tail(zs), tail(ws));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (x == endprev)
|
||||
{
|
||||
//Case C
|
||||
close xLIST_ITEM(end, _, ?endnext, xprev, l);
|
||||
close xLIST_ITEM(xprev, ?xprev_val, end, _, l);
|
||||
if (endnext == xprev)
|
||||
{
|
||||
close DLS(xprev, end, end, xprev, singleton(xprev), singleton(xprev_val), l);
|
||||
close DLS(end, xprev, end, xprev, cons(end, singleton(xprev)), cons(portMAX_DELAY, singleton(xprev_val)), l);
|
||||
}
|
||||
else
|
||||
{
|
||||
close DLS(xprev, ?xprevprev, xnext, xprev, singleton(xprev), singleton(xprev_val), l);
|
||||
assert DLS(endnext, end, xprev, xprevprev, ?cells_endnext_to_xprevprev, ?vals_endnext_to_xprevprev, l);
|
||||
join(endnext, end, xprev, xprevprev, cells_endnext_to_xprevprev, vals_endnext_to_xprevprev,
|
||||
xprev, xprevprev, xnext, xprev, singleton(xprev), singleton(xprev_val));
|
||||
close DLS(end, xprev, end, xprev, ys, vs, l);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Case D
|
||||
close xLIST_ITEM(xnext, _, ?xnextnext, xprev, l);
|
||||
close DLS(xnext, xprev, end, endprev, tail(zs), tail(ws), l);
|
||||
close xLIST_ITEM(end, _, ?endnext, endprev, l);
|
||||
close xLIST_ITEM(xprev, ?xprev_val, xnext, _, l);
|
||||
if (endnext == xprev)
|
||||
{
|
||||
close DLS(xprev, _, xnext, xprev, singleton(xprev), singleton(xprev_val), l);
|
||||
close DLS(end, endprev, xnext, xprev, ys, vs, l);
|
||||
join(end, endprev, xnext, xprev, ys, vs,
|
||||
xnext, xprev, end, endprev, tail(zs), tail(ws));
|
||||
}
|
||||
else
|
||||
{
|
||||
close DLS(xprev, ?xprevprev, xnext, xprev, singleton(xprev), singleton(xprev_val), l);
|
||||
assert DLS(endnext, end, xprev, xprevprev, ?cells_endnext_to_xprevprev, ?vals_endnext_to_xprevprev, l);
|
||||
join(endnext, end, xprev, xprevprev, cells_endnext_to_xprevprev, vals_endnext_to_xprevprev,
|
||||
xprev, xprevprev, xnext, xprev, singleton(xprev), singleton(xprev_val));
|
||||
close DLS(end, endprev, xnext, xprev, ys, vs, l);
|
||||
join(end, endprev, xnext, xprev, ys, vs,
|
||||
xnext, xprev, end, endprev, tail(zs), tail(ws));
|
||||
}
|
||||
}
|
||||
}
|
||||
@*/
|
||||
/*@remove_remove_nth(cells, x);@*/
|
||||
/*@
|
||||
if (idx == x)
|
||||
{
|
||||
close xLIST(l, len-1, xprev, end, append(ys, tail(zs)), append(vs, tail(ws)));
|
||||
}
|
||||
else
|
||||
{
|
||||
idx_remains_in_list(cells, idx, x, i);
|
||||
close xLIST(l, len-1, idx, end, append(ys, tail(zs)), append(vs, tail(ws)));
|
||||
}
|
||||
@*/
|
||||
/*@close xLIST_ITEM(x, nth(i, vals), xnext, xprev, NULL);@*/
|
||||
}
|
||||
|
||||
ListItem_t * client_example( List_t * l )
|
||||
/*@requires
|
||||
xLIST(l, ?len, ?idx, ?end, ?cells, ?vals) &*&
|
||||
idx != end &*&
|
||||
cells == cons(end, cons(idx, ?cells_tl)) &*&
|
||||
vals == cons(portMAX_DELAY, cons(42, ?vals_tl));@*/
|
||||
/*@ensures
|
||||
xLIST(l, len - 1, _, end, cons(end, cells_tl), cons(portMAX_DELAY, vals_tl)) &*&
|
||||
xLIST_ITEM(result, 42, _, _, NULL);@*/
|
||||
{
|
||||
/*@open xLIST(l, len, idx, end, cells, vals);@*/
|
||||
ListItem_t *index = l->pxIndex;
|
||||
/*@close xLIST(l, len, idx, end, cells, vals);@*/
|
||||
/*@close exists(l);@*/
|
||||
uxListRemove( index );
|
||||
return index;
|
||||
}
|
||||
|
||||
void client_example2( List_t * l )
|
||||
/*@requires
|
||||
xLIST(l, ?len, ?idx, ?end, ?cells, ?vals) &*&
|
||||
cells == cons(end, cons(?x1, cons(?x2, ?cells_tl))) &*&
|
||||
idx == x2 &*&
|
||||
vals == cons(portMAX_DELAY, cons(1, cons(2, ?vals_tl)));@*/
|
||||
/*@ensures
|
||||
xLIST(l, len-2, end, end, cons(end, cells_tl), cons(portMAX_DELAY, vals_tl)) &*&
|
||||
xLIST_ITEM(_, 1, _, _, NULL) &*&
|
||||
xLIST_ITEM(_, 2, _, _, NULL);@*/
|
||||
{
|
||||
/*@xLIST_distinct_cells(l);@*/
|
||||
/*@open xLIST(l, len, idx, end, cells, vals);@*/
|
||||
ListItem_t *index = l->pxIndex;
|
||||
/*@close xLIST(l, len, idx, end, cells, vals);@*/
|
||||
/*@close exists(l);@*/
|
||||
uxListRemove( index );
|
||||
/*@open xLIST(l, len-1, x1, end, cons(end, cons(x1, cells_tl)), cons(portMAX_DELAY, cons(1, vals_tl)));@*/
|
||||
index = l->pxIndex;
|
||||
/*@close xLIST(l, len-1, x1, end, cons(end, cons(x1, cells_tl)), cons(portMAX_DELAY, cons(1, vals_tl)));@*/
|
||||
/*@close exists(l);@*/
|
||||
uxListRemove( index );
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "proof/list.h"
|
||||
|
||||
/*@
|
||||
predicate xLIST_uninitialised(struct xLIST *l) =
|
||||
l->uxNumberOfItems |-> _ &*&
|
||||
l->pxIndex |-> _ &*&
|
||||
l->xListEnd.xItemValue |-> _ &*&
|
||||
l->xListEnd.pxNext |-> _ &*&
|
||||
l->xListEnd.pxPrevious |-> _ &*&
|
||||
l->xListEnd.pvOwner |-> _ &*&
|
||||
l->xListEnd.pxContainer |-> _ &*&
|
||||
struct_xLIST_ITEM_padding(&l->xListEnd);
|
||||
@*/
|
||||
|
||||
void vListInitialise( List_t * const pxList )
|
||||
/*@requires xLIST_uninitialised(pxList);@*/
|
||||
/*@ensures xLIST(pxList, 0, ?end, end, singleton(end), singleton(portMAX_DELAY));@*/
|
||||
{
|
||||
/*@open xLIST_uninitialised(pxList);@*/
|
||||
|
||||
/* The list structure contains a list item which is used to mark the
|
||||
* end of the list. To initialise the list the list end is inserted
|
||||
* as the only list entry. */
|
||||
pxList->pxIndex = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
|
||||
/* The list end value is the highest possible value in the list to
|
||||
* ensure it remains at the end of the list. */
|
||||
pxList->xListEnd.xItemValue = portMAX_DELAY;
|
||||
|
||||
/* The list end next and previous pointers point to itself so we know
|
||||
* when the list is empty. */
|
||||
pxList->xListEnd.pxNext = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
pxList->xListEnd.pxPrevious = ( ListItem_t * ) &( pxList->xListEnd ); /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. */
|
||||
|
||||
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
|
||||
|
||||
/* Write known values into the list if
|
||||
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_LIST_INTEGRITY_CHECK_1_VALUE( pxList );
|
||||
listSET_LIST_INTEGRITY_CHECK_2_VALUE( pxList );
|
||||
|
||||
#ifdef VERIFAST /*< ***change MiniList_t to ListItem_t*** */
|
||||
pxList->xListEnd.pxContainer = pxList;
|
||||
#endif
|
||||
/*@ListItem_t *end = &(pxList->xListEnd);@*/
|
||||
/*@close xLIST_ITEM(end, portMAX_DELAY, _, _, pxList);@*/
|
||||
/*@close DLS(end, end, end, end, singleton(end), singleton(portMAX_DELAY), pxList);@*/
|
||||
/*@close xLIST(pxList, 0, end, end, singleton(end), singleton(portMAX_DELAY));@*/
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "proof/list.h"
|
||||
|
||||
void vListInitialiseItem( ListItem_t * const pxItem )
|
||||
/*@requires xLIST_ITEM(pxItem, _, _, _, _);@*/
|
||||
/*@ensures xLIST_ITEM(pxItem, _, _, _, NULL);@*/
|
||||
{
|
||||
/* Make sure the list item is not recorded as being on a list. */
|
||||
pxItem->pxContainer = NULL;
|
||||
|
||||
/* Write known values into the list item if
|
||||
* configUSE_LIST_DATA_INTEGRITY_CHECK_BYTES is set to 1. */
|
||||
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
|
||||
/*@close xLIST_ITEM(pxItem, _, _, _, NULL);@*/
|
||||
}
|
@ -0,0 +1,316 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "proof/list.h"
|
||||
|
||||
|
||||
ListItem_t * choose(List_t * list);
|
||||
/*@ requires DLS(&(list->xListEnd), ?endprev, &(list->xListEnd), endprev, ?cells, ?vals, ?container);@*/
|
||||
/*@ ensures DLS(&(list->xListEnd), endprev, &(list->xListEnd), endprev, cells, vals, container) &*&
|
||||
mem(result, cells) == true;@*/
|
||||
|
||||
void vListInsert( List_t * const pxList,
|
||||
ListItem_t * const pxNewListItem )
|
||||
/*@requires xLIST(pxList, ?len, ?idx, ?end, ?cells, ?vals) &*&
|
||||
xLIST_ITEM(pxNewListItem, ?val, _, _, _);@*/
|
||||
/*@ensures xLIST(pxList, len+1, idx, end, ?new_cells, ?new_vals) &*&
|
||||
remove(pxNewListItem, new_cells) == cells
|
||||
;@*/
|
||||
{
|
||||
/*@xLIST_star_item(pxList, pxNewListItem);@*/
|
||||
/*@open xLIST_ITEM(pxNewListItem, _, _, _, _);@*/
|
||||
/*@open xLIST(pxList, len, idx, end, cells, vals);@*/
|
||||
/*@assert DLS(end, ?endprev, end, endprev, cells, vals, pxList);@*/
|
||||
ListItem_t * pxIterator;
|
||||
const TickType_t xValueOfInsertion = pxNewListItem->xItemValue;
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
* the list data structures being overwritten in memory. They will not catch
|
||||
* data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
|
||||
/* Insert the new list item into the list, sorted in xItemValue order.
|
||||
*
|
||||
* If the list already contains a list item with the same item value then the
|
||||
* new list item should be placed after it. This ensures that TCBs which are
|
||||
* stored in ready lists (all of which have the same xItemValue value) get a
|
||||
* share of the CPU. However, if the xItemValue is the same as the back marker
|
||||
* the iteration loop below will not end. Therefore the value is checked
|
||||
* first, and the algorithm slightly modified if necessary. */
|
||||
if( xValueOfInsertion == portMAX_DELAY )
|
||||
{
|
||||
/*@open DLS(end, endprev, end, endprev, cells, vals, pxList);@*/
|
||||
/*@open xLIST_ITEM(end, portMAX_DELAY, ?endnext, endprev, pxList);@*/
|
||||
/*@
|
||||
if (end != endprev)
|
||||
{
|
||||
assert DLS(endnext, end, end, endprev, tail(cells), tail(vals), pxList);
|
||||
if (endnext == endprev)
|
||||
{
|
||||
// done
|
||||
}
|
||||
else
|
||||
{
|
||||
dls_last_mem(endnext, end, end, endprev, tail(cells));
|
||||
split(endnext, end, end, endprev, tail(cells), tail(vals), endprev, index_of(endprev, tail(cells)));
|
||||
}
|
||||
open DLS(endprev, _, _, _, _, _, _);
|
||||
open xLIST_ITEM(endprev, _, _, _, _);
|
||||
}
|
||||
@*/
|
||||
pxIterator = pxList->xListEnd.pxPrevious;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* *** NOTE ***********************************************************
|
||||
* If you find your application is crashing here then likely causes are
|
||||
* listed below. In addition see https://www.freertos.org/FAQHelp.html for
|
||||
* more tips, and ensure configASSERT() is defined!
|
||||
* https://www.freertos.org/a00110.html#configASSERT
|
||||
*
|
||||
* 1) Stack overflow -
|
||||
* see https://www.freertos.org/Stacks-and-stack-overflow-checking.html
|
||||
* 2) Incorrect interrupt priority assignment, especially on Cortex-M
|
||||
* parts where numerically high priority values denote low actual
|
||||
* interrupt priorities, which can seem counter intuitive. See
|
||||
* https://www.freertos.org/RTOS-Cortex-M3-M4.html and the definition
|
||||
* of configMAX_SYSCALL_INTERRUPT_PRIORITY on
|
||||
* https://www.freertos.org/a00110.html
|
||||
* 3) Calling an API function from within a critical section or when
|
||||
* the scheduler is suspended, or calling an API function that does
|
||||
* not end in "FromISR" from an interrupt.
|
||||
* 4) Using a queue or semaphore before it has been initialised or
|
||||
* before the scheduler has been started (are interrupts firing
|
||||
* before vTaskStartScheduler() has been called?).
|
||||
**********************************************************************/
|
||||
|
||||
#ifdef VERIFAST /*< ***over-approximate list insert loop*** */
|
||||
pxIterator = choose(pxList);
|
||||
#else
|
||||
for( pxIterator = ( ListItem_t * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext ) /*lint !e826 !e740 !e9087 The mini list structure is used as the list end to save RAM. This is checked and valid. *//*lint !e440 The iterator moves to a different value, not xValueOfInsertion. */
|
||||
{
|
||||
/* There is nothing to do here, just iterating to the wanted
|
||||
* insertion position. */
|
||||
}
|
||||
#endif
|
||||
/*@int i = index_of(pxIterator, cells);@*/
|
||||
/*@
|
||||
if (pxIterator == end)
|
||||
{
|
||||
open DLS(end, endprev, end, endprev, cells, vals, pxList);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, ?endnext, endprev, pxList);
|
||||
if (end != endprev)
|
||||
{
|
||||
assert DLS(endnext, end, end, endprev, tail(cells), tail(vals), pxList);
|
||||
open DLS(endnext, _, _, _, _, _, _);
|
||||
open xLIST_ITEM(endnext, _, _, _, _);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(end, endprev, end, endprev, cells, vals, pxList);
|
||||
dls_first_mem(end, endprev, end, endprev, cells);
|
||||
assert pxIterator != end;
|
||||
assert index_of(end, cells) == 0;
|
||||
split(end, endprev, end, endprev, cells, vals, pxIterator, i);
|
||||
assert DLS(end, endprev, pxIterator, ?iterprev, take(i, cells), take(i, vals), pxList);
|
||||
assert DLS(pxIterator, iterprev, end, endprev, drop(i, cells), drop(i, vals), pxList);
|
||||
open DLS(pxIterator, iterprev, end, endprev, drop(i, cells), drop(i, vals), pxList);
|
||||
open xLIST_ITEM(pxIterator, _, ?iternext, iterprev, pxList);
|
||||
if (pxIterator == endprev)
|
||||
{
|
||||
open DLS(end, endprev, pxIterator, iterprev, take(i, cells), take(i, vals), pxList);
|
||||
take_take(1, i, vals);
|
||||
assert xLIST_ITEM(end, portMAX_DELAY, _, _, _);
|
||||
open xLIST_ITEM(iternext, _, _, pxIterator, _);
|
||||
}
|
||||
else
|
||||
{
|
||||
open DLS(iternext, pxIterator, end, endprev, _, _, _);
|
||||
open xLIST_ITEM(iternext, _, _, pxIterator, _);
|
||||
}
|
||||
}@*/
|
||||
}
|
||||
|
||||
pxNewListItem->pxNext = pxIterator->pxNext;
|
||||
pxNewListItem->pxNext->pxPrevious = pxNewListItem;
|
||||
pxNewListItem->pxPrevious = pxIterator;
|
||||
pxIterator->pxNext = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. This allows fast removal of the
|
||||
* item later. */
|
||||
pxNewListItem->pxContainer = pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
|
||||
/*@close xLIST_ITEM(pxNewListItem, val, ?iternext, pxIterator, pxList);@*/
|
||||
/*@close xLIST_ITEM(pxIterator, ?iterval, pxNewListItem, ?iterprev, pxList);@*/
|
||||
/*@
|
||||
if( xValueOfInsertion == portMAX_DELAY )
|
||||
{
|
||||
assert iternext == end;
|
||||
assert pxIterator == endprev;
|
||||
if (end == endprev)
|
||||
{
|
||||
close DLS(end, pxNewListItem, pxNewListItem, end, cells, vals, pxList);
|
||||
close DLS(pxNewListItem, end, end, pxNewListItem, singleton(pxNewListItem), singleton(val), pxList);
|
||||
join(end, pxNewListItem, pxNewListItem, end, cells, vals,
|
||||
pxNewListItem, end, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
close xLIST_ITEM(end, portMAX_DELAY, ?endnext, pxNewListItem, pxList);
|
||||
close DLS(pxNewListItem, endprev, end, pxNewListItem, singleton(pxNewListItem), singleton(val), pxList);
|
||||
if (endnext == endprev)
|
||||
{
|
||||
assert xLIST_ITEM(endnext, ?endnextval, pxNewListItem, end, pxList);
|
||||
close DLS(end, pxNewListItem, endnext, end, singleton(end), singleton(portMAX_DELAY), pxList);
|
||||
close DLS(endnext, end, pxNewListItem, endnext, singleton(endnext), singleton(endnextval), pxList);
|
||||
join(end, pxNewListItem, endnext, end, singleton(end), singleton(portMAX_DELAY),
|
||||
endnext, end, pxNewListItem, endnext, singleton(endnext), singleton(endnextval));
|
||||
assert DLS(end, pxNewListItem, pxNewListItem, endnext, cells, vals, pxList);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(endnext, end, endprev, ?endprevprev, ?cells_endnext_to_endprevprev, ?vals_endnext_to_endprevprev, pxList);
|
||||
assert cells_endnext_to_endprevprev == take(index_of(endprev, tail(cells)), tail(cells));
|
||||
assert index_of(endprev, tail(cells)) == length(tail(cells)) - 1;
|
||||
assert cells_endnext_to_endprevprev == take(length(tail(cells)) - 1, tail(cells));
|
||||
assert xLIST_ITEM(endprev, ?endprevval, pxNewListItem, endprevprev, pxList);
|
||||
close DLS(endprev, endprevprev, pxNewListItem, endprev, singleton(endprev), singleton(endprevval), pxList);
|
||||
dls_last_mem(endnext, end, endprev, endprevprev, cells_endnext_to_endprevprev);
|
||||
dls_star_item(endnext, endprevprev, end);
|
||||
close DLS(end, pxNewListItem, endprev, endprevprev, cons(end, cells_endnext_to_endprevprev), cons(portMAX_DELAY, vals_endnext_to_endprevprev), pxList);
|
||||
join(end, pxNewListItem, endprev, endprevprev, cons(end, cells_endnext_to_endprevprev), cons(portMAX_DELAY, vals_endnext_to_endprevprev),
|
||||
endprev, endprevprev, pxNewListItem, endprev, singleton(endprev), singleton(endprevval));
|
||||
assert DLS(end, pxNewListItem, pxNewListItem, endprev, cells, vals, pxList);
|
||||
|
||||
}
|
||||
join(end, pxNewListItem, pxNewListItem, endprev, cells, vals,
|
||||
pxNewListItem, endprev, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
remove_append(pxNewListItem, cells, singleton(pxNewListItem));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (pxIterator == end)
|
||||
{
|
||||
if (iternext == end)
|
||||
{
|
||||
close DLS(end, pxNewListItem, pxNewListItem, end, cells, vals, pxList);
|
||||
close DLS(pxNewListItem, pxIterator, end, pxNewListItem, singleton(pxNewListItem), singleton(val), pxList);
|
||||
join(end, pxNewListItem, pxNewListItem, end, cells, vals,
|
||||
pxNewListItem, pxIterator, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
close xLIST_ITEM(iternext, ?iternextval, _, pxNewListItem, pxList);
|
||||
if (iternext == endprev)
|
||||
{
|
||||
close DLS(iternext, pxNewListItem, end, endprev, singleton(iternext), singleton(iternextval), pxList);
|
||||
dls_last_mem(iternext, pxNewListItem, end, endprev, singleton(iternext));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(?iternextnext, iternext, end, endprev, ?cells_iternextnext_to_endprev, ?vals_iternextnext_to_endprev, pxList);
|
||||
close DLS(iternext, pxNewListItem, end, endprev, cons(iternext, cells_iternextnext_to_endprev), cons(iternextval, vals_iternextnext_to_endprev), pxList);
|
||||
dls_last_mem(iternext, pxNewListItem, end, endprev, cons(iternext, cells_iternextnext_to_endprev));
|
||||
}
|
||||
close DLS(end, endprev, pxNewListItem, end, singleton(end), singleton(portMAX_DELAY), pxList);
|
||||
assert DLS(iternext, pxNewListItem, end, endprev, ?cells_iternext_to_endprev, ?vals_iternext_to_endprev, pxList);
|
||||
dls_star_item(iternext, endprev, pxNewListItem);
|
||||
close DLS(pxNewListItem, pxIterator, end, endprev, cons(pxNewListItem, cells_iternext_to_endprev), cons(val, vals_iternext_to_endprev), pxList);
|
||||
join(end, endprev, pxNewListItem, end, singleton(end), singleton(portMAX_DELAY),
|
||||
pxNewListItem, pxIterator, end, endprev, cons(pxNewListItem, cells_iternext_to_endprev), cons(val, vals_iternext_to_endprev));
|
||||
close xLIST(pxList, len+1, idx, end, cons(end, cons(pxNewListItem, cells_iternext_to_endprev)), cons(portMAX_DELAY, cons(val, vals_iternext_to_endprev)));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
close xLIST_ITEM(iternext, ?iternextval, _, pxNewListItem, pxList);
|
||||
if (pxIterator == endprev)
|
||||
{
|
||||
if (iterprev == end)
|
||||
{
|
||||
close DLS(end, pxNewListItem, pxIterator, end, singleton(end), singleton(portMAX_DELAY), pxList);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(_, iternext, pxIterator, iterprev, ?cells1, ?vals1, _);
|
||||
close DLS(end, pxNewListItem, pxIterator, iterprev, cons(end, cells1), cons(portMAX_DELAY, vals1), pxList);
|
||||
}
|
||||
int i = index_of(pxIterator, cells);
|
||||
assert DLS(end, pxNewListItem, pxIterator, iterprev, take(i, cells), take(i, vals), pxList);
|
||||
close DLS(pxIterator, iterprev, pxNewListItem, pxIterator, drop(i, cells), drop(i, vals), pxList);
|
||||
close DLS(pxNewListItem, pxIterator, end, pxNewListItem, singleton(pxNewListItem), singleton(val), pxList);
|
||||
join(end, pxNewListItem, pxIterator, iterprev, take(i, cells), take(i, vals),
|
||||
pxIterator, iterprev, pxNewListItem, pxIterator, drop(i, cells), drop(i, vals));
|
||||
join(end, pxNewListItem, pxNewListItem, pxIterator, cells, vals,
|
||||
pxNewListItem, pxIterator, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
remove_append(pxNewListItem, cells, singleton(pxNewListItem));
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = index_of(pxIterator, cells);
|
||||
if (iternext == endprev)
|
||||
{
|
||||
close DLS(iternext, pxNewListItem, end, endprev, singleton(iternext), singleton(iternextval), pxList);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(_, iternext, end, endprev, ?cells0, ?vals0, pxList);
|
||||
dls_star_item(end, iterprev, iternext);
|
||||
close DLS(iternext, pxNewListItem, end, endprev, tail(drop(i, cells)), tail(drop(i, vals)), pxList);
|
||||
}
|
||||
drop_drop(1, i, cells);
|
||||
drop_drop(1, i, vals);
|
||||
assert DLS(iternext, pxNewListItem, end, endprev, drop(i+1, cells), drop(i+1, vals), pxList);
|
||||
assert DLS(end, endprev, pxIterator, iterprev, take(i, cells), take(i, vals), pxList);
|
||||
dls_star_item(iternext, endprev, pxNewListItem);
|
||||
dls_last_mem(iternext, pxNewListItem, end, endprev, drop(i+1, cells));
|
||||
close DLS(pxNewListItem, pxIterator, end, endprev, cons(pxNewListItem, drop(i+1, cells)), cons(val, drop(i+1, vals)), pxList);
|
||||
close DLS(pxIterator, iterprev, end, endprev, cons(pxIterator, cons(pxNewListItem, drop(i+1, cells))), cons(iterval, cons(val, drop(i+1, vals))), pxList);
|
||||
join(end, endprev, pxIterator, iterprev, take(i, cells), take(i, vals),
|
||||
pxIterator, iterprev, end, endprev, cons(pxIterator, cons(pxNewListItem, drop(i+1, cells))), cons(iterval, cons(val, drop(i+1, vals))));
|
||||
list<struct xLIST_ITEM * >new_cells = append(take(i, cells), cons(pxIterator, cons(pxNewListItem, drop(i+1, cells))));
|
||||
list<TickType_t >new_vals = append(take(i, vals), cons(iterval, cons(val, drop(i+1, vals))));
|
||||
head_append(take(i, cells), cons(pxIterator, cons(pxNewListItem, drop(i+1, cells))));
|
||||
take_head(take(i, cells));
|
||||
take_take(1, i, cells);
|
||||
assert( end == head(new_cells) );
|
||||
head_append(take(i, vals), cons(iterval, cons(val, drop(i+1, vals))));
|
||||
take_head(take(i, vals));
|
||||
take_take(1, i, vals);
|
||||
assert( portMAX_DELAY == head(new_vals) );
|
||||
append_take_drop_n(cells, index_of(pxIterator, cells));
|
||||
close xLIST(pxList, len+1, idx, end, append(take(i, cells), cons(pxIterator, cons(pxNewListItem, drop(i+1, cells)))), append(take(i, vals), cons(iterval, cons(val, drop(i+1, vals)))));
|
||||
mem_take_false(pxNewListItem, i, cells);
|
||||
remove_append(pxNewListItem, take(i, cells), cons(pxIterator, cons(pxNewListItem, drop(i+1, cells))));
|
||||
}
|
||||
}
|
||||
}@*/
|
||||
}
|
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* FreeRTOS VeriFast Proofs
|
||||
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
* the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "proof/list.h"
|
||||
|
||||
void vListInsertEnd( List_t * const pxList,
|
||||
ListItem_t * const pxNewListItem )
|
||||
/*@requires xLIST(pxList, ?len, ?idx, ?end, ?cells, ?vals) &*&
|
||||
xLIST_ITEM(pxNewListItem, ?val, _, _, _);@*/
|
||||
/*@ensures xLIST(pxList, len+1, idx, end, ?new_cells, ?new_vals) &*&
|
||||
idx == end
|
||||
? (new_cells == append(cells, singleton(pxNewListItem)) &*&
|
||||
new_vals == append(vals, singleton(val)))
|
||||
: (new_cells == append(take(index_of(idx, cells), cells), append(singleton(pxNewListItem), drop(index_of(idx, cells), cells))) &*&
|
||||
new_vals == append(take(index_of(idx, cells), vals), append(singleton(val), drop(index_of(idx, cells), vals))));@*/
|
||||
{
|
||||
/*@xLIST_star_item(pxList, pxNewListItem);@*/
|
||||
/*@assert mem(pxNewListItem, cells) == false;@*/
|
||||
/*@open xLIST(pxList, len, idx, end, cells, vals);@*/
|
||||
#ifdef VERIFAST /*< const pointer declaration */
|
||||
ListItem_t * pxIndex = pxList->pxIndex;
|
||||
#else
|
||||
ListItem_t * const pxIndex = pxList->pxIndex;
|
||||
|
||||
/* Only effective when configASSERT() is also defined, these tests may catch
|
||||
* the list data structures being overwritten in memory. They will not catch
|
||||
* data errors caused by incorrect configuration or use of FreeRTOS. */
|
||||
listTEST_LIST_INTEGRITY( pxList );
|
||||
listTEST_LIST_ITEM_INTEGRITY( pxNewListItem );
|
||||
#endif
|
||||
|
||||
/*@open xLIST_ITEM(pxNewListItem, _, _, _, _);@*/
|
||||
/*@assert DLS(end, ?endprev, end, _, cells, vals, pxList);@*/
|
||||
/*@dls_first_mem(end, endprev, end, endprev, cells);@*/
|
||||
/*@dls_last_mem(end, endprev, end, endprev, cells);@*/
|
||||
/*@
|
||||
if (end == idx)
|
||||
{
|
||||
open DLS(end, endprev, end, endprev, cells, vals, pxList);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, ?endnext, endprev, pxList);
|
||||
if (end == endprev)
|
||||
{
|
||||
// Case A (singleton): idx==end==endprev
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(endnext, end, end, endprev, tail(cells), tail(vals), pxList);
|
||||
if (endnext == endprev)
|
||||
{
|
||||
// Case B (two): idx==end and endnext==endprev
|
||||
open DLS(endnext, end, end, endnext, _, _, _);
|
||||
open xLIST_ITEM(endnext, _, _, _, _);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case C: idx==end and DLS:endnext...endprev
|
||||
split(endnext, end, end, endprev, tail(cells), tail(vals), endprev, index_of(endprev, tail(cells)));
|
||||
open DLS(endprev, _, _, _, _, _, _);
|
||||
open xLIST_ITEM(endprev, _, _, _, _);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = index_of(idx, cells);
|
||||
split(end, endprev, end, endprev, cells, vals, idx, i);
|
||||
assert DLS(end, endprev, idx, ?idxprev, take(i, cells), take(i, vals), pxList);
|
||||
assert DLS(idx, idxprev, end, endprev, drop(i, cells), drop(i, vals), pxList);
|
||||
open DLS(idx, idxprev, end, endprev, _, _, _);
|
||||
open xLIST_ITEM(idx, _, _, _, _);
|
||||
if (end == idxprev)
|
||||
{
|
||||
// Case D: end==idxprev and DLS:idx...endprev
|
||||
take_take(1, i, vals);
|
||||
take_head(vals);
|
||||
open DLS(end, endprev, idx, idxprev, take(i, cells), take(i, vals), pxList);
|
||||
open xLIST_ITEM(end, portMAX_DELAY, _, _, _);
|
||||
assert length(take(i, cells)) == 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case E: DLS:end...idxprev and DLS:idx...endprev
|
||||
dls_last_mem(end, endprev, idx, idxprev, take(i, cells));
|
||||
split(end, endprev, idx, idxprev, take(i, cells), take(i, vals), idxprev, index_of(idxprev, take(i, cells)));
|
||||
open DLS(idxprev, _, _, idxprev, _, _, _);
|
||||
length_take(i, cells);
|
||||
drop_take_singleton(i, vals);
|
||||
open xLIST_ITEM(idxprev, nth(i-1, vals), _, _, _);
|
||||
}
|
||||
}
|
||||
@*/
|
||||
|
||||
/* Insert a new list item into pxList, but rather than sort the list,
|
||||
* makes the new list item the last item to be removed by a call to
|
||||
* listGET_OWNER_OF_NEXT_ENTRY(). */
|
||||
pxNewListItem->pxNext = pxIndex;
|
||||
pxNewListItem->pxPrevious = pxIndex->pxPrevious;
|
||||
|
||||
/* Only used during decision coverage testing. */
|
||||
mtCOVERAGE_TEST_DELAY();
|
||||
|
||||
pxIndex->pxPrevious->pxNext = pxNewListItem;
|
||||
pxIndex->pxPrevious = pxNewListItem;
|
||||
|
||||
/* Remember which list the item is in. */
|
||||
pxNewListItem->pxContainer = pxList;
|
||||
|
||||
( pxList->uxNumberOfItems )++;
|
||||
|
||||
/*@
|
||||
if (end == idx)
|
||||
{
|
||||
close xLIST_ITEM(pxNewListItem, val, end, endprev, pxList);
|
||||
close DLS(pxNewListItem, endprev, end, pxNewListItem, singleton(pxNewListItem), singleton(val), pxList);
|
||||
close xLIST_ITEM(end, portMAX_DELAY, ?endnext, pxNewListItem, pxList);
|
||||
if (end == endprev)
|
||||
{
|
||||
// Case A (singleton): idx==end==endprev
|
||||
close DLS(end, pxNewListItem, endnext, end, cells, vals, pxList);
|
||||
join(end, pxNewListItem, endnext, end, cells, vals,
|
||||
pxNewListItem, endprev, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
close xLIST_ITEM(endprev, ?endprevval, pxNewListItem, ?endprevprev, _);
|
||||
if (endnext == endprev)
|
||||
{
|
||||
// Case B (two): idx==end and endnext==endprev
|
||||
close DLS(endprev, end, pxNewListItem, endprev, singleton(endprev), singleton(endprevval), pxList);
|
||||
close DLS(end, pxNewListItem, pxNewListItem, endprev, cells, vals, pxList);
|
||||
join(end, pxNewListItem, pxNewListItem, endprev, cells, vals,
|
||||
pxNewListItem, endprev, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case C: idx==end and DLS:endnext...endprev
|
||||
close DLS(endprev, endprevprev, pxNewListItem, endprev, singleton(endprev), singleton(endprevval), pxList);
|
||||
assert DLS(endnext, end, endprev, endprevprev, ?cells_endnext_to_endprevprev, ?vals_endnext_to_endprevprev, pxList);
|
||||
join(endnext, end, endprev, endprevprev, cells_endnext_to_endprevprev, vals_endnext_to_endprevprev,
|
||||
endprev, endprevprev, pxNewListItem, endprev, singleton(endprev), singleton(endprevval));
|
||||
close DLS(end, pxNewListItem, pxNewListItem, endprev, cells, vals, pxList);
|
||||
join(end, pxNewListItem, pxNewListItem, endprev, cells, vals,
|
||||
pxNewListItem, endprev, end, pxNewListItem, singleton(pxNewListItem), singleton(val));
|
||||
close xLIST(pxList, len+1, idx, end, append(cells, singleton(pxNewListItem)), append(vals, singleton(val)));
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case D: end==idxprev and DLS:idx...endprev
|
||||
// Case E: DLS:end...idxprev and DLS:idx...endprev
|
||||
int i = index_of(idx, cells);
|
||||
close xLIST_ITEM(pxNewListItem, val, idx, ?idxprev, pxList);
|
||||
close xLIST_ITEM(idx, ?idxval, ?idxnext, pxNewListItem, pxList);
|
||||
nth_drop2(vals, i);
|
||||
assert idxval == nth(i, vals);
|
||||
close xLIST_ITEM(idxprev, ?idxprevval, pxNewListItem, ?idxprevprev, pxList);
|
||||
|
||||
if (end == idxprev)
|
||||
{
|
||||
close DLS(end, endprev, pxNewListItem, end, singleton(end), singleton(portMAX_DELAY), pxList);
|
||||
}
|
||||
else
|
||||
{
|
||||
length_take(i, cells);
|
||||
take_take(i-1, i, vals);
|
||||
take_singleton(i-1, vals);
|
||||
take_singleton(i, vals);
|
||||
assert DLS(end, endprev, idxprev, idxprevprev, ?cells_end_to_idxprevprev, take(i-1, vals), pxList);
|
||||
close DLS(idxprev, idxprevprev, pxNewListItem, idxprev, singleton(idxprev), singleton(idxprevval), pxList);
|
||||
join(end, endprev, idxprev, idxprevprev, cells_end_to_idxprevprev, take(i-1, vals),
|
||||
idxprev, idxprevprev, pxNewListItem, idxprev, singleton(idxprev), singleton(idxprevval));
|
||||
}
|
||||
|
||||
if (idx == endprev)
|
||||
{
|
||||
close DLS(idx, pxNewListItem, end, idx, singleton(idx), singleton(idxval), pxList);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert DLS(end, endprev, pxNewListItem, idxprev, ?cells_end_to_idxprev, ?vals_end_to_idxprev, pxList);
|
||||
close DLS(idx, pxNewListItem, end, endprev, drop(i, cells), drop(i, vals), pxList);
|
||||
}
|
||||
|
||||
assert DLS(end, endprev, pxNewListItem, idxprev, take(i, cells), take(i, vals), pxList);
|
||||
assert DLS(idx, pxNewListItem, end, endprev, drop(i, cells), drop(i, vals), pxList);
|
||||
assert xLIST_ITEM(pxNewListItem, val, idx, idxprev, pxList);
|
||||
dls_star_item(idx, endprev, pxNewListItem);
|
||||
close DLS(pxNewListItem, idxprev, end, endprev, cons(pxNewListItem, drop(i, cells)), cons(val, drop(i, vals)), pxList);
|
||||
join(end, endprev, pxNewListItem, idxprev, take(i, cells), take(i, vals),
|
||||
pxNewListItem, idxprev, end, endprev, cons(pxNewListItem, drop(i, cells)), cons(val, drop(i, vals)));
|
||||
assert DLS(end, endprev, end, endprev, ?cells_new, ?vals_new, pxList);
|
||||
assert cells_new == append(take(i, cells), append(singleton(pxNewListItem), drop(i, cells)));
|
||||
assert vals_new == append(take(i, vals) , append(singleton(val), drop(i, vals)));
|
||||
head_append(take(i, cells), append(singleton(pxNewListItem), drop(i, cells)));
|
||||
take_take(1, i, cells);
|
||||
head_append(take(i, vals), append(singleton(val), drop(i, vals)));
|
||||
take_take(1, i, vals);
|
||||
close xLIST(pxList, len+1, idx, end, cells_new, vals_new);
|
||||
}
|
||||
@*/
|
||||
}
|
||||
|
||||
void client_example1( List_t * const l, ListItem_t * const pxNewListItem )
|
||||
/*@requires
|
||||
xLIST(l, ?len, ?idx, ?end, ?cells, ?vals) &*&
|
||||
xLIST_ITEM(pxNewListItem, ?val, _, _, _) &*&
|
||||
idx == end;@*/
|
||||
/*@ensures
|
||||
xLIST(l, len + 1, idx, end, _, append(vals, singleton(val)));@*/
|
||||
{
|
||||
vListInsertEnd(l, pxNewListItem);
|
||||
}
|
@ -1,3 +1,3 @@
|
||||
#!/bin/bash -eu
|
||||
|
||||
NO_COVERAGE=1 EXTRA_VERIFAST_ARGS=-stats make queue | grep overhead: | sort | uniq
|
||||
NO_COVERAGE=1 EXTRA_VERIFAST_ARGS=-stats make queue list | grep overhead: | sort | uniq
|
||||
|
Loading…
Reference in New Issue