Verified minimal contract for xTaskGetCurrentTaskHandle.

This commit is contained in:
Tobias Reinhard 2022-11-10 14:36:04 -05:00
parent 63d8c5afa8
commit 29e14be203
4 changed files with 75 additions and 39 deletions

20
tasks.c
View file

@ -4155,7 +4155,9 @@ void vTaskSwitchContext( BaseType_t xCoreID )
/*@ requires 0 <= xCoreID &*& xCoreID < configNUM_CORES &*& /*@ requires 0 <= xCoreID &*& xCoreID < configNUM_CORES &*&
locked(nil) &*& locked(nil) &*&
[?f_ISR]isrLock() &*& [?f_ISR]isrLock() &*&
[?f_task]taskLock(); [?f_task]taskLock() &*&
interruptState_p(xCoreID, ?state) &*&
xCoreID == coreID_f();
@*/ @*/
//@ ensures true; //@ ensures true;
{ {
@ -4176,7 +4178,15 @@ void vTaskSwitchContext( BaseType_t xCoreID )
#ifdef VERIFAST #ifdef VERIFAST
/* Reason for rewrite: VeriFast cannot handle non-pure assertions. */ /* Reason for rewrite: VeriFast cannot handle non-pure assertions. */
{ {
UBaseType_t nesting = pxCurrentTCB->uxCriticalNesting; // PROBLEM:
// Line
// UBaseType_t nesting = pxCurrentTCB->uxCriticalNesting;
// leads to VF error
// "This potentially side-effecting expression is not supported in this position, because of C's unspecified evaluation order"
//
// TODO: Inspect reason.
TaskHandle_t handle = pxCurrentTCB;
UBaseType_t nesting = handle->uxCriticalNesting;
configASSERT( nesting == 0 ); configASSERT( nesting == 0 );
} }
#else #else
@ -5305,14 +5315,16 @@ static void prvResetNextTaskUnblockTime( void )
#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) #if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
TaskHandle_t xTaskGetCurrentTaskHandle( void ) TaskHandle_t xTaskGetCurrentTaskHandle( void )
///@ requires interruptState_p(?coreID, ?irpState); //@ requires interruptState_p(?coreID, ?irpState);
///@ ensures interruptState_p(coreID, irpState) &*& false; //@ ensures interruptState_p(coreID, irpState);
{ {
TaskHandle_t xReturn; TaskHandle_t xReturn;
uint32_t ulState; uint32_t ulState;
ulState = portDISABLE_INTERRUPTS(); ulState = portDISABLE_INTERRUPTS();
//@ open coreLocalGlobalVars_p();
xReturn = pxCurrentTCBs[ portGET_CORE_ID() ]; xReturn = pxCurrentTCBs[ portGET_CORE_ID() ];
//@ close coreLocalGlobalVars_p();
portRESTORE_INTERRUPTS( ulState ); portRESTORE_INTERRUPTS( ulState );
return xReturn; return xReturn;

View file

@ -10384,14 +10384,19 @@ uint32_t VF__portDISABLE_INTERRUPTS();
//@ requires interruptState_p(?coreID, ?state); //@ requires interruptState_p(?coreID, ?state);
/*@ ensures result == state &*& /*@ ensures result == state &*&
interruptState_p(coreID, ?newState) &*& interruptState_p(coreID, ?newState) &*&
interruptsDisabled_f(newState) == true; interruptsDisabled_f(newState) == true &*&
coreLocalGlobalVars_p();
@*/ @*/
void VF__portRESTORE_INTERRUPTS(uint32_t state); void VF__portRESTORE_INTERRUPTS(uint32_t ulState);
//@ requires interruptState_p(?coreID, _); /*@ requires interruptState_p(?coreID, ?tmpState) &*&
/*@ ensures interruptState_p(coreID, state); interruptsDisabled_f(tmpState) == true
? coreLocalGlobalVars_p()
: true;
@*/
/*@ ensures interruptState_p(coreID, ulState);
@*/ @*/
@ -10458,7 +10463,7 @@ predicate interruptState_p(uint32_t coreID, uint32_t state);
fixpoint bool interruptsDisabled_f(uint32_t); fixpoint bool interruptsDisabled_f(uint32_t);
predicate coreLocalGlobalVars() = predicate coreLocalGlobalVars_p() =
pointer(&pxCurrentTCBs[coreID_f], _); pointer(&pxCurrentTCBs[coreID_f], _);
predicate coreLocalLocked(uint32_t coreID); predicate coreLocalLocked(uint32_t coreID);
@ -10527,7 +10532,9 @@ predicate isrLockInv() =
fixpoint int taskISRLockID_f(); fixpoint int taskISRLockID_f();
predicate taskISRLockInv() = predicate taskISRLockInv() =
integer_((int*) &uxSchedulerSuspended, sizeof(UBaseType_t), false, _); integer_((int*) &uxSchedulerSuspended, sizeof(UBaseType_t), false, _) &*&
//TCB_p(pxCurrentTCBs[coreID_f()], ?ulFreeBytesOnStack);
true;
lemma void get_taskISRLockInv(); lemma void get_taskISRLockInv();
@ -13957,7 +13964,9 @@ void vTaskSwitchContext( BaseType_t xCoreID )
/*@ requires 0 <= xCoreID &*& xCoreID < configNUM_CORES &*& /*@ requires 0 <= xCoreID &*& xCoreID < configNUM_CORES &*&
locked(nil) &*& locked(nil) &*&
[?f_ISR]isrLock() &*& [?f_ISR]isrLock() &*&
[?f_task]taskLock(); [?f_task]taskLock() &*&
interruptState_p(xCoreID, ?state) &*&
xCoreID == coreID_f();
@*/ @*/
//@ ensures true; //@ ensures true;
{ {
@ -13978,7 +13987,15 @@ void vTaskSwitchContext( BaseType_t xCoreID )
/* Reason for rewrite: VeriFast cannot handle non-pure assertions. */ /* Reason for rewrite: VeriFast cannot handle non-pure assertions. */
{ {
UBaseType_t nesting = xTaskGetCurrentTaskHandle()->uxCriticalNesting; // PROBLEM:
// Line
// UBaseType_t nesting = pxCurrentTCB->uxCriticalNesting;
// leads to VF error
// "This potentially side-effecting expression is not supported in this position, because of C's unspecified evaluation order"
//
// TODO: Inspect reason.
TaskHandle_t handle = xTaskGetCurrentTaskHandle();
UBaseType_t nesting = handle->uxCriticalNesting;
assert(nesting == 0); assert(nesting == 0);
} }
@ -13995,7 +14012,7 @@ void vTaskSwitchContext( BaseType_t xCoreID )
{ {
xYieldPendings[ xCoreID ] = ( ( char ) 0 ); xYieldPendings[ xCoreID ] = ( ( char ) 0 );
; ;
// # 4225 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4235 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/* Check for stack overflow, if configured. */ /* Check for stack overflow, if configured. */
{ const uint32_t * pulStack = ( uint32_t * ) xTaskGetCurrentTaskHandle()->pxStack; const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; if( ( pulStack[ 0 ] != ulCheckValue ) || ( pulStack[ 1 ] != ulCheckValue ) || ( pulStack[ 2 ] != ulCheckValue ) || ( pulStack[ 3 ] != ulCheckValue ) ) { vApplicationStackOverflowHook( ( TaskHandle_t ) xTaskGetCurrentTaskHandle(), xTaskGetCurrentTaskHandle()->pcTaskName ); } }; { const uint32_t * pulStack = ( uint32_t * ) xTaskGetCurrentTaskHandle()->pxStack; const uint32_t ulCheckValue = ( uint32_t ) 0xa5a5a5a5; if( ( pulStack[ 0 ] != ulCheckValue ) || ( pulStack[ 1 ] != ulCheckValue ) || ( pulStack[ 2 ] != ulCheckValue ) || ( pulStack[ 3 ] != ulCheckValue ) ) { vApplicationStackOverflowHook( ( TaskHandle_t ) xTaskGetCurrentTaskHandle(), xTaskGetCurrentTaskHandle()->pcTaskName ); } };
@ -14012,7 +14029,7 @@ void vTaskSwitchContext( BaseType_t xCoreID )
; ;
/* After the new task is switched in, update the global errno. */ /* After the new task is switched in, update the global errno. */
// # 4259 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4269 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
} }
} }
vPortRecursiveLock(0, spin_lock_instance(14), ( ( char ) 0 )); vPortRecursiveLock(0, spin_lock_instance(14), ( ( char ) 0 ));
@ -14125,7 +14142,7 @@ BaseType_t xTaskRemoveFromEventList( const List_t * pxEventList )
{ {
( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) ); ( void ) uxListRemove( &( pxUnblockedTCB->xStateListItem ) );
; { if( ( ( pxUnblockedTCB )->uxPriority ) > uxTopReadyPriority ) { uxTopReadyPriority = ( ( pxUnblockedTCB )->uxPriority ); } }; vListInsertEnd( &( pxReadyTasksLists[ ( pxUnblockedTCB )->uxPriority ] ), &( ( pxUnblockedTCB )->xStateListItem ) ); ; ; { if( ( ( pxUnblockedTCB )->uxPriority ) > uxTopReadyPriority ) { uxTopReadyPriority = ( ( pxUnblockedTCB )->uxPriority ); } }; vListInsertEnd( &( pxReadyTasksLists[ ( pxUnblockedTCB )->uxPriority ] ), &( ( pxUnblockedTCB )->xStateListItem ) ); ;
// # 4385 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4395 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
} }
else else
{ {
@ -14165,7 +14182,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
pxUnblockedTCB = ( ( pxEventListItem )->pvOwner ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */ pxUnblockedTCB = ( ( pxEventListItem )->pvOwner ); /*lint !e9079 void * is used as this macro is used with timers and co-routines too. Alignment is known to be fine as the type of the pointer stored and retrieved is the same. */
assert(pxUnblockedTCB); assert(pxUnblockedTCB);
( void ) uxListRemove( pxEventListItem ); ( void ) uxListRemove( pxEventListItem );
// # 4439 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4449 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/* Remove the task from the delayed list and add it to the ready list. The /* Remove the task from the delayed list and add it to the ready list. The
* scheduler is suspended so interrupts will not be accessing the ready * scheduler is suspended so interrupts will not be accessing the ready
* lists. */ * lists. */
@ -14338,7 +14355,7 @@ void vTaskMissedYield( void )
for( ; ; ) for( ; ; )
{ {
// # 4622 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4632 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
{ {
/* When using preemption tasks of equal priority will be /* When using preemption tasks of equal priority will be
* timesliced. If a task that is sharing the idle priority is ready * timesliced. If a task that is sharing the idle priority is ready
@ -14359,7 +14376,7 @@ void vTaskMissedYield( void )
; ;
} }
} }
// # 4659 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4669 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
} }
} }
@ -14393,7 +14410,7 @@ static void prvIdleTask( void * pvParameters )
/* See if any tasks have deleted themselves - if so then the idle task /* See if any tasks have deleted themselves - if so then the idle task
* is responsible for freeing the deleted task's TCB and stack. */ * is responsible for freeing the deleted task's TCB and stack. */
prvCheckTasksWaitingTermination(); prvCheckTasksWaitingTermination();
// # 4704 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4714 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
{ {
/* When using preemption tasks of equal priority will be /* When using preemption tasks of equal priority will be
* timesliced. If a task that is sharing the idle priority is ready * timesliced. If a task that is sharing the idle priority is ready
@ -14414,16 +14431,16 @@ static void prvIdleTask( void * pvParameters )
; ;
} }
} }
// # 4740 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4750 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/* This conditional compilation should use inequality to 0, not equality /* This conditional compilation should use inequality to 0, not equality
* to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when * to 1. This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
* user defined low power mode implementations require * user defined low power mode implementations require
* configUSE_TICKLESS_IDLE to be set to a value other than 1. */ * configUSE_TICKLESS_IDLE to be set to a value other than 1. */
// # 4805 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4815 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
} }
} }
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
// # 4855 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4865 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -14468,7 +14485,7 @@ static void prvIdleTask( void * pvParameters )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
// # 4915 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 4925 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvInitialiseTaskLists( void ) static void prvInitialiseTaskLists( void )
@ -14570,7 +14587,7 @@ static void prvCheckTasksWaitingTermination( void )
{ {
pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority; pxTaskStatus->uxBasePriority = pxTCB->uxBasePriority;
} }
// # 5027 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 5037 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
{ {
pxTaskStatus->ulRunTimeCounter = 0; pxTaskStatus->ulRunTimeCounter = 0;
} }
@ -14701,7 +14718,7 @@ static void prvCheckTasksWaitingTermination( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
// # 5196 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 5206 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
@ -14758,7 +14775,7 @@ static void prvCheckTasksWaitingTermination( void )
free( (void*) pxTCB->pxStack); free( (void*) pxTCB->pxStack);
free( (void*) pxTCB); free( (void*) pxTCB);
} }
// # 5279 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 5289 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
} }
@ -14788,14 +14805,16 @@ static void prvResetNextTaskUnblockTime( void )
TaskHandle_t xTaskGetCurrentTaskHandle( void ) TaskHandle_t xTaskGetCurrentTaskHandle( void )
///@ requires interruptState_p(?coreID, ?irpState); //@ requires interruptState_p(?coreID, ?irpState);
///@ ensures interruptState_p(coreID, irpState) &*& false; //@ ensures interruptState_p(coreID, irpState);
{ {
TaskHandle_t xReturn; TaskHandle_t xReturn;
uint32_t ulState; uint32_t ulState;
ulState = VF__portDISABLE_INTERRUPTS(); ulState = VF__portDISABLE_INTERRUPTS();
//@ open coreLocalGlobalVars_p();
xReturn = pxCurrentTCBs[ VF__get_core_num() ]; xReturn = pxCurrentTCBs[ VF__get_core_num() ];
//@ close coreLocalGlobalVars_p();
VF__portRESTORE_INTERRUPTS(ulState); VF__portRESTORE_INTERRUPTS(ulState);
return xReturn; return xReturn;
@ -15263,11 +15282,11 @@ void vTaskYieldWithinAPI( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
// # 5809 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 5819 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
// # 5915 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 5925 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*----------------------------------------------------------*/ /*----------------------------------------------------------*/
// # 6042 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 6052 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
TickType_t uxTaskResetEventItemValue( void ) TickType_t uxTaskResetEventItemValue( void )
@ -15541,7 +15560,7 @@ TickType_t uxTaskResetEventItemValue( void )
/* The task should not have been on an event list. */ /* The task should not have been on an event list. */
assert(( ( &( pxTCB->xEventListItem ) )->pxContainer ) == 0); assert(( ( &( pxTCB->xEventListItem ) )->pxContainer ) == 0);
// # 6333 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 6343 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
{ {
prvYieldForTask( pxTCB, ( ( char ) 0 ) ); prvYieldForTask( pxTCB, ( ( char ) 0 ) );
} }
@ -15835,7 +15854,7 @@ TickType_t uxTaskResetEventItemValue( void )
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
// # 6642 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 6652 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait, static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
@ -15911,7 +15930,7 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
} }
} }
} }
// # 6754 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c" // # 6764 "/Users/reitobia/repos2/FreeRTOS-Kernel/tasks.c"
} }
/* Code below here allows additional code to be inserted into this source file, /* Code below here allows additional code to be inserted into this source file,

View file

@ -49,7 +49,7 @@ predicate interruptState_p(uint32_t coreID, uint32_t state);
fixpoint bool interruptsDisabled_f(uint32_t); fixpoint bool interruptsDisabled_f(uint32_t);
predicate coreLocalGlobalVars() = predicate coreLocalGlobalVars_p() =
pointer(&pxCurrentTCBs[coreID_f], _); pointer(&pxCurrentTCBs[coreID_f], _);
predicate coreLocalLocked(uint32_t coreID); predicate coreLocalLocked(uint32_t coreID);

View file

@ -34,14 +34,19 @@ uint32_t VF__portDISABLE_INTERRUPTS();
//@ requires interruptState_p(?coreID, ?state); //@ requires interruptState_p(?coreID, ?state);
/*@ ensures result == state &*& /*@ ensures result == state &*&
interruptState_p(coreID, ?newState) &*& interruptState_p(coreID, ?newState) &*&
interruptsDisabled_f(newState) == true; interruptsDisabled_f(newState) == true &*&
coreLocalGlobalVars_p();
@*/ @*/
#undef portRESTORE_INTERRUPTS #undef portRESTORE_INTERRUPTS
#define portRESTORE_INTERRUPTS(ulState) VF__portRESTORE_INTERRUPTS(ulState) #define portRESTORE_INTERRUPTS(ulState) VF__portRESTORE_INTERRUPTS(ulState)
void VF__portRESTORE_INTERRUPTS(uint32_t state); void VF__portRESTORE_INTERRUPTS(uint32_t ulState);
//@ requires interruptState_p(?coreID, _); /*@ requires interruptState_p(?coreID, ?tmpState) &*&
/*@ ensures interruptState_p(coreID, state); interruptsDisabled_f(tmpState) == true
? coreLocalGlobalVars_p()
: true;
@*/
/*@ ensures interruptState_p(coreID, ulState);
@*/ @*/
#undef portGET_TASK_LOCK #undef portGET_TASK_LOCK