Update VeriFast proofs (#836)

* Undo syntax changes preventing VeriFast parsing

* Update proofs inline with source changes

Outstanding:
  - xQueueGenericReset return code
  - Not using prvIncrementQueueTxLock or prvIncrementQueueRxLock macros

* Remove git hash check

* Document new changes between proven code and implementation

* Update copyright header

* VeriFast proofs: turn off uncrustify checks

Uncrustify requires formatting of comments that is at odds with VeriFast's
proof annotations, which are contained within comments.

* Update ci.yml

Co-authored-by: Joseph Julicher <jjulicher@mac.com>
Co-authored-by: Aniruddha Kanhere <60444055+AniruddhaKanhere@users.noreply.github.com>
This commit is contained in:
Nathan Chong 2022-10-27 17:54:38 -04:00 committed by GitHub
parent 4e0fecaadd
commit 4f87f485d5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 1877 additions and 1864 deletions

View file

@ -114,7 +114,7 @@ jobs:
# Add path to the tool to the environment variable.
PATH=$PATH:commonCI/spellings/tools
# Make sure that only Amazon licenced files are checked.
sed -i 's/`find $DIRNAME \\( -iname \\\*\.\[ch\] -o -iname \\\*\.dox \\) -type f`/`grep -ril "copyright \(c\) \[0-9\]\[0-9\]\[0-9\]\[0-9\] amazon.com" | grep "\\.\[ch\]"`/g' commonCI/spellings/tools/find-unknown-comment-words
sed -i 's/`find $DIRNAME \\( -iname \\\*\.\[ch\] -o -iname \\\*\.dox \\) -type f`/`grep -ril "copyright \(c\) \[0-9\]\[0-9\]\[0-9\]\[0-9\] amazon.com" | grep "\\.\[ch\]" | grep -v "FreeRTOS\/FreeRTOS\/Test\/VeriFast"`/g' commonCI/spellings/tools/find-unknown-comment-words
# Run the spell check script.
find-unknown-comment-words --directory FreeRTOS/ --lexicon FreeRTOS/lexicon.txt
# Check the exit status.

View file

@ -18,7 +18,7 @@ all: queue list
.PHONY: queue
queue:
@$(VERIFAST) $(VERIFAST_ARGS) queue/create.c | $(call check_coverage,325)
@$(VERIFAST) $(VERIFAST_ARGS) -disable_overflow_check queue/create.c | $(call check_coverage,315)
@$(VERIFAST) $(VERIFAST_ARGS) queue/prvCopyDataFromQueue.c | $(call check_coverage,308)
@$(VERIFAST) $(VERIFAST_ARGS) -disable_overflow_check queue/prvCopyDataToQueue.c | $(call check_coverage,336)
@$(VERIFAST) $(VERIFAST_ARGS) queue/prvIsQueueEmpty.c | $(call check_coverage,289)
@ -41,7 +41,7 @@ queue:
list:
@$(VERIFAST) $(VERIFAST_ARGS) list/listLIST_IS_EMPTY.c | $(call check_coverage,314)
@$(VERIFAST) $(VERIFAST_ARGS) list/uxListRemove.c | $(call check_coverage,440)
@$(VERIFAST) $(VERIFAST_ARGS) list/vListInitialise.c | $(call check_coverage,325)
@$(VERIFAST) $(VERIFAST_ARGS) list/vListInitialise.c | $(call check_coverage,329)
@$(VERIFAST) $(VERIFAST_ARGS) list/vListInitialiseItem.c | $(call check_coverage,316)
@$(VERIFAST) $(VERIFAST_ARGS) -disable_overflow_check list/vListInsertEnd.c | $(call check_coverage,410)
@$(VERIFAST) $(VERIFAST_ARGS) -disable_overflow_check list/vListInsert.c | $(call check_coverage,456)
@ -49,18 +49,3 @@ list:
.PHONY: proof_changes
proof_changes:
@git grep "if[n]*def VERIFAST" | cut -f 3- -d ' ' | sort | uniq
GIT?=git
NO_CHANGE_CHECKOUT_DIR=no-change-check-freertos-kernel
NO_CHANGE_EXPECTED_HASH_QUEUE = ec62f69dab7
NO_CHANGE_EXPECTED_HASH_QUEUE_HEADER = ec62f69dab7
NO_CHANGE_EXPECTED_HASH_LIST = ec62f69dab7
NO_CHANGE_EXPECTED_HASH_LIST_HEADER = ec62f69dab7
.PHONY: synced_with_source_check
synced_with_source_check:
@rm -rf $(NO_CHANGE_CHECKOUT_DIR)
@$(GIT) clone https://github.com/FreeRTOS/FreeRTOS-Kernel.git $(NO_CHANGE_CHECKOUT_DIR)
@cd $(NO_CHANGE_CHECKOUT_DIR) && $(GIT) diff --quiet $(NO_CHANGE_EXPECTED_HASH_QUEUE) queue.c
@cd $(NO_CHANGE_CHECKOUT_DIR) && $(GIT) diff --quiet $(NO_CHANGE_EXPECTED_HASH_QUEUE_HEADER) include/queue.h
@cd $(NO_CHANGE_CHECKOUT_DIR) && $(GIT) diff --quiet $(NO_CHANGE_EXPECTED_HASH_LIST) list.c
@cd $(NO_CHANGE_CHECKOUT_DIR) && $(GIT) diff --quiet $(NO_CHANGE_EXPECTED_HASH_LIST_HEADER) include/list.h

View file

@ -56,6 +56,7 @@ Then click `Verify` and `Verify Program` (or press F5). Note that the following
proofs require arithmetic overflow checking to be turned off (click `Verify`
and uncheck `Check arithmetic overflow`).
- `queue/create.c`
- `queue/prvCopyDataToQueue.c`
- `queue/xQueueGenericSendFromISR.c`
- `queue/xQueueReceiveFromISR.c`

View file

@ -80,7 +80,10 @@ The main queue changes are:
- xQueueGenericReset happens-before concurrent behavior: assume that queue
initialisation is not concurrent.
- do not model pxIndex and xListEnd of xLIST struct: ignore these fields in
the list structs of the queue implementation
the list structs of the queue implementation.
- we do not use the prvIncrementQueueTxLock or prvIncrementQueueRxLock macros
in xQueueGenericSendFromISR and xQueueReceiveFromISR functions.
- we prove an older version of xQueueGenericReset that always resets a queue
The main list changes are:

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,13 +24,15 @@
*
*/
/* *INDENT-OFF* */
#ifndef LIST_H
#define LIST_H
#define VERIFAST
#include <stdlib.h>
#include <stdint.h>
/*@#include "common.gh" */
//@#include "common.gh"
typedef size_t TickType_t;
typedef size_t UBaseType_t;
@ -54,8 +56,7 @@ typedef ssize_t BaseType_t;
struct xLIST;
struct xLIST_ITEM
{
struct xLIST_ITEM {
TickType_t xItemValue;
struct xLIST_ITEM * pxNext;
struct xLIST_ITEM * pxPrevious;
@ -64,8 +65,7 @@ struct xLIST_ITEM
};
typedef struct xLIST_ITEM ListItem_t;
typedef struct xLIST
{
typedef struct xLIST {
UBaseType_t uxNumberOfItems;
struct xLIST_ITEM *pxIndex;
#ifdef VERIFAST /*< ***change MiniList_t to ListItem_t*** */
@ -76,301 +76,301 @@ typedef struct xLIST
} 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;
* @*/
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);
* }
* @*/
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)`. */
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 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);
* }
* }
* @*/
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 */
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#ifndef QUEUE_H
#define QUEUE_H
@ -102,14 +104,12 @@ typedef struct SemaphoreData
} SemaphoreData_t;
/* VeriFast does not support unions so we replace with a struct */
struct fake_union_t
{
struct fake_union_t {
QueuePointers_t xQueue;
SemaphoreData_t xSemaphore;
};
typedef struct xLIST
{
typedef struct xLIST {
UBaseType_t uxNumberOfItems;
#ifndef VERIFAST /*< do not model pxIndex and xListEnd of xLIST struct */
struct xLIST_ITEM *pxIndex;
@ -166,266 +166,259 @@ typedef struct QueueDefinition * QueueHandle_t;
/*@
#define QUEUE_SHAPE(q, Storage, N, M, K) \
* malloc_block_QueueDefinition(q) &*& \
* q->pcHead |-> Storage &*& \
* q->pcWriteTo |-> ?WPtr &*& \
* q->u.xQueue.pcTail |-> ?End &*& \
* q->u.xQueue.pcReadFrom |-> ?RPtr &*& \
* q->uxItemSize |-> M &*& \
* q->uxLength |-> N &*& \
* q->uxMessagesWaiting |-> K &*& \
* q->cRxLock |-> ?rxLock &*& \
* q->cTxLock |-> ?txLock &*& \
* struct_QueuePointers_padding(&q->u.xQueue) &*& \
* struct_SemaphoreData_padding(&q->u.xSemaphore) &*& \
* struct_fake_union_t_padding(&q->u) &*& \
* struct_xLIST_padding(&q->xTasksWaitingToSend) &*& \
* struct_xLIST_padding(&q->xTasksWaitingToReceive) &*& \
* q->u.xSemaphore.xMutexHolder |-> _ &*& \
* q->u.xSemaphore.uxRecursiveCallCount |-> _ &*& \
* true
*
* predicate queue(QueueHandle_t q, int8_t *Storage, size_t N, size_t M, size_t W, size_t R, size_t K, bool is_locked; list<list<char> >abs) =
* QUEUE_SHAPE(q, Storage, N, M, K) &*&
* 0 < N &*&
* 0 < M &*&
* 0 <= W &*& W < N &*&
* 0 <= R &*& R < N &*&
* 0 <= K &*& K <= N &*&
* W == (R + 1 + K) % N &*&
* (-1) <= rxLock &*&
* (-1) <= txLock &*&
* (is_locked ? 0 <= rxLock : (-1) == rxLock) &*&
* (is_locked ? 0 <= txLock : (-1) == txLock) &*&
* WPtr == Storage + (W*M) &*&
* RPtr == Storage + (R*M) &*&
* End == Storage + (N*M) &*&
* buffer(Storage, N, M, ?contents) &*&
* length(contents) == N &*&
* abs == take(K, rotate_left((R+1)%N, contents)) &*&
* malloc_block(Storage, N*M) &*&
* true
* ;
* @*/
malloc_block_QueueDefinition(q) &*& \
q->pcHead |-> Storage &*& \
q->pcWriteTo |-> ?WPtr &*& \
q->u.xQueue.pcTail |-> ?End &*& \
q->u.xQueue.pcReadFrom |-> ?RPtr &*& \
q->uxItemSize |-> M &*& \
q->uxLength |-> N &*& \
q->uxMessagesWaiting |-> K &*& \
q->cRxLock |-> ?rxLock &*& \
q->cTxLock |-> ?txLock &*& \
struct_QueuePointers_padding(&q->u.xQueue) &*& \
struct_SemaphoreData_padding(&q->u.xSemaphore) &*& \
struct_fake_union_t_padding(&q->u) &*& \
struct_xLIST_padding(&q->xTasksWaitingToSend) &*& \
struct_xLIST_padding(&q->xTasksWaitingToReceive) &*& \
q->u.xSemaphore.xMutexHolder |-> _ &*& \
q->u.xSemaphore.uxRecursiveCallCount |-> _ &*& \
true
predicate queue(QueueHandle_t q, int8_t *Storage, size_t N, size_t M, size_t W, size_t R, size_t K, bool is_locked; list<list<char> >abs) =
QUEUE_SHAPE(q, Storage, N, M, K) &*&
0 < N &*&
0 < M &*&
0 <= W &*& W < N &*&
0 <= R &*& R < N &*&
0 <= K &*& K <= N &*&
W == (R + 1 + K) % N &*&
(-1) <= rxLock &*&
(-1) <= txLock &*&
(is_locked ? 0 <= rxLock : (-1) == rxLock) &*&
(is_locked ? 0 <= txLock : (-1) == txLock) &*&
WPtr == Storage + (W*M) &*&
RPtr == Storage + (R*M) &*&
End == Storage + (N*M) &*&
buffer(Storage, N, M, ?contents) &*&
length(contents) == N &*&
abs == take(K, rotate_left((R+1)%N, contents)) &*&
malloc_block(Storage, N*M) &*&
true
;
@*/
/* A buffer allows us to interpret a flat character array of `N*M` bytes as a
* list of `N` elements where each element is `M` bytes */
list of `N` elements where each element is `M` bytes */
/*@
* predicate buffer(char *buffer, size_t N, size_t M; list<list<char> > elements) =
* N == 0
* ? elements == nil
* : chars(buffer, M, ?x) &*& buffer(buffer + M, N - 1, M, ?xs) &*& elements == cons(x, xs);
*
* lemma void buffer_length(char *buffer, size_t N, size_t M)
* requires buffer(buffer, N, M, ?elements);
* ensures buffer(buffer, N, M, elements) &*& length(elements) == N;
* {
* if (N == 0) {
* open buffer(buffer, N, M, elements);
* close buffer(buffer, N, M, elements);
* } else {
* open buffer(buffer, N, M, elements);
* buffer_length(buffer+M, N-1, M);
* }
* }
* @*/
predicate buffer(char *buffer, size_t N, size_t M; list<list<char> > elements) =
N == 0
? elements == nil
: chars(buffer, M, ?x) &*& buffer(buffer + M, N - 1, M, ?xs) &*& elements == cons(x, xs);
lemma void buffer_length(char *buffer, size_t N, size_t M)
requires buffer(buffer, N, M, ?elements);
ensures buffer(buffer, N, M, elements) &*& length(elements) == N;
{
if (N == 0) {
open buffer(buffer, N, M, elements);
close buffer(buffer, N, M, elements);
} else {
open buffer(buffer, N, M, elements);
buffer_length(buffer+M, N-1, M);
}
}
@*/
/*
* There is no need in the queue proofs to preserve a relationship between `cs`
* and `elements` (i.e., `flatten(elements) == cs`) because we only move in one
* direction from `cs` to `elements` during queue creation when the contents is
* fresh from `malloc` (i.e., uninitialized). If we needed to do a roundtrip from
* elements back to cs then this would require a stronger lemma.
There is no need in the queue proofs to preserve a relationship between `cs`
and `elements` (i.e., `flatten(elements) == cs`) because we only move in one
direction from `cs` to `elements` during queue creation when the contents is
fresh from `malloc` (i.e., uninitialized). If we needed to do a roundtrip from
elements back to cs then this would require a stronger lemma.
*/
/*@
* lemma void buffer_from_chars(char *buffer, size_t N, size_t M)
* requires chars(buffer, N*M, ?cs) &*& 0 <= N &*& 0 < M;
* ensures exists<list<list<char> > >(?elements) &*& buffer(buffer, N, M, elements) &*& length(elements) == N;
* {
* if (N == 0) {
* close exists(nil);
* } else {
* int i = 0;
* while (i < N)
* invariant 0 <= i &*& i <= N &*&
* chars(buffer, (N-i)*M, ?xs) &*& xs == take((N-i)*M, cs) &*&
* buffer(buffer + (N-i)*M, i, M, ?ys);
* decreases N-i;
* {
* mul_mono_l(0, N-i-1, M);
* chars_split(buffer, (N-i-1)*M);
* mul_mono_l(i, N, M);
* mul_mono_l(N-i, N, M);
* take_take((N-i-1)*M, (N-i)*M, cs);
* i++;
* }
* close exists(ys);
* buffer_length(buffer, N, M);
* }
* }
*
* lemma void append_buffer(char *buffer, size_t N1, size_t N2, size_t M)
* requires
* buffer(buffer, N1, M, ?elements1) &*&
* buffer(buffer + N1 * M, N2, M, ?elements2) &*&
* 0 <= N1 &*& 0 <= N2;
* ensures buffer(buffer, N1+N2, M, append(elements1, elements2));
* {
* if (N1 == 0) {
* open buffer(buffer, 0, M, _);
* } else if (N2 == 0) {
* open buffer(buffer + N1 * M, 0, M, _);
* } else {
* open buffer(buffer, N1, M, elements1);
* append_buffer(buffer + M, N1-1, N2, M);
* close buffer(buffer, N1+N2, M, cons(?x, append(xs, elements2)));
* }
* }
*
* lemma void split_element<t>(char *buffer, size_t N, size_t M, size_t i)
* requires buffer(buffer, N, M, ?elements) &*& 0 <= i &*& i < N;
* ensures
* buffer(buffer, i, M, take(i, elements)) &*&
* chars(buffer + i * M, M, nth(i, elements)) &*&
* buffer(buffer + (i + 1) * M, (N-1-i), M, drop(i+1, elements));
* {
* if (i == 0) {
* // straightforward
* } else {
* buffer_length(buffer, N, M);
* int j = 0;
* while (j < i)
* invariant 0 <= j &*& j <= i &*&
* buffer(buffer, j, M, take(j, elements)) &*&
* buffer(buffer + j * M, N-j, M, drop(j, elements));
* decreases i-j;
* {
* drop_drop(1, j, elements);
* nth_drop2(elements, j);
* open buffer(buffer + j * M, N-j, M, drop(j, elements));
* assert chars(buffer + j * M, M, ?x) &*& x == nth(j, elements);
* close buffer(buffer + j * M, 1, M, singleton(x));
* append_buffer(buffer, j, 1, M);
* take_plus_one(j, elements);
* j++;
* }
* drop_drop(1, j, elements);
* nth_drop2(elements, i);
* }
* }
*
* lemma void join_element(char *buffer, size_t N, size_t M, size_t i)
* requires
* 0 <= i &*& i < N &*&
* buffer(buffer, i, M, ?prefix) &*&
* chars(buffer + i * M, M, ?element) &*&
* buffer(buffer + (i + 1) * M, (N-1-i), M, ?suffix);
* ensures buffer(buffer, N, M, append(prefix, cons(element, suffix)));
* {
* if (i == 0) {
* open buffer(buffer, i, M, prefix);
* assert prefix == nil;
* close buffer(buffer, N, M, cons(element, suffix));
* } else {
* close buffer(buffer + i * M, N-i, M, cons(element, suffix));
* append_buffer(buffer, i, N-i, M);
* }
* }
*
* predicate list(List_t *l;) =
* l->uxNumberOfItems |-> _;
*
* predicate queuelists(QueueHandle_t q;) =
* list(&q->xTasksWaitingToSend) &*&
* list(&q->xTasksWaitingToReceive);
* @*/
lemma void buffer_from_chars(char *buffer, size_t N, size_t M)
requires chars(buffer, N*M, ?cs) &*& 0 <= N &*& 0 < M;
ensures exists<list<list<char> > >(?elements) &*& buffer(buffer, N, M, elements) &*& length(elements) == N;
{
if (N == 0) {
close exists(nil);
} else {
int i = 0;
while (i < N)
invariant 0 <= i &*& i <= N &*&
chars(buffer, (N-i)*M, ?xs) &*& xs == take((N-i)*M, cs) &*&
buffer(buffer + (N-i)*M, i, M, ?ys);
decreases N-i;
{
mul_mono_l(0, N-i-1, M);
chars_split(buffer, (N-i-1)*M);
mul_mono_l(i, N, M);
mul_mono_l(N-i, N, M);
take_take((N-i-1)*M, (N-i)*M, cs);
i++;
}
close exists(ys);
buffer_length(buffer, N, M);
}
}
lemma void append_buffer(char *buffer, size_t N1, size_t N2, size_t M)
requires
buffer(buffer, N1, M, ?elements1) &*&
buffer(buffer + N1 * M, N2, M, ?elements2) &*&
0 <= N1 &*& 0 <= N2;
ensures buffer(buffer, N1+N2, M, append(elements1, elements2));
{
if (N1 == 0) {
open buffer(buffer, 0, M, _);
} else if (N2 == 0) {
open buffer(buffer + N1 * M, 0, M, _);
} else {
open buffer(buffer, N1, M, elements1);
append_buffer(buffer + M, N1-1, N2, M);
close buffer(buffer, N1+N2, M, cons(?x, append(xs, elements2)));
}
}
lemma void split_element<t>(char *buffer, size_t N, size_t M, size_t i)
requires buffer(buffer, N, M, ?elements) &*& 0 <= i &*& i < N;
ensures
buffer(buffer, i, M, take(i, elements)) &*&
chars(buffer + i * M, M, nth(i, elements)) &*&
buffer(buffer + (i + 1) * M, (N-1-i), M, drop(i+1, elements));
{
if (i == 0) {
// straightforward
} else {
buffer_length(buffer, N, M);
int j = 0;
while (j < i)
invariant 0 <= j &*& j <= i &*&
buffer(buffer, j, M, take(j, elements)) &*&
buffer(buffer + j * M, N-j, M, drop(j, elements));
decreases i-j;
{
drop_drop(1, j, elements);
nth_drop2(elements, j);
open buffer(buffer + j * M, N-j, M, drop(j, elements));
assert chars(buffer + j * M, M, ?x) &*& x == nth(j, elements);
close buffer(buffer + j * M, 1, M, singleton(x));
append_buffer(buffer, j, 1, M);
take_plus_one(j, elements);
j++;
}
drop_drop(1, j, elements);
nth_drop2(elements, i);
}
}
lemma void join_element(char *buffer, size_t N, size_t M, size_t i)
requires
0 <= i &*& i < N &*&
buffer(buffer, i, M, ?prefix) &*&
chars(buffer + i * M, M, ?element) &*&
buffer(buffer + (i + 1) * M, (N-1-i), M, ?suffix);
ensures buffer(buffer, N, M, append(prefix, cons(element, suffix)));
{
if (i == 0) {
open buffer(buffer, i, M, prefix);
assert prefix == nil;
close buffer(buffer, N, M, cons(element, suffix));
} else {
close buffer(buffer + i * M, N-i, M, cons(element, suffix));
append_buffer(buffer, i, N-i, M);
}
}
predicate list(List_t *l;) =
l->uxNumberOfItems |-> _;
predicate queuelists(QueueHandle_t q;) =
list(&q->xTasksWaitingToSend) &*&
list(&q->xTasksWaitingToReceive);
@*/
/* Because prvCopyDataFromQueue does *not* decrement uxMessagesWaiting (K) the
* queue predicate above does not hold as a postcondition. If the caller
* subsequently decrements K then the queue predicate can be reinstated. */
queue predicate above does not hold as a postcondition. If the caller
subsequently decrements K then the queue predicate can be reinstated. */
/*@
* predicate queue_after_prvCopyDataFromQueue(QueueHandle_t q, int8_t *Storage, size_t N, size_t M, size_t W, size_t R, size_t K, bool is_locked; list<list<char> >abs) =
* QUEUE_SHAPE(q, Storage, N, M, K) &*&
* 0 < N &*&
* 0 < M &*&
* 0 <= W &*& W < N &*&
* 0 <= R &*& R < N &*&
* 0 <= K &*& K <= N &*&
* W == (R + K) % N &*& //< Differs from queue predicate
* (-1) <= rxLock &*&
* (-1) <= txLock &*&
* (is_locked ? 0 <= rxLock : (-1) == rxLock) &*&
* (is_locked ? 0 <= txLock : (-1) == txLock) &*&
* WPtr == Storage + (W*M) &*&
* RPtr == Storage + (R*M) &*&
* End == Storage + (N*M) &*&
* buffer(Storage, N, M, ?contents) &*&
* length(contents) == N &*&
* abs == take(K, rotate_left(R, contents)) &*& //< Differs from queue predicate
* malloc_block(Storage, N*M) &*&
* true
* ;
* @*/
predicate queue_after_prvCopyDataFromQueue(QueueHandle_t q, int8_t *Storage, size_t N, size_t M, size_t W, size_t R, size_t K, bool is_locked; list<list<char> >abs) =
QUEUE_SHAPE(q, Storage, N, M, K) &*&
0 < N &*&
0 < M &*&
0 <= W &*& W < N &*&
0 <= R &*& R < N &*&
0 <= K &*& K <= N &*&
W == (R + K) % N &*& //< Differs from queue predicate
(-1) <= rxLock &*&
(-1) <= txLock &*&
(is_locked ? 0 <= rxLock : (-1) == rxLock) &*&
(is_locked ? 0 <= txLock : (-1) == txLock) &*&
WPtr == Storage + (W*M) &*&
RPtr == Storage + (R*M) &*&
End == Storage + (N*M) &*&
buffer(Storage, N, M, ?contents) &*&
length(contents) == N &*&
abs == take(K, rotate_left(R, contents)) &*& //< Differs from queue predicate
malloc_block(Storage, N*M) &*&
true
;
@*/
/* Can't be called `mutex` as this clashes with VeriFast's predicate */
/*@
* predicate freertos_mutex(QueueHandle_t q, int8_t *Storage, size_t N, size_t K;) =
* QUEUE_SHAPE(q, Storage, N, 0, K) &*&
* queuelists(q) &*&
* 0 < N &*&
* 0 <= K &*& K <= N &*&
* (-1) <= rxLock &*&
* (-1) <= txLock &*&
* WPtr == Storage &*&
* RPtr == Storage &*&
* End == Storage &*&
* malloc_block(Storage, 0) &*&
* chars(Storage, 0, _) &*&
* true
* ;
* @*/
predicate freertos_mutex(QueueHandle_t q, int8_t *Storage, size_t N, size_t K;) =
QUEUE_SHAPE(q, Storage, N, 0, K) &*&
queuelists(q) &*&
0 < N &*&
0 <= K &*& K <= N &*&
(-1) <= rxLock &*&
(-1) <= txLock &*&
WPtr == Storage &*&
RPtr == Storage &*&
End == Storage &*&
malloc_block(Storage, 0) &*&
chars(Storage, 0, _) &*&
true
;
@*/
/* A queuehandle can be shared between tasks and ISRs. Acquiring the ghost
* `irqMask` gives access to the core queue resources. The permissions granted
* after masking interrupts depends on the caller:
* - A task has access to the queue and the queuelists
* - An ISR has access to the queue and, if the queue is unlocked, the queuelists */
`irqMask` gives access to the core queue resources. The permissions granted
after masking interrupts depends on the caller:
- A task has access to the queue and the queuelists
- An ISR has access to the queue and, if the queue is unlocked, the queuelists */
/*@
* predicate queuehandle(QueueHandle_t q, size_t N, size_t M, bool is_isr;) =
* q->irqMask |-> ?m &*& mutex(m, irqs_masked_invariant(q, N, M, is_isr));
*
* predicate_ctor irqs_masked_invariant(QueueHandle_t queue, size_t N, size_t M, bool is_isr)() =
* queue(queue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* (is_isr && is_locked ? true : queuelists(queue));
* @*/
predicate queuehandle(QueueHandle_t q, size_t N, size_t M, bool is_isr;) =
q->irqMask |-> ?m &*& mutex(m, irqs_masked_invariant(q, N, M, is_isr));
predicate_ctor irqs_masked_invariant(QueueHandle_t queue, size_t N, size_t M, bool is_isr)() =
queue(queue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
(is_isr && is_locked ? true : queuelists(queue));
@*/
/* A queuesuspend can be shared between tasks. Acquiring the ghost `schedulerSuspend` gives access to the `locked` mutex. */
/*@
* predicate_ctor scheduler_suspended_invariant(QueueHandle_t queue)() =
* queue->locked |-> ?m &*&
* mutex(m, queue_locked_invariant(queue));
*
* predicate queuesuspend(QueueHandle_t q;) =
* q->schedulerSuspend |-> ?m &*&
* mutex(m, scheduler_suspended_invariant(q));
* @*/
predicate_ctor scheduler_suspended_invariant(QueueHandle_t queue)() =
queue->locked |-> ?m &*&
mutex(m, queue_locked_invariant(queue));
predicate queuesuspend(QueueHandle_t q;) =
q->schedulerSuspend |-> ?m &*&
mutex(m, scheduler_suspended_invariant(q));
@*/
/* A queuelock is exclusively acquired by a task. Acquiring the ghost `queuelock` gives access to the queue list resources. */
/*@
* predicate queuelock(QueueHandle_t q;) =
* q->locked |-> ?m &*&
* mutex(m, queue_locked_invariant(q));
*
* predicate_ctor queue_locked_invariant(QueueHandle_t queue)() =
* queuelists(queue);
* @*/
predicate queuelock(QueueHandle_t q;) =
q->locked |-> ?m &*&
mutex(m, queue_locked_invariant(q));
predicate_ctor queue_locked_invariant(QueueHandle_t queue)() =
queuelists(queue);
@*/
BaseType_t vListInitialise(List_t *list);
/*@requires list(list);@*/
@ -442,18 +435,17 @@ typedef struct xTIME_OUT
} TimeOut_t;
/*@
* predicate xTIME_OUT(struct xTIME_OUT *to;) =
* to->xOverflowCount |-> _ &*&
* to->xTimeOnEntering |-> _ &*&
* struct_xTIME_OUT_padding(to);
* @*/
predicate xTIME_OUT(struct xTIME_OUT *to;) =
to->xOverflowCount |-> _ &*&
to->xTimeOnEntering |-> _ &*&
struct_xTIME_OUT_padding(to);
@*/
void vTaskInternalSetTimeOutState( TimeOut_t * x);
/*@requires xTIME_OUT(x);@*/
/*@ensures xTIME_OUT(x);@*/
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut,
TickType_t * const pxTicksToWait );
BaseType_t xTaskCheckForTimeOut( TimeOut_t * const pxTimeOut, TickType_t * const pxTicksToWait );
/*@requires xTIME_OUT(pxTimeOut) &*& u_integer(pxTicksToWait, _);@*/
/*@ensures xTIME_OUT(pxTimeOut) &*& u_integer(pxTicksToWait, _);@*/
@ -461,8 +453,7 @@ BaseType_t xTaskRemoveFromEventList( List_t * list );
/*@requires list(list);@*/
/*@ensures list(list);@*/
void vTaskPlaceOnEventList( List_t * const pxEventList,
const TickType_t xTicksToWait );
void vTaskPlaceOnEventList( List_t * const pxEventList, const TickType_t xTicksToWait );
/*@requires list(pxEventList);@*/
/*@ensures list(pxEventList);@*/
@ -471,54 +462,45 @@ void vTaskMissedYield();
/*@ensures true;@*/
void vTaskSuspendAll();
/*@requires exists<QueueHandle_t>(?xQueue) &*&
* [1/2]xQueue->schedulerSuspend |-> ?m &*&
* [1/2]mutex(m, scheduler_suspended_invariant(xQueue));@*/
[1/2]xQueue->schedulerSuspend |-> ?m &*&
[1/2]mutex(m, scheduler_suspended_invariant(xQueue));@*/
/*@ensures [1/2]xQueue->schedulerSuspend |-> m &*&
* mutex_held(m, scheduler_suspended_invariant(xQueue), currentThread, 1/2) &*&
* xQueue->locked |-> ?m2 &*&
* mutex(m2, queue_locked_invariant(xQueue));@*/
mutex_held(m, scheduler_suspended_invariant(xQueue), currentThread, 1/2) &*&
xQueue->locked |-> ?m2 &*&
mutex(m2, queue_locked_invariant(xQueue));@*/
BaseType_t xTaskResumeAll( void );
/*@requires exists<QueueHandle_t>(?xQueue) &*&
* [1/2]xQueue->schedulerSuspend |-> ?m &*&
* mutex_held(m, scheduler_suspended_invariant(xQueue), currentThread, 1/2) &*&
* xQueue->locked |-> ?m2 &*&
* mutex(m2, queue_locked_invariant(xQueue));@*/
[1/2]xQueue->schedulerSuspend |-> ?m &*&
mutex_held(m, scheduler_suspended_invariant(xQueue), currentThread, 1/2) &*&
xQueue->locked |-> ?m2 &*&
mutex(m2, queue_locked_invariant(xQueue));@*/
/*@ensures [1/2]xQueue->schedulerSuspend |-> m &*&
* [1/2]mutex(m, scheduler_suspended_invariant(xQueue));@*/
[1/2]mutex(m, scheduler_suspended_invariant(xQueue));@*/
void prvLockQueue( QueueHandle_t xQueue );
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]queuelock(xQueue); @*/
[1/2]queuelock(xQueue); @*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]xQueue->locked |-> ?m &*&
* mutex_held(m, queue_locked_invariant(xQueue), currentThread, 1/2) &*&
* queue_locked_invariant(xQueue)();@*/
[1/2]xQueue->locked |-> ?m &*&
mutex_held(m, queue_locked_invariant(xQueue), currentThread, 1/2) &*&
queue_locked_invariant(xQueue)();@*/
void prvUnlockQueue( QueueHandle_t xQueue );
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]xQueue->locked |-> ?m &*&
* mutex_held(m, queue_locked_invariant(xQueue), currentThread, 1/2) &*&
* queue_locked_invariant(xQueue)();@*/
[1/2]xQueue->locked |-> ?m &*&
mutex_held(m, queue_locked_invariant(xQueue), currentThread, 1/2) &*&
queue_locked_invariant(xQueue)();@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuelock(xQueue);@*/
[1/2]queuelock(xQueue);@*/
void setInterruptMask(QueueHandle_t xQueue)
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false;@*/
/*@ensures [1/2]xQueue->irqMask |-> ?m &*&
* mutex_held(m, irqs_masked_invariant(xQueue, N, M, is_isr), currentThread, 1/2) &*&
* queue(xQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* queuelists(xQueue);@*/
mutex_held(m, irqs_masked_invariant(xQueue, N, M, is_isr), currentThread, 1/2) &*&
queue(xQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
queuelists(xQueue);@*/
{
/*@open queuehandle(xQueue, N, M, is_isr);@*/
mutex_acquire(xQueue->irqMask);
@ -526,11 +508,10 @@ void setInterruptMask( QueueHandle_t xQueue )
}
void clearInterruptMask(QueueHandle_t xQueue)
/*@requires queue(xQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* [1/2]xQueue->irqMask |-> ?m &*&
* mutex_held(m, irqs_masked_invariant(xQueue, N, M, false), currentThread, 1/2) &*&
* queuelists(xQueue);@*/
[1/2]xQueue->irqMask |-> ?m &*&
mutex_held(m, irqs_masked_invariant(xQueue, N, M, false), currentThread, 1/2) &*&
queuelists(xQueue);@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, false);@*/
{
/*@close irqs_masked_invariant(xQueue, N, M, false)();@*/
@ -545,11 +526,10 @@ void clearInterruptMask( QueueHandle_t xQueue )
UBaseType_t setInterruptMaskFromISR(QueueHandle_t xQueue)
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == true;@*/
/*@ensures [1/2]xQueue->irqMask |-> ?m &*&
* mutex_held(m, irqs_masked_invariant(xQueue, N, M, is_isr), currentThread, 1/2) &*&
* queue(xQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* (is_locked ? true : queuelists(xQueue));@*/
mutex_held(m, irqs_masked_invariant(xQueue, N, M, is_isr), currentThread, 1/2) &*&
queue(xQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
(is_locked ? true : queuelists(xQueue));@*/
{
/*@open queuehandle(xQueue, N, M, is_isr);@*/
mutex_acquire(xQueue->irqMask);
@ -557,13 +537,11 @@ UBaseType_t setInterruptMaskFromISR( QueueHandle_t xQueue )
return 0;
}
void clearInterruptMaskFromISR( QueueHandle_t xQueue,
UBaseType_t uxSavedInterruptStatus )
void clearInterruptMaskFromISR(QueueHandle_t xQueue, UBaseType_t uxSavedInterruptStatus)
/*@requires queue(xQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* [1/2]xQueue->irqMask |-> ?m &*&
* mutex_held(m, irqs_masked_invariant(xQueue, N, M, true), currentThread, 1/2) &*&
* (is_locked ? true : queuelists(xQueue));@*/
[1/2]xQueue->irqMask |-> ?m &*&
mutex_held(m, irqs_masked_invariant(xQueue, N, M, true), currentThread, 1/2) &*&
(is_locked ? true : queuelists(xQueue));@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, true);@*/
{
/*@close irqs_masked_invariant(xQueue, N, M, true)();@*/
@ -575,3 +553,5 @@ void clearInterruptMaskFromISR( QueueHandle_t xQueue,
#define portCLEAR_INTERRUPT_MASK_FROM_ISR(uxSavedInterruptStatus) clearInterruptMaskFromISR(xQueue, uxSavedInterruptStatus)
#endif /* QUEUE_H */
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,37 +24,33 @@
*
*/
/* *INDENT-OFF* */
#ifndef QUEUECONTRACTS_H
#define QUEUECONTRACTS_H
#include "queue.h"
void prvCopyDataFromQueue( Queue_t * const pxQueue,
void * const pvBuffer );
void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer );
/*@requires queue(pxQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*& 0 < K &*& chars(pvBuffer, M, _);@*/
/*@ensures queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs) &*&
* chars(pvBuffer, M, head(abs));@*/
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
const void * pvItemToQueue,
const BaseType_t xPosition );
chars(pvBuffer, M, head(abs));@*/
BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue, const void *pvItemToQueue, const BaseType_t xPosition );
/*@requires queue(pxQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* (K < N || xPosition == queueOVERWRITE) &*&
* chars(pvItemToQueue, M, ?x) &*&
* (xPosition == queueSEND_TO_BACK || xPosition == queueSEND_TO_FRONT || (xPosition == queueOVERWRITE && N == 1));@*/
(K < N || xPosition == queueOVERWRITE) &*&
chars(pvItemToQueue, M, ?x) &*&
(xPosition == queueSEND_TO_BACK || xPosition == queueSEND_TO_FRONT || (xPosition == queueOVERWRITE && N == 1));@*/
/*@ensures
* (xPosition == queueSEND_TO_BACK
* ? queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)))
* : (xPosition == queueSEND_TO_FRONT
* ? (R == 0
* ? queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs))
* : queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs)))
* : xPosition == queueOVERWRITE &*& queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x)))
* ) &*&
* chars(pvItemToQueue, M, x);@*/
(xPosition == queueSEND_TO_BACK
? queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)))
: (xPosition == queueSEND_TO_FRONT
? (R == 0
? queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs))
: queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs)))
: xPosition == queueOVERWRITE &*& queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x)))
) &*&
chars(pvItemToQueue, M, x);@*/
BaseType_t prvIsQueueEmpty( Queue_t * pxQueue );
/*@requires [1/2]queuehandle(pxQueue, ?N, ?M, ?is_isr) &*& is_isr == false;@*/
@ -65,3 +61,5 @@ BaseType_t prvIsQueueFull( Queue_t * pxQueue );
/*@ensures [1/2]queuehandle(pxQueue, N, M, is_isr);@*/
#endif /* QUEUECONTRACTS_H */
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/list.h"
/* Wrap the macro in a function call so we can give a function contract */
@ -31,11 +33,12 @@
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); @*/
result == ((len == 0) ? pdTRUE : pdFALSE); @*/
{
/*@open xLIST(pxList, len, _, _, _, _);@*/
return listLIST_IS_EMPTY( pxList );
/*@close xLIST(pxList, len, _, _, cells, vals);@*/
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,21 +24,21 @@
*
*/
/* *INDENT-OFF* */
#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;@*/
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));@*/
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;@*/
@ -50,7 +50,7 @@ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
/*@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 */
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);@*/
@ -63,97 +63,96 @@ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
/*@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);
* }
* }
* @*/
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);@*/
@ -187,105 +186,101 @@ UBaseType_t uxListRemove( ListItem_t * const pxItemToRemove )
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));
* }
* }
* }
* @*/
// 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)));
* }
* @*/
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));@*/
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);@*/
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 );
@ -293,22 +288,19 @@ ListItem_t * client_example( List_t * l )
}
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)));@*/
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(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 );
@ -318,3 +310,5 @@ void client_example2( List_t * l )
/*@close exists(l);@*/
uxListRemove( index );
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,19 +24,21 @@
*
*/
/* *INDENT-OFF* */
#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);
* @*/
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);@*/
@ -49,6 +51,8 @@ void vListInitialise( List_t * const pxList )
* 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. */
listSET_FIRST_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
/* 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;
@ -58,6 +62,15 @@ void vListInitialise( List_t * const pxList )
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. */
/* Initialize the remaining fields of xListEnd when it is a proper ListItem_t */
#if ( configUSE_MINI_LIST_ITEM == 0 )
{
pxList->xListEnd.pvOwner = NULL;
pxList->xListEnd.pxContainer = NULL;
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( &( pxList->xListEnd ) );
}
#endif
pxList->uxNumberOfItems = ( UBaseType_t ) 0U;
/* Write known values into the list if
@ -73,3 +86,5 @@ void vListInitialise( List_t * const pxList )
/*@close DLS(end, end, end, end, singleton(end), singleton(portMAX_DELAY), pxList);@*/
/*@close xLIST(pxList, 0, end, end, singleton(end), singleton(portMAX_DELAY));@*/
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/list.h"
void vListInitialiseItem( ListItem_t * const pxItem )
@ -39,3 +41,5 @@ void vListInitialiseItem( ListItem_t * const pxItem )
listSET_SECOND_LIST_ITEM_INTEGRITY_CHECK_VALUE( pxItem );
/*@close xLIST_ITEM(pxItem, _, _, _, NULL);@*/
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,24 +24,23 @@
*
*/
/* *INDENT-OFF* */
#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;@*/
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, _, _, _);@*/
xLIST_ITEM(pxNewListItem, ?val, _, _, _);@*/
/*@ensures xLIST(pxList, len+1, idx, end, ?new_cells, ?new_vals) &*&
* remove(pxNewListItem, new_cells) == cells
* ;@*/
remove(pxNewListItem, new_cells) == cells
;@*/
{
/*@xLIST_star_item(pxList, pxNewListItem);@*/
/*@open xLIST_ITEM(pxNewListItem, _, _, _, _);@*/
@ -68,24 +67,23 @@ void vListInsert( List_t * const pxList,
{
/*@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, _, _, _, _);
* }
* @*/
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
@ -110,6 +108,9 @@ void vListInsert( List_t * const pxList,
* 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?).
* 5) If the FreeRTOS port supports interrupt nesting then ensure that
* the priority of the tick interrupt is at or below
* configMAX_SYSCALL_INTERRUPT_PRIORITY.
**********************************************************************/
#ifdef VERIFAST /*< ***over-approximate list insert loop*** */
@ -122,43 +123,42 @@ void vListInsert( List_t * const pxList,
}
#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, _);
* }
* }@*/
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;
@ -174,153 +174,154 @@ void vListInsert( List_t * const pxList,
/*@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))));
* }
* }
* }@*/
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))));
}
}
}@*/
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,20 +24,20 @@
*
*/
/* *INDENT-OFF* */
#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, _, _, _);@*/
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))));@*/
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;@*/
@ -58,63 +58,62 @@ void vListInsertEnd( List_t * const pxList,
/*@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), _, _, _);
* }
* }
* @*/
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
@ -134,111 +133,110 @@ void vListInsertEnd( List_t * const 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);
* }
* @*/
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));
}
void client_example1( List_t * const l,
ListItem_t * const pxNewListItem )
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;@*/
xLIST(l, ?len, ?idx, ?end, ?cells, ?vals) &*&
xLIST_ITEM(pxNewListItem, ?val, _, _, _) &*&
idx == end;@*/
/*@ensures
* xLIST(l, len + 1, idx, end, _, append(vals, singleton(val)));@*/
xLIST(l, len + 1, idx, end, _, append(vals, singleton(val)));@*/
{
vListInsertEnd(l, pxNewListItem);
}
/* *INDENT-ON* */

View file

@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
/* Simplifying assumption: we do not verify queue initialisation in a
@ -37,31 +39,29 @@
/* The following intermediate queue predicates summarise states used by queue
* initialization but not used elsewhere so we confine them to these proofs
* locally. */
/*@
* predicate queue_init1(QueueHandle_t q;) =
* QUEUE_SHAPE(q, _, _, _, _) &*&
* queuelists(q)
* ;
*
* predicate queue_init2(QueueHandle_t q, int8_t *Storage, size_t N, size_t M;) =
* QUEUE_SHAPE(q, Storage, N, M, _) &*&
* queuelists(q) &*&
* 0 < N &*&
* chars(Storage, (N*M), _) &*&
* malloc_block(Storage, N*M) &*&
* Storage + N * M <= (int8_t *)UINTPTR_MAX &*&
* true
* ;
* @*/
predicate queue_init1(QueueHandle_t q;) =
QUEUE_SHAPE(q, _, _, _, _) &*&
queuelists(q)
;
predicate queue_init2(QueueHandle_t q, int8_t *Storage, size_t N, size_t M;) =
QUEUE_SHAPE(q, Storage, N, M, _) &*&
queuelists(q) &*&
0 < N &*&
chars(Storage, (N*M), _) &*&
malloc_block(Storage, N*M) &*&
Storage + N * M <= (int8_t *)UINTPTR_MAX &*&
true
;
@*/
BaseType_t xQueueGenericReset( QueueHandle_t xQueue,
BaseType_t xNewQueue )
/*@requires queue_init2(xQueue, ?Storage, ?N, ?M);@*/
/*@ensures 0 == M
* ? freertos_mutex(xQueue, Storage, N, 0)
* : queue(xQueue, Storage, N, M, 0, (N-1), 0, false, nil) &*& queuelists(xQueue);@*/
? freertos_mutex(xQueue, Storage, N, 0)
: queue(xQueue, Storage, N, M, 0, (N-1), 0, false, nil) &*& queuelists(xQueue);@*/
{
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
@ -127,16 +127,14 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
Queue_t * pxNewQueue )
/*@requires queue_init1(pxNewQueue) &*&
* 0 < uxQueueLength &*& 0 < uxItemSize &*&
* malloc_block(pucQueueStorage, uxQueueLength * uxItemSize) &*&
* pucQueueStorage + uxQueueLength * uxItemSize <= (uint8_t *)UINTPTR_MAX &*&
* uchars(pucQueueStorage, uxQueueLength * uxItemSize,_);@*/
0 < uxQueueLength &*& 0 < uxItemSize &*&
malloc_block(pucQueueStorage, uxQueueLength * uxItemSize) &*&
pucQueueStorage + uxQueueLength * uxItemSize <= (uint8_t *)UINTPTR_MAX &*&
uchars(pucQueueStorage, uxQueueLength * uxItemSize,_);@*/
/*@ensures queue(pxNewQueue, ((int8_t *)(void *)pucQueueStorage), uxQueueLength, uxItemSize, 0, (uxQueueLength-1), 0, false, nil) &*&
* queuelists(pxNewQueue);@*/
queuelists(pxNewQueue);@*/
{
#ifndef VERIFAST /*< void cast of unused var */
/* Remove compiler warnings about unused parameters should
* configUSE_TRACE_FACILITY not be set to 1. */
( void ) ucQueueType;
@ -190,45 +188,45 @@ static void prvInitialiseNewQueue( const UBaseType_t uxQueueLength,
traceQUEUE_CREATE( pxNewQueue );
}
#define SIZE_MAX ( ( size_t ) -1 )
QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
const UBaseType_t uxItemSize,
const uint8_t ucQueueType )
/*@requires 0 < uxQueueLength &*&
* 0 < uxItemSize &*&
* 0 < uxQueueLength * uxItemSize &*&
* uxQueueLength * uxItemSize <= UINT_MAX;@*/
0 < uxItemSize &*&
0 < uxQueueLength * uxItemSize &*&
uxQueueLength * uxItemSize <= UINT_MAX;@*/
/*@ensures result == NULL
* ? true
* : queue(result, _, uxQueueLength, uxItemSize, 0, (uxQueueLength-1), 0, false, nil) &*&
* queuelists(result) &*&
* result->irqMask |-> _ &*&
* result->schedulerSuspend |-> _ &*&
* result->locked |-> _;@*/
? true
: queue(result, _, uxQueueLength, uxItemSize, 0, (uxQueueLength-1), 0, false, nil) &*&
queuelists(result) &*&
result->irqMask |-> _ &*&
result->schedulerSuspend |-> _ &*&
result->locked |-> _;@*/
{
#ifdef VERIFAST /*< ***model static initialization*** */
Queue_t * pxNewQueue = NULL;
#else
Queue_t * pxNewQueue;
#endif
size_t xQueueSizeInBytes;
uint8_t * pucQueueStorage;
configASSERT( uxQueueLength > ( UBaseType_t ) 0 );
if( ( uxQueueLength > ( UBaseType_t ) 0 ) &&
/* Check for multiplication overflow. */
( ( SIZE_MAX / uxQueueLength ) >= uxItemSize ) &&
/* Check for addition overflow. */
( ( SIZE_MAX - sizeof( Queue_t ) ) >= ( uxQueueLength * uxItemSize ) ) )
{
/* Allocate enough space to hold the maximum number of items that
* can be in the queue at any time. It is valid for uxItemSize to be
* zero in the case the queue is used as a semaphore. */
xQueueSizeInBytes = ( size_t ) ( uxQueueLength * uxItemSize ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Check for multiplication overflow. */
configASSERT( ( uxItemSize == 0 ) || ( uxQueueLength == ( xQueueSizeInBytes / uxItemSize ) ) );
/* Check for addition overflow. */
configASSERT( ( sizeof( Queue_t ) + xQueueSizeInBytes ) > xQueueSizeInBytes );
#ifdef VERIFAST /*< ***model single malloc of struct and buffer*** */
pxNewQueue = ( Queue_t * ) pvPortMalloc( sizeof( Queue_t ) );
#else
/* Allocate the queue and storage area. Justification for MISRA
* deviation as follows: pvPortMalloc() always ensures returned memory
* blocks are aligned per the requirements of the MCU stack. In this case
@ -254,12 +252,11 @@ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
/*@malloc_block_limits(pucQueueStorage);@*/
#else
/* Jump past the queue structure to find the location of the queue
* storage area. */
pucQueueStorage = ( uint8_t * ) pxNewQueue;
pucQueueStorage += sizeof( Queue_t ); /*lint !e9016 Pointer arithmetic allowed on char types, especially when it assists conveying intent. */
#endif /* ifdef VERIFAST */
#endif
#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
{
@ -277,6 +274,14 @@ QueueHandle_t xQueueGenericCreate( const UBaseType_t uxQueueLength,
traceQUEUE_CREATE_FAILED( ucQueueType );
mtCOVERAGE_TEST_MARKER();
}
}
else
{
configASSERT( pxNewQueue );
mtCOVERAGE_TEST_MARKER();
}
return pxNewQueue;
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,14 +24,15 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
static void prvCopyDataFromQueue( Queue_t * const pxQueue,
void * const pvBuffer )
/*@requires queue(pxQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*& 0 < K &*& chars(pvBuffer, M, _);@*/
/*@ensures queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs) &*&
* chars(pvBuffer, M, head(abs));@*/
chars(pvBuffer, M, head(abs));@*/
{
if( pxQueue->uxItemSize != ( UBaseType_t ) 0 )
{
@ -47,48 +48,44 @@ static void prvCopyDataFromQueue( Queue_t * const pxQueue,
else
{
/*@{
* div_lt(R+1, N, M); // now we know R+1 < N
* mod_lt(R+1, N); // so, R+1 == (R+1)%N
* note(pxQueue->u.xQueue.pcReadFrom == Storage + ((R + 1) * M));
* note( Storage + ((R + 1) * M) == Storage + (((R + 1) % N) * M));
* }@*/
div_lt(R+1, N, M); // now we know R+1 < N
mod_lt(R+1, N); // so, R+1 == (R+1)%N
note(pxQueue->u.xQueue.pcReadFrom == Storage + ((R + 1) * M));
note( Storage + ((R + 1) * M) == Storage + (((R + 1) % N) * M));
}@*/
mtCOVERAGE_TEST_MARKER();
}
/*@mod_plus(R+1, K, N);@*/
/*@mod_mod(R+1, N);@*/
/*@split_element(Storage, N, M, (R+1)%N);@*/
/*@assert
* buffer(Storage, (R+1)%N, M, ?prefix) &*&
* chars(Storage + ((R+1)%N) * M, M, ?element) &*&
* buffer(Storage + ((R+1)%N + 1) * M, (N-1-(R+1)%N), M, ?suffix);@*/
buffer(Storage, (R+1)%N, M, ?prefix) &*&
chars(Storage + ((R+1)%N) * M, M, ?element) &*&
buffer(Storage + ((R+1)%N + 1) * M, (N-1-(R+1)%N), M, ?suffix);@*/
#ifdef VERIFAST /*< void cast of unused return value */
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize );
#else
( void ) memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports. Also previous logic ensures a null pointer can only be passed to memcpy() when the count is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */
#endif
/*@{
* combine_list_no_change(prefix, element, suffix, (R+1)%N, contents);
* join_element(Storage, N, M, (R+1)%N);
* length_take(K, contents);
* take_length_eq(K, rotate_left((R+1)%N, contents), abs);
* deq_value_lemma(K, (R+1)%N, contents, abs);
* }@*/
combine_list_no_change(prefix, element, suffix, (R+1)%N, contents);
join_element(Storage, N, M, (R+1)%N);
length_take(K, contents);
take_length_eq(K, rotate_left((R+1)%N, contents), abs);
deq_value_lemma(K, (R+1)%N, contents, abs);
}@*/
}
}
void caller_reinstates_queue_predicate( Queue_t * const pxQueue,
void * const pvBuffer )
/*@requires queue(pxQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* 0 < K &*&
* chars(pvBuffer, M, _);@*/
0 < K &*&
chars(pvBuffer, M, _);@*/
/*@ensures
* queue(pxQueue, Storage, N, M, W, (R+1)%N, K-1, is_locked, tail(abs)) &*&
* chars(pvBuffer, M, head(abs));@*/
queue(pxQueue, Storage, N, M, W, (R+1)%N, K-1, is_locked, tail(abs)) &*&
chars(pvBuffer, M, head(abs));@*/
{
prvCopyDataFromQueue( pxQueue, pvBuffer );
/*@open queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs);@*/
@ -96,3 +93,5 @@ void caller_reinstates_queue_predicate( Queue_t * const pxQueue,
pxQueue->uxMessagesWaiting = pxQueue->uxMessagesWaiting - 1;
/*@deq_lemma(K, (R+1)%N, contents, abs, head(abs));@*/
}
/* *INDENT-ON* */

View file

@ -24,27 +24,27 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
const void * pvItemToQueue,
const BaseType_t xPosition )
/*@requires queue(pxQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* (K < N || xPosition == queueOVERWRITE) &*&
* chars(pvItemToQueue, M, ?x) &*&
* (xPosition == queueSEND_TO_BACK || xPosition == queueSEND_TO_FRONT || (xPosition == queueOVERWRITE && N == 1));@*/
(K < N || xPosition == queueOVERWRITE) &*&
chars(pvItemToQueue, M, ?x) &*&
(xPosition == queueSEND_TO_BACK || xPosition == queueSEND_TO_FRONT || (xPosition == queueOVERWRITE && N == 1));@*/
/*@ensures
* (xPosition == queueSEND_TO_BACK
* ? queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)))
* : (xPosition == queueSEND_TO_FRONT
* ? (R == 0
* ? queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs))
* : queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs)))
* : xPosition == queueOVERWRITE &*& queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x)))
* ) &*&
* chars(pvItemToQueue, M, x);@*/
(xPosition == queueSEND_TO_BACK
? queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)))
: (xPosition == queueSEND_TO_FRONT
? (R == 0
? queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs))
: queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs)))
: xPosition == queueOVERWRITE &*& queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x)))
) &*&
chars(pvItemToQueue, M, x);@*/
{
BaseType_t xReturn = pdFALSE;
UBaseType_t uxMessagesWaiting;
@ -77,24 +77,22 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
else if( xPosition == queueSEND_TO_BACK )
{
#ifdef VERIFAST /*< void cast of unused return value */
/* Now we focus the proof on the logical element of the buffer that
* will be updated using the following lemma to split the buffer into 3
* parts: a prefix, the element we want to update, and the suffix. This
* enables the subsequent memcpy to verify. */
/*@split_element(Storage, N, M, W);@*/
/*@assert
* buffer(Storage, W, M, ?prefix) &*&
* chars(Storage + W * M, M, _) &*&
* buffer(Storage + (W + 1) * M, (N-1-W), M, ?suffix);@*/
buffer(Storage, W, M, ?prefix) &*&
chars(Storage + W * M, M, _) &*&
buffer(Storage + (W + 1) * M, (N-1-W), M, ?suffix);@*/
memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize );
/* After the update we stitch the buffer back together */
/*@join_element(Storage, N, M, W);@*/
/*@combine_list_update(prefix, x, suffix, W, contents);@*/
#else
( void ) memcpy( ( void * ) pxQueue->pcWriteTo, pvItemToQueue, ( size_t ) pxQueue->uxItemSize ); /*lint !e961 !e418 !e9087 MISRA exception as the casts are only redundant for some ports, plus previous logic ensures a null pointer can only be passed to memcpy() if the copy size is 0. Cast to void required by function signature and safe as no alignment requirement and copy length specified in bytes. */
#endif /* ifdef VERIFAST */
#endif
/*@mul_mono_l(W, N-1, M);@*/
pxQueue->pcWriteTo += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */
@ -106,11 +104,11 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
else
{
/*@{
* div_lt(W+1, N, M); // now we know W+1 < N
* mod_lt(W+1, N); // so, W+1 == (W+1)%N
* note(pxQueue->pcWriteTo == Storage + ((W + 1) * M));
* note( Storage + ((W + 1) * M) == Storage + (((W + 1) % N) * M));
* }@*/
div_lt(W+1, N, M); // now we know W+1 < N
mod_lt(W+1, N); // so, W+1 == (W+1)%N
note(pxQueue->pcWriteTo == Storage + ((W + 1) * M));
note( Storage + ((W + 1) * M) == Storage + (((W + 1) % N) * M));
}@*/
mtCOVERAGE_TEST_MARKER();
}
}
@ -118,11 +116,10 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
{
#ifdef VERIFAST /*< void cast of unused return value */
/*@split_element(Storage, N, M, R);@*/
/*@assert
* buffer(Storage, R, M, ?prefix) &*&
* chars(Storage + R * M, M, _) &*&
* buffer(Storage + (R + 1) * M, (N-1-R), M, ?suffix);@*/
buffer(Storage, R, M, ?prefix) &*&
chars(Storage + R * M, M, _) &*&
buffer(Storage + (R + 1) * M, (N-1-R), M, ?suffix);@*/
memcpy( ( void * ) pxQueue->u.xQueue.pcReadFrom, pvItemToQueue, ( size_t ) pxQueue->uxItemSize );
/*@join_element(Storage, N, M, R);@*/
/*@combine_list_update(prefix, x, suffix, R, contents);@*/
@ -146,12 +143,12 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
}
/*@
* if (R == 0)
* {
* mod_plus(N, (K+1), N); mod_same(N); mod_mod(K+1, N);
* assert W == ((N-1) + 1 + (K+1)) % N;
* }
* @*/
if (R == 0)
{
mod_plus(N, (K+1), N); mod_same(N); mod_mod(K+1, N);
assert W == ((N-1) + 1 + (K+1)) % N;
}
@*/
if( xPosition == queueOVERWRITE )
{
if( uxMessagesWaiting > ( UBaseType_t ) 0 )
@ -176,20 +173,22 @@ static BaseType_t prvCopyDataToQueue( Queue_t * const pxQueue,
pxQueue->uxMessagesWaiting = uxMessagesWaiting + ( UBaseType_t ) 1;
/*@
* if (xPosition == queueSEND_TO_BACK)
* {
* enq_lemma(K, (R+1)%N, contents, abs, x);
* mod_plus_one(W, R + 1 + K, N);
* mod_plus_distr(R+1, K, N);
* }
* else if (xPosition == queueSEND_TO_FRONT)
* {
* front_enq_lemma(K, R, contents, abs, x);
* if (0 < R)
* {
* mod_lt(R, N);
* }
* }
* @*/
if (xPosition == queueSEND_TO_BACK)
{
enq_lemma(K, (R+1)%N, contents, abs, x);
mod_plus_one(W, R + 1 + K, N);
mod_plus_distr(R+1, K, N);
}
else if (xPosition == queueSEND_TO_FRONT)
{
front_enq_lemma(K, R, contents, abs, x);
if (0 < R)
{
mod_lt(R, N);
}
}
@*/
return xReturn;
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#define taskENTER_CRITICAL() setInterruptMask( pxQueue )
#define taskEXIT_CRITICAL() clearInterruptMask( pxQueue )
@ -51,3 +53,5 @@ static BaseType_t prvIsQueueEmpty( const Queue_t * pxQueue )
return xReturn;
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#define taskENTER_CRITICAL() setInterruptMask( pxQueue )
#define taskEXIT_CRITICAL() clearInterruptMask( pxQueue )
@ -51,3 +53,5 @@ static BaseType_t prvIsQueueFull( const Queue_t * pxQueue )
return xReturn;
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
/* In this case we cannot wrap the macro in a function call to give a function
@ -46,12 +48,11 @@
void wrapper_prvLockQueue( QueueHandle_t xQueue )
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]queuelock(xQueue);@*/
[1/2]queuelock(xQueue);@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]xQueue->locked |-> ?m &*&
* mutex_held(m, queue_locked_invariant(xQueue), currentThread, 1/2) &*&
* queue_locked_invariant(xQueue)();@*/
[1/2]xQueue->locked |-> ?m &*&
mutex_held(m, queue_locked_invariant(xQueue), currentThread, 1/2) &*&
queue_locked_invariant(xQueue)();@*/
{
taskENTER_CRITICAL();
/*@open queue(xQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
@ -72,3 +73,5 @@ void wrapper_prvLockQueue( QueueHandle_t xQueue )
mutex_acquire( xQueue->locked );
#endif
}
/* *INDENT-ON* */

View file

@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#define taskENTER_CRITICAL() setInterruptMask( pxQueue )
#define taskEXIT_CRITICAL() clearInterruptMask( pxQueue )
@ -32,14 +34,12 @@
* decrementing `cTxLock` and `cRxLock`. */
static void prvUnlockQueue( Queue_t * const pxQueue )
/*@requires [1/2]queuehandle(pxQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]pxQueue->locked |-> ?m &*&
* mutex_held(m, queue_locked_invariant(pxQueue), currentThread, 1/2) &*&
* queue_locked_invariant(pxQueue)();@*/
[1/2]pxQueue->locked |-> ?m &*&
mutex_held(m, queue_locked_invariant(pxQueue), currentThread, 1/2) &*&
queue_locked_invariant(pxQueue)();@*/
/*@ensures [1/2]queuehandle(pxQueue, N, M, is_isr) &*&
* [1/2]queuelock(pxQueue);@*/
[1/2]queuelock(pxQueue);@*/
{
/* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED. */
@ -166,3 +166,5 @@ static void prvUnlockQueue( Queue_t * const pxQueue )
mutex_release( pxQueue->locked );
#endif
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
/* It may seem that the read of `pxQueue->uxMessagesWaiting` is required to be
@ -71,3 +73,5 @@ UBaseType_t uxQueueMessagesWaiting( const QueueHandle_t xQueue )
return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
@ -51,3 +53,5 @@ UBaseType_t uxQueueSpacesAvailable( const QueueHandle_t xQueue )
return uxReturn;
} /*lint !e818 Pointer cannot be declared const as xQueue is a typedef not pointer. */
/* *INDENT-ON* */

View file

@ -24,17 +24,18 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#define configSUPPORT_DYNAMIC_ALLOCATION 1
#define configSUPPORT_STATIC_ALLOCATION 0
void vQueueDelete( QueueHandle_t xQueue )
/*@requires queue(xQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs) &*&
* queuelists(xQueue) &*&
* xQueue->irqMask |-> _ &*&
* xQueue->schedulerSuspend |-> _ &*&
* xQueue->locked |-> _;@*/
queuelists(xQueue) &*&
xQueue->irqMask |-> _ &*&
xQueue->schedulerSuspend |-> _ &*&
xQueue->locked |-> _;@*/
/*@ensures true;@*/
{
#ifdef VERIFAST /*< const pointer declaration */
@ -83,3 +84,5 @@ void vQueueDelete( QueueHandle_t xQueue )
}
#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
}
/* *INDENT-ON* */

View file

@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#include "proof/queuecontracts.h"
@ -31,19 +33,16 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
const void * const pvItemToQueue,
TickType_t xTicksToWait,
const BaseType_t xCopyPosition )
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvItemToQueue, M, ?x) &*&
* (xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1));@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvItemToQueue, M, ?x) &*&
(xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1));@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvItemToQueue, M, x);@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvItemToQueue, M, x);@*/
{
BaseType_t xEntryTimeSet = pdFALSE, xYieldRequired;
TimeOut_t xTimeOut;
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
#else
@ -57,24 +56,22 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
#endif /* ifdef VERIFAST */
#endif
/*lint -save -e904 This function relaxes the coding standard somewhat to
* allow return statements within the function itself. This is done in the
* interest of execution time efficiency. */
for( ; ; )
/*@invariant [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvItemToQueue, M, x) &*&
* u_integer(&xTicksToWait, _) &*&
* (xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1)) &*&
* xTIME_OUT(&xTimeOut);@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvItemToQueue, M, x) &*&
u_integer(&xTicksToWait, _) &*&
(xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1)) &*&
xTIME_OUT(&xTimeOut);@*/
{
taskENTER_CRITICAL();
{
/*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
/* Is there room on the queue now? The running task must be the
* highest priority task wanting to access the queue. If the head item
* in the queue is to be overwritten then it does not matter if the
@ -182,19 +179,19 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
#endif /* configUSE_QUEUE_SETS */
/*@
* if (xCopyPosition == queueSEND_TO_BACK)
* {
* close queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)));
* }
* else if (xCopyPosition == queueSEND_TO_FRONT)
* {
* close queue(pxQueue, Storage, N, M, W, (R == 0 ? (N-1) : (R-1)), (K+1), is_locked, cons(x, abs));
* }
* else if (xCopyPosition == queueOVERWRITE)
* {
* close queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x));
* }
* @*/
if (xCopyPosition == queueSEND_TO_BACK)
{
close queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)));
}
else if (xCopyPosition == queueSEND_TO_FRONT)
{
close queue(pxQueue, Storage, N, M, W, (R == 0 ? (N-1) : (R-1)), (K+1), is_locked, cons(x, abs));
}
else if (xCopyPosition == queueOVERWRITE)
{
close queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x));
}
@*/
taskEXIT_CRITICAL();
return pdPASS;
}
@ -203,7 +200,6 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
if( xTicksToWait == ( TickType_t ) 0 )
{
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
/* The queue was full and no block time is specified (or
* the block time has expired) so leave now. */
taskEXIT_CRITICAL();
@ -226,7 +222,6 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
mtCOVERAGE_TEST_MARKER();
}
}
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
}
taskEXIT_CRITICAL();
@ -251,13 +246,13 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
* event list. It is possible that interrupts occurring now
* remove this task from the event list again - but as the
* scheduler is suspended the task will go onto the pending
* ready last instead of the actual ready list. */
* ready list instead of the actual ready list. */
/*@close queue_locked_invariant(xQueue)();@*/
prvUnlockQueue( pxQueue );
/* Resuming the scheduler will move tasks from the pending
* ready list into the ready list - so it is feasible that this
* task is already in a ready list before it yields - in which
* task is already in the ready list before it yields - in which
* case the yield will not cause a context switch unless there
* is also a higher priority task in the pending ready list. */
/*@close exists(pxQueue);@*/
@ -294,3 +289,5 @@ BaseType_t xQueueGenericSend( QueueHandle_t xQueue,
}
} /*lint -restore */
}
/* *INDENT-ON* */

View file

@ -24,6 +24,8 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#include "proof/queuecontracts.h"
@ -31,17 +33,15 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
const void * const pvItemToQueue,
BaseType_t * const pxHigherPriorityTaskWoken,
const BaseType_t xCopyPosition )
/*@requires
* [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == true &*&
* chars(pvItemToQueue, M, ?x) &*&
* integer(pxHigherPriorityTaskWoken, _) &*&
* (xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1));@*/
[1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == true &*&
chars(pvItemToQueue, M, ?x) &*&
integer(pxHigherPriorityTaskWoken, _) &*&
(xCopyPosition == queueSEND_TO_BACK || xCopyPosition == queueSEND_TO_FRONT || (xCopyPosition == queueOVERWRITE && N == 1));@*/
/*@ensures
* [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* chars(pvItemToQueue, M, x) &*&
* integer(pxHigherPriorityTaskWoken, _);@*/
[1/2]queuehandle(xQueue, N, M, is_isr) &*&
chars(pvItemToQueue, M, x) &*&
integer(pxHigherPriorityTaskWoken, _);@*/
{
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
@ -207,27 +207,26 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
}
xReturn = pdPASS;
/*@
* if (xCopyPosition == queueSEND_TO_BACK)
* {
* close queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)));
* }
* else if (xCopyPosition == queueSEND_TO_FRONT)
* {
* if (R == 0)
* {
* close queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs));
* }
* else
* {
* close queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs));
* }
* } else if (xCopyPosition == queueOVERWRITE)
* {
* close queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x));
* }
* @*/
if (xCopyPosition == queueSEND_TO_BACK)
{
close queue(pxQueue, Storage, N, M, (W+1)%N, R, (K+1), is_locked, append(abs, singleton(x)));
}
else if (xCopyPosition == queueSEND_TO_FRONT)
{
if (R == 0)
{
close queue(pxQueue, Storage, N, M, W, (N-1), (K+1), is_locked, cons(x, abs));
}
else
{
close queue(pxQueue, Storage, N, M, W, (R-1), (K+1), is_locked, cons(x, abs));
}
} else if (xCopyPosition == queueOVERWRITE)
{
close queue(pxQueue, Storage, N, M, W, R, 1, is_locked, singleton(x));
}
@*/
}
else
{
@ -240,3 +239,5 @@ BaseType_t xQueueGenericSendFromISR( QueueHandle_t xQueue,
return xReturn;
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,13 +24,14 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
/*@requires queue(xQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
/*@ensures queue(xQueue, Storage, N, M, W, R, K, is_locked, abs) &*&
* result == ((K == 0) ? pdTRUE : pdFALSE);@*/
result == ((K == 0) ? pdTRUE : pdFALSE);@*/
{
BaseType_t xReturn;
@ -53,3 +54,5 @@ BaseType_t xQueueIsQueueEmptyFromISR( const QueueHandle_t xQueue )
return xReturn;
} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,13 +24,14 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
/*@requires queue(xQueue, ?Storage, ?N, ?M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
/*@ensures queue(xQueue, Storage, N, M, W, R, K, is_locked, abs) &*&
* result == ((K == N) ? pdTRUE : pdFALSE);@*/
result == ((K == N) ? pdTRUE : pdFALSE);@*/
{
BaseType_t xReturn;
@ -53,3 +54,5 @@ BaseType_t xQueueIsQueueFullFromISR( const QueueHandle_t xQueue )
return xReturn;
} /*lint !e818 xQueue could not be pointer to const because it is a typedef. */
/* *INDENT-ON* */

View file

@ -24,25 +24,24 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#include "proof/queuecontracts.h"
BaseType_t xQueuePeek( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait )
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvBuffer, M, ?x);@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvBuffer, M, ?x);@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuesuspend(xQueue) &*&
* (result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/
[1/2]queuesuspend(xQueue) &*&
(result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/
{
BaseType_t xEntryTimeSet = pdFALSE;
TimeOut_t xTimeOut;
int8_t * pcOriginalReadPosition;
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
#else
@ -61,18 +60,17 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue,
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
#endif /* ifdef VERIFAST */
#endif
/*lint -save -e904 This function relaxes the coding standard somewhat to
* allow return statements within the function itself. This is done in the
* interest of execution time efficiency. */
for( ; ; )
/*@invariant [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvBuffer, M, x) &*&
* u_integer(&xTicksToWait, _) &*&
* xTIME_OUT(&xTimeOut);@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvBuffer, M, x) &*&
u_integer(&xTicksToWait, _) &*&
xTIME_OUT(&xTimeOut);@*/
{
taskENTER_CRITICAL();
/*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
@ -148,7 +146,7 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue,
taskEXIT_CRITICAL();
/* Interrupts and other tasks can send to and receive from the queue
* now the critical section has been exited. */
* now that the critical section has been exited. */
/*@close exists<QueueHandle_t>(pxQueue);@*/
vTaskSuspendAll();
@ -214,3 +212,5 @@ BaseType_t xQueuePeek( QueueHandle_t xQueue,
}
} /*lint -restore */
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,22 +24,21 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#include "proof/queuecontracts.h"
BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
void * const pvBuffer )
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == true &*&
* chars(pvBuffer, M, ?x);@*/
chars(pvBuffer, M, ?x);@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* (result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/
(result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/
{
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
int8_t * pcOriginalReadPosition;
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
#else
@ -95,3 +94,5 @@ BaseType_t xQueuePeekFromISR( QueueHandle_t xQueue,
return xReturn;
}
/* *INDENT-ON* */

View file

@ -24,24 +24,23 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#include "proof/queuecontracts.h"
BaseType_t xQueueReceive( QueueHandle_t xQueue,
void * const pvBuffer,
TickType_t xTicksToWait )
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == false &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvBuffer, M, ?x);@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvBuffer, M, ?x);@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuesuspend(xQueue) &*&
* (result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/
[1/2]queuesuspend(xQueue) &*&
(result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x));@*/
{
BaseType_t xEntryTimeSet = pdFALSE;
TimeOut_t xTimeOut;
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
#else
@ -60,18 +59,17 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
}
#endif
#endif /* ifdef VERIFAST */
#endif
/*lint -save -e904 This function relaxes the coding standard somewhat to
* allow return statements within the function itself. This is done in the
* interest of execution time efficiency. */
for( ; ; )
/*@invariant [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* [1/2]queuesuspend(xQueue) &*&
* chars(pvBuffer, M, x) &*&
* u_integer(&xTicksToWait, _) &*&
* xTIME_OUT(&xTimeOut);@*/
[1/2]queuesuspend(xQueue) &*&
chars(pvBuffer, M, x) &*&
u_integer(&xTicksToWait, _) &*&
xTIME_OUT(&xTimeOut);@*/
{
taskENTER_CRITICAL();
/*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
@ -90,10 +88,9 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
/*@assert
* pxQueue->pcHead |-> ?buffer &*&
* buffer(buffer, N, M, ?contents);@*/
pxQueue->pcHead |-> ?buffer &*&
buffer(buffer, N, M, ?contents);@*/
/*@deq_lemma(K, (R+1)%N, contents, abs, head(abs));@*/
/* There is now space in the queue, were any tasks waiting to
* post to the queue? If so, unblock the highest priority waiting
* task. */
@ -123,7 +120,6 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
if( xTicksToWait == ( TickType_t ) 0 )
{
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
/* The queue was empty and no block time is specified (or
* the block time has expired) so leave now. */
taskEXIT_CRITICAL();
@ -214,3 +210,5 @@ BaseType_t xQueueReceive( QueueHandle_t xQueue,
}
} /*lint -restore */
}
/* *INDENT-ON* */

View file

@ -1,6 +1,6 @@
/*
* FreeRTOS V202112.00
* Copyright (C) Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 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
@ -24,24 +24,23 @@
*
*/
/* *INDENT-OFF* */
#include "proof/queue.h"
#include "proof/queuecontracts.h"
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
void * const pvBuffer,
BaseType_t * const pxHigherPriorityTaskWoken )
/*@requires [1/2]queuehandle(xQueue, ?N, ?M, ?is_isr) &*& is_isr == true &*&
* chars(pvBuffer, M, ?x) &*&
* pxHigherPriorityTaskWoken == NULL ? true : integer(pxHigherPriorityTaskWoken, _);@*/
chars(pvBuffer, M, ?x) &*&
pxHigherPriorityTaskWoken == NULL ? true : integer(pxHigherPriorityTaskWoken, _);@*/
/*@ensures [1/2]queuehandle(xQueue, N, M, is_isr) &*&
* (result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x)) &*&
* (pxHigherPriorityTaskWoken == NULL ? true : integer(pxHigherPriorityTaskWoken, _));@*/
(result == pdPASS ? chars(pvBuffer, M, _) : chars(pvBuffer, M, x)) &*&
(pxHigherPriorityTaskWoken == NULL ? true : integer(pxHigherPriorityTaskWoken, _));@*/
{
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
#else
@ -141,3 +140,5 @@ BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue,
return xReturn;
}
/* *INDENT-ON* */