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:
Nathan Chong 2020-07-21 12:51:20 -04:00 committed by GitHub
parent c720c18ada
commit 8e36bee30e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
26 changed files with 2021 additions and 1762 deletions

View file

@ -23,112 +23,114 @@
#include "proof/queue.h"
#include "proof/queuecontracts.h"
BaseType_t xQueueReceiveFromISR( QueueHandle_t xQueue, void * const pvBuffer, BaseType_t * const pxHigherPriorityTaskWoken )
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;
BaseType_t xReturn;
UBaseType_t uxSavedInterruptStatus;
#ifdef VERIFAST /*< const pointer declaration */
Queue_t * pxQueue = xQueue;
Queue_t * pxQueue = xQueue;
#else
Queue_t * const pxQueue = xQueue;
Queue_t * const pxQueue = xQueue;
configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
configASSERT( pxQueue );
configASSERT( !( ( pvBuffer == NULL ) && ( pxQueue->uxItemSize != ( UBaseType_t ) 0U ) ) );
#endif
/* RTOS ports that support interrupt nesting have the concept of a maximum
system call (or maximum API call) interrupt priority. Interrupts that are
above the maximum system call priority are kept permanently enabled, even
when the RTOS kernel is in a critical section, but cannot make any calls to
FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has been
assigned a priority above the configured maximum system call priority.
Only FreeRTOS functions that end in FromISR can be called from interrupts
that have been assigned a priority at or (logically) below the maximum
system call interrupt priority. FreeRTOS maintains a separate interrupt
safe API to ensure interrupt entry is as fast and as simple as possible.
More information (albeit Cortex-M specific) is provided on the following
link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
/* RTOS ports that support interrupt nesting have the concept of a maximum
* system call (or maximum API call) interrupt priority. Interrupts that are
* above the maximum system call priority are kept permanently enabled, even
* when the RTOS kernel is in a critical section, but cannot make any calls to
* FreeRTOS API functions. If configASSERT() is defined in FreeRTOSConfig.h
* then portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
* failure if a FreeRTOS API function is called from an interrupt that has been
* assigned a priority above the configured maximum system call priority.
* Only FreeRTOS functions that end in FromISR can be called from interrupts
* that have been assigned a priority at or (logically) below the maximum
* system call interrupt priority. FreeRTOS maintains a separate interrupt
* safe API to ensure interrupt entry is as fast and as simple as possible.
* More information (albeit Cortex-M specific) is provided on the following
* link: http://www.freertos.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
/*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
{
const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
uxSavedInterruptStatus = portSET_INTERRUPT_MASK_FROM_ISR();
/*@assert queue(pxQueue, ?Storage, N, M, ?W, ?R, ?K, ?is_locked, ?abs);@*/
{
const UBaseType_t uxMessagesWaiting = pxQueue->uxMessagesWaiting;
/* Cannot block in an ISR, so check there is data available. */
if( uxMessagesWaiting > ( UBaseType_t ) 0 )
{
const int8_t cRxLock = pxQueue->cRxLock;
/* Cannot block in an ISR, so check there is data available. */
if( uxMessagesWaiting > ( UBaseType_t ) 0 )
{
const int8_t cRxLock = pxQueue->cRxLock;
traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
traceQUEUE_RECEIVE_FROM_ISR( pxQueue );
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
prvCopyDataFromQueue( pxQueue, pvBuffer );
/*@open queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs);@*/
pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
/*@assert buffer(Storage, N, M, ?contents);@*/
/*@deq_lemma(K, (R+1)%N, contents, abs, head(abs));@*/
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
prvCopyDataFromQueue( pxQueue, pvBuffer );
/*@open queue_after_prvCopyDataFromQueue(pxQueue, Storage, N, M, W, (R+1)%N, K, is_locked, abs);@*/
pxQueue->uxMessagesWaiting = uxMessagesWaiting - ( UBaseType_t ) 1;
/*@assert buffer(Storage, N, M, ?contents);@*/
/*@deq_lemma(K, (R+1)%N, contents, abs, head(abs));@*/
/* If the queue is locked the event list will not be modified.
Instead update the lock count so the task that unlocks the queue
will know that an ISR has removed data while the queue was
locked. */
if( cRxLock == queueUNLOCKED )
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
/* The task waiting has a higher priority than us so
force a context switch. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* Increment the lock count so the task that unlocks the queue
knows that data was removed while it was locked. */
configASSERT( cRxLock != queueINT8_MAX);
/* If the queue is locked the event list will not be modified.
* Instead update the lock count so the task that unlocks the queue
* will know that an ISR has removed data while the queue was
* locked. */
if( cRxLock == queueUNLOCKED )
{
if( listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToSend ) ) == pdFALSE )
{
if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToSend ) ) != pdFALSE )
{
/* The task waiting has a higher priority than us so
* force a context switch. */
if( pxHigherPriorityTaskWoken != NULL )
{
*pxHigherPriorityTaskWoken = pdTRUE;
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
else
{
/* Increment the lock count so the task that unlocks the queue
* knows that data was removed while it was locked. */
configASSERT( cRxLock != queueINT8_MAX );
pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 );
}
pxQueue->cRxLock = ( int8_t ) ( cRxLock + 1 );
}
/*@close queue(pxQueue, Storage, N, M, W, (R+1)%N, K-1, is_locked, tail(abs));@*/
/*@assert chars(pvBuffer, M, head(abs));@*/
xReturn = pdPASS;
}
else
{
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
xReturn = pdFAIL;
traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
/*@close queue(pxQueue, Storage, N, M, W, (R+1)%N, K-1, is_locked, tail(abs));@*/
/*@assert chars(pvBuffer, M, head(abs));@*/
xReturn = pdPASS;
}
else
{
/*@close queue(pxQueue, Storage, N, M, W, R, K, is_locked, abs);@*/
xReturn = pdFAIL;
traceQUEUE_RECEIVE_FROM_ISR_FAILED( pxQueue );
}
}
portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedInterruptStatus );
return xReturn;
return xReturn;
}