mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-10-15 17:27:46 -04:00
Prove buffer lemmas (#124)
* Prove buffer lemmas * Update queue proofs to latest kernel source All changes were syntactic due to uncrustify code-formatting * Strengthen prvCopyDataToQueue proof * Add extract script for diff comparison Co-authored-by: Yuhui Zheng <10982575+yuhui-zheng@users.noreply.github.com>
This commit is contained in:
parent
c720c18ada
commit
8e36bee30e
26 changed files with 2021 additions and 1762 deletions
|
@ -22,64 +22,68 @@
|
|||
|
||||
#include "proof/queue.h"
|
||||
|
||||
static void prvCopyDataFromQueue( Queue_t * const pxQueue, void * const pvBuffer )
|
||||
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 )
|
||||
{
|
||||
/*@assert buffer(Storage, N, M, ?contents);@*/
|
||||
/*@mul_mono_l(R, N-1, M);@*/
|
||||
pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */
|
||||
if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
|
||||
{
|
||||
/*@div_leq(N, R+1, M);@*/ // now we know R == N-1
|
||||
pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
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));
|
||||
}@*/
|
||||
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);@*/
|
||||
if( pxQueue->uxItemSize != ( UBaseType_t ) 0 )
|
||||
{
|
||||
/*@assert buffer(Storage, N, M, ?contents);@*/
|
||||
/*@mul_mono_l(R, N-1, M);@*/
|
||||
pxQueue->u.xQueue.pcReadFrom += pxQueue->uxItemSize; /*lint !e9016 Pointer arithmetic on char types ok, especially in this use case where it is the clearest way of conveying intent. */
|
||||
|
||||
if( pxQueue->u.xQueue.pcReadFrom >= pxQueue->u.xQueue.pcTail ) /*lint !e946 MISRA exception justified as use of the relational operator is the cleanest solutions. */
|
||||
{
|
||||
/*@div_leq(N, R+1, M);@*/ /* now we know R == N-1 */
|
||||
pxQueue->u.xQueue.pcReadFrom = pxQueue->pcHead;
|
||||
}
|
||||
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));
|
||||
}@*/
|
||||
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);@*/
|
||||
#ifdef VERIFAST /*< void cast of unused return value */
|
||||
memcpy( ( void * ) pvBuffer, ( void * ) pxQueue->u.xQueue.pcReadFrom, ( size_t ) pxQueue->uxItemSize );
|
||||
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. */
|
||||
( 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)
|
||||
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);@*/
|
||||
/*@assert buffer(Storage, N, M, ?contents);@*/
|
||||
pxQueue->uxMessagesWaiting = pxQueue->uxMessagesWaiting - 1;
|
||||
/*@deq_lemma(K, (R+1)%N, contents, abs, head(abs));@*/
|
||||
prvCopyDataFromQueue( pxQueue, pvBuffer );
|
||||
/*@open queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs);@*/
|
||||
/*@assert buffer(Storage, N, M, ?contents);@*/
|
||||
pxQueue->uxMessagesWaiting = pxQueue->uxMessagesWaiting - 1;
|
||||
/*@deq_lemma(K, (R+1)%N, contents, abs, head(abs));@*/
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue