Verified runtime assertion that running task is either scheduled or yielding.

This commit is contained in:
Tobias Reinhard 2022-12-04 11:54:07 -05:00
parent 61bffc4617
commit 00bb9d4a17
2 changed files with 59 additions and 5 deletions

22
tasks.c
View file

@ -1058,7 +1058,8 @@ static void prvYieldForTask( TCB_t * pxTCB,
&*& &*&
// Write permission for task scheduled on this core // Write permission for task scheduled on this core
[1/2]sharedSeg_TCB_p(gCurrentTCB, ?gCurrentTCB_state) &*& [1/2]sharedSeg_TCB_p(gCurrentTCB, ?gCurrentTCB_state) &*&
gCurrentTCB_state != taskTASK_NOT_RUNNING &*& // gCurrentTCB_state != taskTASK_NOT_RUNNING &*&
(gCurrentTCB_state == coreID_f() || gCurrentTCB_state == taskTASK_YIELDING) &*&
nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state
&*& &*&
// TODO: // TODO:
@ -1221,7 +1222,6 @@ static void prvYieldForTask( TCB_t * pxTCB,
} }
else if( pxTCB == pxCurrentTCBs[ xCoreID ] ) else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
{ {
//@ assume(false);
configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_YIELDING ) ); configASSERT( ( pxTCB->xTaskRunState == xCoreID ) || ( pxTCB->xTaskRunState == taskTASK_YIELDING ) );
#if ( configNUM_CORES > 1 ) #if ( configNUM_CORES > 1 )
#if ( configUSE_CORE_AFFINITY == 1 ) #if ( configUSE_CORE_AFFINITY == 1 )
@ -1229,13 +1229,27 @@ static void prvYieldForTask( TCB_t * pxTCB,
#endif #endif
#endif #endif
{ {
//@ assert( pxTCB->xTaskRunState != taskTASK_NOT_RUNNING );
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates)) );
//@ assert( nth(index_of(pxTCB, gTasks), gStates) != taskTASK_NOT_RUNNING);
/* The task is already running on this core, mark it as scheduled */ /* The task is already running on this core, mark it as scheduled */
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID; pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
xTaskScheduled = pdTRUE; xTaskScheduled = pdTRUE;
/*@ list<TaskRunning_t> gEquivStates
= update(index_of(pxTCB, gTasks), xCoreID, gStates);
@*/
//@ open exists_in_taskISRLockInv_p(gTasks, gStates);
/*@ scheduleRunning_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
(pxTCB, gTasks, gStates, gEquivStates, xCoreID);
@*/
//@ close exists_in_taskISRLockInv_p(gTasks, gEquivStates);
} }
} }
/*@ /*@
if( !gPxTCB_not_running ) { // else branch of swapping if-statement above if( !gPxTCB_not_running && pxTCB != gCurrentTCB ) {
assert( exists_in_taskISRLockInv_p(gTasks, gStates) );
// Put read permission for `pxTCB` back // Put read permission for `pxTCB` back
close [1/2]sharedSeg_TCB_p(pxTCB, _); close [1/2]sharedSeg_TCB_p(pxTCB, _);
close readOnly_sharedSeg_TCB_p(gTasks, gStates)(pxTCB); close readOnly_sharedSeg_TCB_p(gTasks, gStates)(pxTCB);
@ -1256,7 +1270,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
break; break;
} }
//@ assert( exists_in_taskISRLockInv_p(gTasks, ?gStatesEnd) ); //@ assert( exists_in_taskISRLockInv_p(gTasks, ?gStatesEnd) );
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStatesEnd)) ); //@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStatesEnd)) );
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStatesEnd)) ); //@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStatesEnd)) );
} while( pxTaskItem != pxLastTaskItem ); } while( pxTaskItem != pxLastTaskItem );

View file

@ -108,7 +108,8 @@ predicate taskISRLockInv_p() =
// (RP-Current) Read permission for task currently scheduled on this core // (RP-Current) Read permission for task currently scheduled on this core
// (RP-All) + (RP-Current) => Write permission for scheduled task // (RP-All) + (RP-Current) => Write permission for scheduled task
[1/2]sharedSeg_TCB_p(gCurrentTCB, ?gCurrentTCB_state) &*& [1/2]sharedSeg_TCB_p(gCurrentTCB, ?gCurrentTCB_state) &*&
gCurrentTCB_state != taskTASK_NOT_RUNNING &*& // gCurrentTCB_state != taskTASK_NOT_RUNNING &*&
(gCurrentTCB_state == coreID_f() || gCurrentTCB_state == taskTASK_YIELDING) &*&
nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state
&*& &*&
// (RP-Unsched) Read permissions for unscheduled tasks // (RP-Unsched) Read permissions for unscheduled tasks
@ -397,6 +398,45 @@ ensures
close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)(startedTask); close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)(startedTask);
foreach_unremove(startedTask, tasks); foreach_unremove(startedTask, tasks);
} }
lemma void scheduleRunning_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
(TCB_t* runningTask, list<void*> tasks,
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
int coreID)
requires
distinct(tasks) == true &*&
length(tasks) == length(states) &*&
mem(runningTask, tasks) == true &*&
(nth(index_of(runningTask, tasks), states) == coreID
|| nth(index_of(runningTask, tasks), states) == taskTASK_YIELDING)
&*&
foreach(tasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)) &*&
updatedStates == update(index_of(runningTask, tasks), coreID, states) &*&
0 <= coreID &*& coreID < configNUM_CORES;
ensures
foreach(tasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)) &*&
nth(index_of(runningTask, tasks), updatedStates) == coreID;
{
switch(tasks) {
case nil:
open foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states));
close foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates));
case cons(h, t):
foreach_remove(runningTask, tasks);
distinct_remove(runningTask, tasks);
distinct_mem_remove(runningTask, tasks);
remove_result_subset(runningTask, tasks);
updateUnaffectedStates_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
(runningTask, tasks, remove(runningTask, tasks),
states, updatedStates, coreID);
open readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)(runningTask);
close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)(runningTask);
foreach_unremove(runningTask, tasks);
}
}
@*/ @*/