mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-11 14:15:12 -05:00
Renamed TCB predicates to convey access rights expressed by each predicate. Updated lemmas accordinly.
This commit is contained in:
parent
63154a4add
commit
6dc6c5dbbe
5 changed files with 121 additions and 131 deletions
|
|
@ -96,14 +96,14 @@
|
||||||
#define taskCHECK_FOR_STACK_OVERFLOW() VF__taskCHECK_FOR_STACK_OVERFLOW()
|
#define taskCHECK_FOR_STACK_OVERFLOW() VF__taskCHECK_FOR_STACK_OVERFLOW()
|
||||||
|
|
||||||
void VF__taskCHECK_FOR_STACK_OVERFLOW()
|
void VF__taskCHECK_FOR_STACK_OVERFLOW()
|
||||||
/*@ requires prvSeg_TCB_p(?gCurrentTCB, ?ulFreeBytesOnStack) &*&
|
/*@ requires TCB_stack_p(?gCurrentTCB, ?ulFreeBytesOnStack) &*&
|
||||||
coreLocalSeg_TCB_p(gCurrentTCB, ?uxCriticalNesting) &*&
|
coreLocalSeg_TCB_p(gCurrentTCB, ?uxCriticalNesting) &*&
|
||||||
// chunks required by `pxCurrentTCB` aka `xTaskGetCurrentTaskHandle()`
|
// chunks required by `pxCurrentTCB` aka `xTaskGetCurrentTaskHandle()`
|
||||||
interruptState_p(coreID_f(), ?state) &*&
|
interruptState_p(coreID_f(), ?state) &*&
|
||||||
interruptsDisabled_f(state) == true &*&
|
interruptsDisabled_f(state) == true &*&
|
||||||
pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB);
|
pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB);
|
||||||
@*/
|
@*/
|
||||||
/*@ ensures prvSeg_TCB_p(gCurrentTCB, ulFreeBytesOnStack) &*&
|
/*@ ensures TCB_stack_p(gCurrentTCB, ulFreeBytesOnStack) &*&
|
||||||
coreLocalSeg_TCB_p(gCurrentTCB, uxCriticalNesting) &*&
|
coreLocalSeg_TCB_p(gCurrentTCB, uxCriticalNesting) &*&
|
||||||
// chunks required by `pxCurrentTCB` aka `xTaskGetCurrentTaskHandle()`
|
// chunks required by `pxCurrentTCB` aka `xTaskGetCurrentTaskHandle()`
|
||||||
interruptState_p(coreID_f(), state) &*&
|
interruptState_p(coreID_f(), state) &*&
|
||||||
|
|
@ -111,7 +111,7 @@
|
||||||
pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB); \
|
pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB); \
|
||||||
@*/ \
|
@*/ \
|
||||||
{ \
|
{ \
|
||||||
/*@ open prvSeg_TCB_p(gCurrentTCB, ulFreeBytesOnStack); @*/ \
|
/*@ open TCB_stack_p(gCurrentTCB, ulFreeBytesOnStack); @*/ \
|
||||||
/*@ assert( stack_p(?pxStack, ?ulStackDepth, ?pxTopOfStack, \
|
/*@ assert( stack_p(?pxStack, ?ulStackDepth, ?pxTopOfStack, \
|
||||||
?ulFreeBytes, ?ulUsedCells, ?ulUnalignedBytes) ); \
|
?ulFreeBytes, ?ulUsedCells, ?ulUnalignedBytes) ); \
|
||||||
@*/ \
|
@*/ \
|
||||||
|
|
@ -139,7 +139,7 @@
|
||||||
/*@ close stack_p(pxStack, ulStackDepth, pxTopOfStack, \
|
/*@ close stack_p(pxStack, ulStackDepth, pxTopOfStack, \
|
||||||
ulFreeBytes, ulUsedCells, ulUnalignedBytes); \
|
ulFreeBytes, ulUsedCells, ulUnalignedBytes); \
|
||||||
@*/ \
|
@*/ \
|
||||||
/*@ close prvSeg_TCB_p(gCurrentTCB, ulFreeBytesOnStack); @*/ \
|
/*@ close TCB_stack_p(gCurrentTCB, ulFreeBytesOnStack); @*/ \
|
||||||
TCB_t* tcb1 = pxCurrentTCB; \
|
TCB_t* tcb1 = pxCurrentTCB; \
|
||||||
TCB_t* tcb2 = pxCurrentTCB; \
|
TCB_t* tcb2 = pxCurrentTCB; \
|
||||||
vApplicationStackOverflowHook( ( TaskHandle_t ) tcb1, tcb2->pcTaskName ); \
|
vApplicationStackOverflowHook( ( TaskHandle_t ) tcb1, tcb2->pcTaskName ); \
|
||||||
|
|
@ -151,7 +151,7 @@
|
||||||
chars_split((char*) pxStack, ulFreeBytesOnStack); \
|
chars_split((char*) pxStack, ulFreeBytesOnStack); \
|
||||||
close stack_p(pxStack, ulStackDepth, pxTopOfStack, \
|
close stack_p(pxStack, ulStackDepth, pxTopOfStack, \
|
||||||
ulFreeBytes, ulUsedCells, ulUnalignedBytes); \
|
ulFreeBytes, ulUsedCells, ulUnalignedBytes); \
|
||||||
close prvSeg_TCB_p(gCurrentTCB, ulFreeBytesOnStack); \
|
close TCB_stack_p(gCurrentTCB, ulFreeBytesOnStack); \
|
||||||
} \
|
} \
|
||||||
@*/ \
|
@*/ \
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1863,10 +1863,10 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL
|
||||||
*/
|
*/
|
||||||
void vApplicationStackOverflowHook( TaskHandle_t xTask,
|
void vApplicationStackOverflowHook( TaskHandle_t xTask,
|
||||||
char * pcTaskName );
|
char * pcTaskName );
|
||||||
/*@ requires prvSeg_TCB_p(xTask, ?ulFreeBytesOnStack) &*&
|
/*@ requires TCB_stack_p(xTask, ?ulFreeBytesOnStack) &*&
|
||||||
coreLocalSeg_TCB_p(xTask, ?uxCriticalNesting);
|
coreLocalSeg_TCB_p(xTask, ?uxCriticalNesting);
|
||||||
@*/
|
@*/
|
||||||
/*@ ensures prvSeg_TCB_p(xTask, ulFreeBytesOnStack) &*&
|
/*@ ensures TCB_stack_p(xTask, ulFreeBytesOnStack) &*&
|
||||||
coreLocalSeg_TCB_p(xTask, uxCriticalNesting);
|
coreLocalSeg_TCB_p(xTask, uxCriticalNesting);
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,30 +49,20 @@ predicate TCB_p(TCB_t * tcb, uint32_t ulFreeBytesOnStack) =
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
// We have to segment TCBs into:
|
// This predicate represents write access to a TCB's stack.
|
||||||
// (i) public parts that can be accessed by anyone after
|
predicate TCB_stack_p(TCB_t* tcb, uint32_t ulFreeBytesOnStack) =
|
||||||
// following the appropriote synchronization steps and
|
|
||||||
// (ii) private parts that may only be used by the task itself
|
|
||||||
// which the TCB represents
|
|
||||||
//
|
|
||||||
// The predicates below will be expanded iteratively.
|
|
||||||
|
|
||||||
// This predicate captures the private part of a TCB that should only be
|
|
||||||
// accessed by the TCB represents or under specific circumstances where
|
|
||||||
// we are certain that the task is not running.
|
|
||||||
predicate prvSeg_TCB_p(TCB_t* tcb, uint32_t ulFreeBytesOnStack) =
|
|
||||||
tcb->pxStack |-> ?stackPtr &*&
|
tcb->pxStack |-> ?stackPtr &*&
|
||||||
tcb->pxTopOfStack |-> ?topPtr &*&
|
tcb->pxTopOfStack |-> ?topPtr &*&
|
||||||
stack_p(stackPtr, ?ulStackDepth, topPtr,
|
stack_p(stackPtr, ?ulStackDepth, topPtr,
|
||||||
ulFreeBytesOnStack, ?ulUsedCells, ?ulUnalignedBytes);
|
ulFreeBytesOnStack, ?ulUsedCells, ?ulUnalignedBytes);
|
||||||
|
|
||||||
// This predicate represents a shared part of a TCB that can be accessed by
|
// This predicate represents write access to the run state of a TCB.
|
||||||
// anyone. Note that this predicate only contains the minimal access rights
|
predicate TCB_runState_p(TCB_t* tcb, TaskRunning_t state;) =
|
||||||
// required by the `vTaskSwitchContext` proof. It can be extended in the future
|
|
||||||
// as needed.
|
|
||||||
predicate sharedSeg_TCB_p(TCB_t* tcb, TaskRunning_t state;) =
|
|
||||||
tcb->xTaskRunState |-> state;
|
tcb->xTaskRunState |-> state;
|
||||||
|
|
||||||
|
// This predicate represents write access to the nesting level of a TCB.
|
||||||
|
// Entering a critical section increases the nesting level. Leaving it,
|
||||||
|
// decreases it.
|
||||||
predicate coreLocalSeg_TCB_p(TCB_t* tcb, UBaseType_t uxCriticalNesting) =
|
predicate coreLocalSeg_TCB_p(TCB_t* tcb, UBaseType_t uxCriticalNesting) =
|
||||||
tcb->uxCriticalNesting |-> uxCriticalNesting;
|
tcb->uxCriticalNesting |-> uxCriticalNesting;
|
||||||
@*/
|
@*/
|
||||||
|
|
|
||||||
|
|
@ -106,14 +106,14 @@ predicate _taskISRLockInv_p(UBaseType_t gTopReadyPriority) =
|
||||||
// (RP-All) Read permissions for every task
|
// (RP-All) Read permissions for every task
|
||||||
// and recording of task states in state list
|
// and recording of task states in state list
|
||||||
// (∀t ∈ gTasks.
|
// (∀t ∈ gTasks.
|
||||||
// [1/2]sharedSeg_TCB_p(t, _))
|
// [1/2]TCB_runState_p(t, _))
|
||||||
// ∧
|
// ∧
|
||||||
// ∀i. ∀t. gTasks[i] == t -> gStates[i] == t->xTaskRunState
|
// ∀i. ∀t. gTasks[i] == t -> gStates[i] == t->xTaskRunState
|
||||||
foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStates))
|
foreach(gTasks, readOnly_TCB_runState_p(gTasks, gStates))
|
||||||
&*&
|
&*&
|
||||||
// (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]TCB_runState_p(gCurrentTCB, ?gCurrentTCB_state) &*&
|
||||||
// gCurrentTCB_state != taskTASK_NOT_RUNNING &*&
|
// gCurrentTCB_state != taskTASK_NOT_RUNNING &*&
|
||||||
(gCurrentTCB_state == coreID_f() || gCurrentTCB_state == taskTASK_YIELDING) &*&
|
(gCurrentTCB_state == coreID_f() || gCurrentTCB_state == taskTASK_YIELDING) &*&
|
||||||
nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state
|
nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state
|
||||||
|
|
@ -122,7 +122,7 @@ predicate _taskISRLockInv_p(UBaseType_t gTopReadyPriority) =
|
||||||
// (RP-All) + (RP-Unsched) => Write permissions for unscheduled tasks
|
// (RP-All) + (RP-Unsched) => Write permissions for unscheduled tasks
|
||||||
// ∀t ∈ tasks. t->xTaskState == taskTASK_NOT_RUNNING
|
// ∀t ∈ tasks. t->xTaskState == taskTASK_NOT_RUNNING
|
||||||
// -> [1/2]shared_TCB_p(t, taskTASK_NOT_RUNNING)
|
// -> [1/2]shared_TCB_p(t, taskTASK_NOT_RUNNING)
|
||||||
foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates))
|
foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates))
|
||||||
&*&
|
&*&
|
||||||
readyLists_p(?gCellLists, ?gOwnerLists)
|
readyLists_p(?gCellLists, ?gOwnerLists)
|
||||||
&*&
|
&*&
|
||||||
|
|
@ -172,18 +172,18 @@ fixpoint bool mem_list_elem<t>(list<t> xs, t x) {
|
||||||
|
|
||||||
// Auxiliary predicate to allow foreach-quantification about fraction
|
// Auxiliary predicate to allow foreach-quantification about fraction
|
||||||
// and reflection of `t->xTaskRunState` in state list.
|
// and reflection of `t->xTaskRunState` in state list.
|
||||||
predicate_ctor readOnly_sharedSeg_TCB_p
|
predicate_ctor readOnly_TCB_runState_p
|
||||||
(list<void*> tasks, list<TaskRunning_t> states)
|
(list<void*> tasks, list<TaskRunning_t> states)
|
||||||
(TCB_t* t;) =
|
(TCB_t* t;) =
|
||||||
mem(t, tasks) == true &*&
|
mem(t, tasks) == true &*&
|
||||||
[1/2]sharedSeg_TCB_p(t, nth(index_of(t, tasks), states));
|
[1/2]TCB_runState_p(t, nth(index_of(t, tasks), states));
|
||||||
|
|
||||||
predicate_ctor readOnly_sharedSeg_TCB_IF_not_running_p
|
predicate_ctor readOnly_TCB_runState_IF_not_running_p
|
||||||
(list<void*> tasks, list<TaskRunning_t> states)
|
(list<void*> tasks, list<TaskRunning_t> states)
|
||||||
(TCB_t* t;) =
|
(TCB_t* t;) =
|
||||||
mem(t, tasks) == true &*&
|
mem(t, tasks) == true &*&
|
||||||
nth(index_of(t, tasks), states) == taskTASK_NOT_RUNNING
|
nth(index_of(t, tasks), states) == taskTASK_NOT_RUNNING
|
||||||
? [1/2]sharedSeg_TCB_p(t, taskTASK_NOT_RUNNING)
|
? [1/2]TCB_runState_p(t, taskTASK_NOT_RUNNING)
|
||||||
: true;
|
: true;
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
|
|
@ -201,16 +201,16 @@ lemma void nonauto_nth_update<t>(int i, int j, t y, list<t> xs);
|
||||||
// TODO: Move lemmas below to separate header file.
|
// TODO: Move lemmas below to separate header file.
|
||||||
|
|
||||||
/*@
|
/*@
|
||||||
lemma void update_readOnly_sharedSeg_TCB(TCB_t* t,
|
lemma void update_readOnly_TCB_runState(TCB_t* t,
|
||||||
list<void*> tasks,
|
list<void*> tasks,
|
||||||
list<TaskRunning_t> states,
|
list<TaskRunning_t> states,
|
||||||
int updatedIndex,
|
int updatedIndex,
|
||||||
TaskRunning_t s)
|
TaskRunning_t s)
|
||||||
requires readOnly_sharedSeg_TCB_p(tasks, states)(t) &*&
|
requires readOnly_TCB_runState_p(tasks, states)(t) &*&
|
||||||
updatedIndex != index_of(t, tasks) &*&
|
updatedIndex != index_of(t, tasks) &*&
|
||||||
mem(t, tasks) == true &*&
|
mem(t, tasks) == true &*&
|
||||||
length(tasks) == length(states);
|
length(tasks) == length(states);
|
||||||
ensures readOnly_sharedSeg_TCB_p(tasks, update(updatedIndex, s, states))(t);
|
ensures readOnly_TCB_runState_p(tasks, update(updatedIndex, s, states))(t);
|
||||||
{
|
{
|
||||||
list<TaskRunning_t> states2 = update(updatedIndex, s, states);
|
list<TaskRunning_t> states2 = update(updatedIndex, s, states);
|
||||||
int t_index = index_of(t, tasks);
|
int t_index = index_of(t, tasks);
|
||||||
|
|
@ -218,20 +218,20 @@ ensures readOnly_sharedSeg_TCB_p(tasks, update(updatedIndex, s, states))(t);
|
||||||
if( updatedIndex < 0 || updatedIndex >= length(states) ) {
|
if( updatedIndex < 0 || updatedIndex >= length(states) ) {
|
||||||
update_out_of_bounds(updatedIndex, s, states);
|
update_out_of_bounds(updatedIndex, s, states);
|
||||||
} else {
|
} else {
|
||||||
open readOnly_sharedSeg_TCB_p(tasks, states)(t);
|
open readOnly_TCB_runState_p(tasks, states)(t);
|
||||||
open [1/2]sharedSeg_TCB_p(t, nth(t_index, states));
|
open [1/2]TCB_runState_p(t, nth(t_index, states));
|
||||||
|
|
||||||
mem_index_of(t, tasks);
|
mem_index_of(t, tasks);
|
||||||
nth_update(t_index, updatedIndex, s, states);
|
nth_update(t_index, updatedIndex, s, states);
|
||||||
assert( nth(t_index, states) == nth(t_index, states2) );
|
assert( nth(t_index, states) == nth(t_index, states2) );
|
||||||
|
|
||||||
close [1/2]sharedSeg_TCB_p(t, nth(t_index, states2));
|
close [1/2]TCB_runState_p(t, nth(t_index, states2));
|
||||||
close readOnly_sharedSeg_TCB_p(tasks, states2)(t);
|
close readOnly_TCB_runState_p(tasks, states2)(t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lemma void update_foreach_readOnly_sharedSeg_TCB(TCB_t* updatedTask,
|
lemma void update_foreach_readOnly_TCB_runState(TCB_t* updatedTask,
|
||||||
list<void*> tasks,
|
list<void*> tasks,
|
||||||
list<void*> subTasks,
|
list<void*> subTasks,
|
||||||
list<TaskRunning_t> states,
|
list<TaskRunning_t> states,
|
||||||
|
|
@ -240,37 +240,37 @@ lemma void update_foreach_readOnly_sharedSeg_TCB(TCB_t* updatedTask,
|
||||||
requires
|
requires
|
||||||
mem(updatedTask, tasks) == true &*&
|
mem(updatedTask, tasks) == true &*&
|
||||||
length(tasks) == length(states) &*&
|
length(tasks) == length(states) &*&
|
||||||
foreach(subTasks, readOnly_sharedSeg_TCB_p(tasks, states)) &*&
|
foreach(subTasks, readOnly_TCB_runState_p(tasks, states)) &*&
|
||||||
states2 == update(index_of(updatedTask, tasks), s, states) &*&
|
states2 == update(index_of(updatedTask, tasks), s, states) &*&
|
||||||
distinct(tasks) == true &*&
|
distinct(tasks) == true &*&
|
||||||
mem(updatedTask, subTasks) == false &*&
|
mem(updatedTask, subTasks) == false &*&
|
||||||
subset(subTasks, tasks) == true;
|
subset(subTasks, tasks) == true;
|
||||||
ensures
|
ensures
|
||||||
foreach(subTasks, readOnly_sharedSeg_TCB_p(tasks, states2));
|
foreach(subTasks, readOnly_TCB_runState_p(tasks, states2));
|
||||||
{
|
{
|
||||||
switch(subTasks) {
|
switch(subTasks) {
|
||||||
case nil:
|
case nil:
|
||||||
open foreach(nil, readOnly_sharedSeg_TCB_p(tasks, states));
|
open foreach(nil, readOnly_TCB_runState_p(tasks, states));
|
||||||
close foreach(nil, readOnly_sharedSeg_TCB_p(tasks, states2));
|
close foreach(nil, readOnly_TCB_runState_p(tasks, states2));
|
||||||
case cons(h, rest):
|
case cons(h, rest):
|
||||||
int index = index_of(updatedTask, tasks);
|
int index = index_of(updatedTask, tasks);
|
||||||
// distinct_mem_remove(t, tasks);
|
// distinct_mem_remove(t, tasks);
|
||||||
// neq_mem_remove(h, t, tasks);
|
// neq_mem_remove(h, t, tasks);
|
||||||
// index_of_different(h, t, tasks);
|
// index_of_different(h, t, tasks);
|
||||||
open foreach(subTasks, readOnly_sharedSeg_TCB_p(tasks, states));
|
open foreach(subTasks, readOnly_TCB_runState_p(tasks, states));
|
||||||
assert( updatedTask != h );
|
assert( updatedTask != h );
|
||||||
index_of_different(updatedTask, h, tasks);
|
index_of_different(updatedTask, h, tasks);
|
||||||
assert( index != index_of(h, tasks) );
|
assert( index != index_of(h, tasks) );
|
||||||
update_readOnly_sharedSeg_TCB(h, tasks, states, index, s);
|
update_readOnly_TCB_runState(h, tasks, states, index, s);
|
||||||
assert( mem(updatedTask, rest) == false );
|
assert( mem(updatedTask, rest) == false );
|
||||||
update_foreach_readOnly_sharedSeg_TCB(updatedTask, tasks, rest,
|
update_foreach_readOnly_TCB_runState(updatedTask, tasks, rest,
|
||||||
states, states2, s);
|
states, states2, s);
|
||||||
close foreach(subTasks, readOnly_sharedSeg_TCB_p(tasks, states2));
|
close foreach(subTasks, readOnly_TCB_runState_p(tasks, states2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lemma void close_updated_foreach_readOnly_sharedSeg_TCB(TCB_t* updatedTask,
|
lemma void close_updated_foreach_readOnly_TCB_runState(TCB_t* updatedTask,
|
||||||
list<void*> tasks,
|
list<void*> tasks,
|
||||||
list<TaskRunning_t> states,
|
list<TaskRunning_t> states,
|
||||||
list<TaskRunning_t> states2,
|
list<TaskRunning_t> states2,
|
||||||
|
|
@ -279,45 +279,45 @@ requires
|
||||||
mem(updatedTask, tasks) == true &*&
|
mem(updatedTask, tasks) == true &*&
|
||||||
length(states) == length(tasks) &*&
|
length(states) == length(tasks) &*&
|
||||||
distinct(tasks) == true &*&
|
distinct(tasks) == true &*&
|
||||||
foreach(remove(updatedTask, tasks), readOnly_sharedSeg_TCB_p(tasks, states)) &*&
|
foreach(remove(updatedTask, tasks), readOnly_TCB_runState_p(tasks, states)) &*&
|
||||||
states2 == update(index_of(updatedTask, tasks), s, states) &*&
|
states2 == update(index_of(updatedTask, tasks), s, states) &*&
|
||||||
[1/2]sharedSeg_TCB_p(updatedTask, s);
|
[1/2]TCB_runState_p(updatedTask, s);
|
||||||
ensures
|
ensures
|
||||||
foreach(tasks, readOnly_sharedSeg_TCB_p(tasks, states2));
|
foreach(tasks, readOnly_TCB_runState_p(tasks, states2));
|
||||||
{
|
{
|
||||||
distinct_mem_remove(updatedTask, tasks);
|
distinct_mem_remove(updatedTask, tasks);
|
||||||
remove_result_subset(updatedTask, tasks);
|
remove_result_subset(updatedTask, tasks);
|
||||||
|
|
||||||
close readOnly_sharedSeg_TCB_p(tasks, states2)(updatedTask);
|
close readOnly_TCB_runState_p(tasks, states2)(updatedTask);
|
||||||
update_foreach_readOnly_sharedSeg_TCB(updatedTask, tasks,
|
update_foreach_readOnly_TCB_runState(updatedTask, tasks,
|
||||||
remove(updatedTask, tasks),
|
remove(updatedTask, tasks),
|
||||||
states, states2, s);
|
states, states2, s);
|
||||||
foreach_unremove(updatedTask, tasks);
|
foreach_unremove(updatedTask, tasks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
lemma void stopUpdate_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
lemma void stopUpdate_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(TCB_t* stoppedTask, list<void*> tasks, list<void*> subTasks,
|
(TCB_t* stoppedTask, list<void*> tasks, list<void*> subTasks,
|
||||||
list<TaskRunning_t> states, list<TaskRunning_t> states2)
|
list<TaskRunning_t> states, list<TaskRunning_t> states2)
|
||||||
requires
|
requires
|
||||||
distinct(tasks) == true &*&
|
distinct(tasks) == true &*&
|
||||||
distinct(subTasks) == true &*&
|
distinct(subTasks) == true &*&
|
||||||
length(tasks) == length(states) &*&
|
length(tasks) == length(states) &*&
|
||||||
foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)) &*&
|
foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, states)) &*&
|
||||||
states2 == update(index_of(stoppedTask, tasks), taskTASK_NOT_RUNNING, states) &*&
|
states2 == update(index_of(stoppedTask, tasks), taskTASK_NOT_RUNNING, states) &*&
|
||||||
nth(index_of(stoppedTask, tasks), states) != taskTASK_NOT_RUNNING &*&
|
nth(index_of(stoppedTask, tasks), states) != taskTASK_NOT_RUNNING &*&
|
||||||
subset(subTasks, tasks) == true &*&
|
subset(subTasks, tasks) == true &*&
|
||||||
mem(stoppedTask, tasks) == true &*&
|
mem(stoppedTask, tasks) == true &*&
|
||||||
mem(stoppedTask, subTasks)
|
mem(stoppedTask, subTasks)
|
||||||
? [1/2]sharedSeg_TCB_p(stoppedTask, taskTASK_NOT_RUNNING)
|
? [1/2]TCB_runState_p(stoppedTask, taskTASK_NOT_RUNNING)
|
||||||
: true;
|
: true;
|
||||||
ensures
|
ensures
|
||||||
foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states2));
|
foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, states2));
|
||||||
{
|
{
|
||||||
switch(subTasks) {
|
switch(subTasks) {
|
||||||
case nil:
|
case nil:
|
||||||
open foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states));
|
open foreach(nil, readOnly_TCB_runState_IF_not_running_p(tasks, states));
|
||||||
close foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states2));
|
close foreach(nil, readOnly_TCB_runState_IF_not_running_p(tasks, states2));
|
||||||
case cons(h, t):
|
case cons(h, t):
|
||||||
if( h == stoppedTask ) {
|
if( h == stoppedTask ) {
|
||||||
assert( remove(stoppedTask, subTasks) == t );
|
assert( remove(stoppedTask, subTasks) == t );
|
||||||
|
|
@ -333,17 +333,17 @@ ensures
|
||||||
}
|
}
|
||||||
|
|
||||||
nth_update(index_of(stoppedTask, tasks), index_of(stoppedTask, tasks), taskTASK_NOT_RUNNING, states);
|
nth_update(index_of(stoppedTask, tasks), index_of(stoppedTask, tasks), taskTASK_NOT_RUNNING, states);
|
||||||
open foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states));
|
open foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, states));
|
||||||
open readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)(h);
|
open readOnly_TCB_runState_IF_not_running_p(tasks, states)(h);
|
||||||
assert( nth(index_of(stoppedTask, tasks), states2) == taskTASK_NOT_RUNNING );
|
assert( nth(index_of(stoppedTask, tasks), states2) == taskTASK_NOT_RUNNING );
|
||||||
close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states2)(h);
|
close readOnly_TCB_runState_IF_not_running_p(tasks, states2)(h);
|
||||||
stopUpdate_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
stopUpdate_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(stoppedTask, tasks, t, states, states2);
|
(stoppedTask, tasks, t, states, states2);
|
||||||
close foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states2));
|
close foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, states2));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lemma void updateUnaffectedStates_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
lemma void updateUnaffectedStates_in_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(TCB_t* updatedTask, list<void*> tasks, list<void*> subTasks,
|
(TCB_t* updatedTask, list<void*> tasks, list<void*> subTasks,
|
||||||
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
|
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
|
||||||
TaskRunning_t s)
|
TaskRunning_t s)
|
||||||
|
|
@ -354,32 +354,32 @@ requires
|
||||||
mem(updatedTask, tasks) == true &*&
|
mem(updatedTask, tasks) == true &*&
|
||||||
mem(updatedTask, subTasks) == false &*&
|
mem(updatedTask, subTasks) == false &*&
|
||||||
subset(subTasks, tasks) == true &*&
|
subset(subTasks, tasks) == true &*&
|
||||||
foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)) &*&
|
foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, states)) &*&
|
||||||
updatedStates == update(index_of(updatedTask, tasks), s, states);
|
updatedStates == update(index_of(updatedTask, tasks), s, states);
|
||||||
ensures
|
ensures
|
||||||
foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates));
|
foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates));
|
||||||
{
|
{
|
||||||
switch(subTasks) {
|
switch(subTasks) {
|
||||||
case nil:
|
case nil:
|
||||||
open foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states));
|
open foreach(nil, readOnly_TCB_runState_IF_not_running_p(tasks, states));
|
||||||
close foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates));
|
close foreach(nil, readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates));
|
||||||
case cons(h, t):
|
case cons(h, t):
|
||||||
open foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states));
|
open foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, states));
|
||||||
|
|
||||||
// Prove that update preserves state of `h`.
|
// Prove that update preserves state of `h`.
|
||||||
index_of_different(h, updatedTask, tasks);
|
index_of_different(h, updatedTask, tasks);
|
||||||
nth_update(index_of(h, tasks), index_of(updatedTask, tasks), s, states);
|
nth_update(index_of(h, tasks), index_of(updatedTask, tasks), s, states);
|
||||||
assert( nth(index_of(h, tasks), states) == nth(index_of(h, tasks), updatedStates) );
|
assert( nth(index_of(h, tasks), states) == nth(index_of(h, tasks), updatedStates) );
|
||||||
|
|
||||||
open readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)(h);
|
open readOnly_TCB_runState_IF_not_running_p(tasks, states)(h);
|
||||||
close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)(h);
|
close readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates)(h);
|
||||||
updateUnaffectedStates_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
updateUnaffectedStates_in_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(updatedTask, tasks, t, states, updatedStates, s);
|
(updatedTask, tasks, t, states, updatedStates, s);
|
||||||
close foreach(subTasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates));
|
close foreach(subTasks, readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lemma void startUpdate_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
lemma void startUpdate_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(TCB_t* startedTask, list<void*> tasks,
|
(TCB_t* startedTask, list<void*> tasks,
|
||||||
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
|
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
|
||||||
int coreID)
|
int coreID)
|
||||||
|
|
@ -387,25 +387,25 @@ requires
|
||||||
distinct(tasks) == true &*&
|
distinct(tasks) == true &*&
|
||||||
length(tasks) == length(states) &*&
|
length(tasks) == length(states) &*&
|
||||||
mem(startedTask, tasks) == true &*&
|
mem(startedTask, tasks) == true &*&
|
||||||
foreach(remove(startedTask, tasks), readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)) &*&
|
foreach(remove(startedTask, tasks), readOnly_TCB_runState_IF_not_running_p(tasks, states)) &*&
|
||||||
updatedStates == update(index_of(startedTask, tasks), coreID, states) &*&
|
updatedStates == update(index_of(startedTask, tasks), coreID, states) &*&
|
||||||
0 <= coreID &*& coreID < configNUM_CORES;
|
0 <= coreID &*& coreID < configNUM_CORES;
|
||||||
ensures
|
ensures
|
||||||
foreach(tasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates));
|
foreach(tasks, readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates));
|
||||||
{
|
{
|
||||||
distinct_remove(startedTask, tasks);
|
distinct_remove(startedTask, tasks);
|
||||||
distinct_mem_remove(startedTask, tasks);
|
distinct_mem_remove(startedTask, tasks);
|
||||||
remove_result_subset(startedTask, tasks);
|
remove_result_subset(startedTask, tasks);
|
||||||
updateUnaffectedStates_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
updateUnaffectedStates_in_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(startedTask, tasks, remove(startedTask, tasks), states, updatedStates,
|
(startedTask, tasks, remove(startedTask, tasks), states, updatedStates,
|
||||||
coreID);
|
coreID);
|
||||||
|
|
||||||
assert( foreach(remove(startedTask, tasks), readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)) );
|
assert( foreach(remove(startedTask, tasks), readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates)) );
|
||||||
close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)(startedTask);
|
close readOnly_TCB_runState_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
|
lemma void scheduleRunning_in_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(TCB_t* runningTask, list<void*> tasks,
|
(TCB_t* runningTask, list<void*> tasks,
|
||||||
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
|
list<TaskRunning_t> states, list<TaskRunning_t> updatedStates,
|
||||||
int coreID)
|
int coreID)
|
||||||
|
|
@ -416,29 +416,29 @@ requires
|
||||||
(nth(index_of(runningTask, tasks), states) == coreID
|
(nth(index_of(runningTask, tasks), states) == coreID
|
||||||
|| nth(index_of(runningTask, tasks), states) == taskTASK_YIELDING)
|
|| nth(index_of(runningTask, tasks), states) == taskTASK_YIELDING)
|
||||||
&*&
|
&*&
|
||||||
foreach(tasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)) &*&
|
foreach(tasks, readOnly_TCB_runState_IF_not_running_p(tasks, states)) &*&
|
||||||
updatedStates == update(index_of(runningTask, tasks), coreID, states) &*&
|
updatedStates == update(index_of(runningTask, tasks), coreID, states) &*&
|
||||||
0 <= coreID &*& coreID < configNUM_CORES;
|
0 <= coreID &*& coreID < configNUM_CORES;
|
||||||
ensures
|
ensures
|
||||||
foreach(tasks, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)) &*&
|
foreach(tasks, readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates)) &*&
|
||||||
nth(index_of(runningTask, tasks), updatedStates) == coreID;
|
nth(index_of(runningTask, tasks), updatedStates) == coreID;
|
||||||
{
|
{
|
||||||
switch(tasks) {
|
switch(tasks) {
|
||||||
case nil:
|
case nil:
|
||||||
open foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states));
|
open foreach(nil, readOnly_TCB_runState_IF_not_running_p(tasks, states));
|
||||||
close foreach(nil, readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates));
|
close foreach(nil, readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates));
|
||||||
case cons(h, t):
|
case cons(h, t):
|
||||||
foreach_remove(runningTask, tasks);
|
foreach_remove(runningTask, tasks);
|
||||||
|
|
||||||
distinct_remove(runningTask, tasks);
|
distinct_remove(runningTask, tasks);
|
||||||
distinct_mem_remove(runningTask, tasks);
|
distinct_mem_remove(runningTask, tasks);
|
||||||
remove_result_subset(runningTask, tasks);
|
remove_result_subset(runningTask, tasks);
|
||||||
updateUnaffectedStates_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
updateUnaffectedStates_in_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(runningTask, tasks, remove(runningTask, tasks),
|
(runningTask, tasks, remove(runningTask, tasks),
|
||||||
states, updatedStates, coreID);
|
states, updatedStates, coreID);
|
||||||
|
|
||||||
open readOnly_sharedSeg_TCB_IF_not_running_p(tasks, states)(runningTask);
|
open readOnly_TCB_runState_IF_not_running_p(tasks, states)(runningTask);
|
||||||
close readOnly_sharedSeg_TCB_IF_not_running_p(tasks, updatedStates)(runningTask);
|
close readOnly_TCB_runState_IF_not_running_p(tasks, updatedStates)(runningTask);
|
||||||
|
|
||||||
foreach_unremove(runningTask, tasks);
|
foreach_unremove(runningTask, tasks);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -909,7 +909,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
// coreLocalSeg_TCB_p(gCurrentTCB0, 0)
|
// coreLocalSeg_TCB_p(gCurrentTCB0, 0)
|
||||||
&*&
|
&*&
|
||||||
// read access to current task's stack pointer, etc
|
// read access to current task's stack pointer, etc
|
||||||
// prvSeg_TCB_p(gCurrentTCB0, ?ulFreeBytesOnStack);
|
// TCB_stack_p(gCurrentTCB0, ?ulFreeBytesOnStack);
|
||||||
true;
|
true;
|
||||||
@*/
|
@*/
|
||||||
/*@ ensures 0 <= xCoreID &*& xCoreID < configNUM_CORES &*&
|
/*@ ensures 0 <= xCoreID &*& xCoreID < configNUM_CORES &*&
|
||||||
|
|
@ -927,7 +927,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
// coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
// coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
||||||
&*&
|
&*&
|
||||||
// read access to current task's stack pointer, etc
|
// read access to current task's stack pointer, etc
|
||||||
// prvSeg_TCB_p(gCurrentTCB, ulFreeBytesOnStack);
|
// TCB_stack_p(gCurrentTCB, ulFreeBytesOnStack);
|
||||||
true;
|
true;
|
||||||
@*/
|
@*/
|
||||||
{
|
{
|
||||||
|
|
@ -1059,15 +1059,15 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
exists_in_taskISRLockInv_p(gTasks, ?gStates)
|
exists_in_taskISRLockInv_p(gTasks, ?gStates)
|
||||||
&*&
|
&*&
|
||||||
// Read permissions for every task
|
// Read permissions for every task
|
||||||
foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStates))
|
foreach(gTasks, readOnly_TCB_runState_p(gTasks, gStates))
|
||||||
&*&
|
&*&
|
||||||
// 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]TCB_runState_p(gCurrentTCB, ?gCurrentTCB_state) &*&
|
||||||
(gCurrentTCB_state == coreID_f() || gCurrentTCB_state == taskTASK_YIELDING) &*&
|
(gCurrentTCB_state == coreID_f() || gCurrentTCB_state == taskTASK_YIELDING) &*&
|
||||||
nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state
|
nth(index_of(gCurrentTCB, gTasks), gStates) == gCurrentTCB_state
|
||||||
&*&
|
&*&
|
||||||
// Write permissions for unscheduled tasks
|
// Write permissions for unscheduled tasks
|
||||||
foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates))
|
foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates))
|
||||||
&*&
|
&*&
|
||||||
subset(gOwners, gTasks) == true &*&
|
subset(gOwners, gTasks) == true &*&
|
||||||
List_array_p(&pxReadyTasksLists, uxCurrentPriority, gPrefCellLists,
|
List_array_p(&pxReadyTasksLists, uxCurrentPriority, gPrefCellLists,
|
||||||
|
|
@ -1126,7 +1126,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
//@ assert( subset(gOwners, gTasks) == true );
|
//@ assert( subset(gOwners, gTasks) == true );
|
||||||
//@ mem_subset(pxTCB, gOwners, gTasks);
|
//@ mem_subset(pxTCB, gOwners, gTasks);
|
||||||
//@ foreach_remove(pxTCB, gTasks);
|
//@ foreach_remove(pxTCB, gTasks);
|
||||||
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_sharedSeg_TCB_p(gTasks, gStates)) );
|
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_TCB_runState_p(gTasks, gStates)) );
|
||||||
|
|
||||||
/*debug_printf("Attempting to schedule %s on core %d\n", pxTCB->pcTaskName, portGET_CORE_ID() ); */
|
/*debug_printf("Attempting to schedule %s on core %d\n", pxTCB->pcTaskName, portGET_CORE_ID() ); */
|
||||||
|
|
||||||
|
|
@ -1156,9 +1156,9 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
{
|
{
|
||||||
//@ open exists_in_taskISRLockInv_p(gTasks, gStates);
|
//@ open exists_in_taskISRLockInv_p(gTasks, gStates);
|
||||||
//@ assert( nth(index_of(pxTCB, gTasks), gStates) == taskTASK_NOT_RUNNING);
|
//@ assert( nth(index_of(pxTCB, gTasks), gStates) == taskTASK_NOT_RUNNING);
|
||||||
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_sharedSeg_TCB_p(gTasks, gStates)) );
|
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_TCB_runState_p(gTasks, gStates)) );
|
||||||
//@ assert( gCurrentTCB == pxCurrentTCBs[ xCoreID ] );
|
//@ assert( gCurrentTCB == pxCurrentTCBs[ xCoreID ] );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates)) );
|
||||||
|
|
||||||
/* We could reuse the read permission to `pxTCB` we extracted before the if statement.
|
/* We could reuse the read permission to `pxTCB` we extracted before the if statement.
|
||||||
* But putting permissions back as soon as we no longer need them simplifies the
|
* But putting permissions back as soon as we no longer need them simplifies the
|
||||||
|
|
@ -1166,70 +1166,70 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Put read permission for `pxTCB` back
|
// Put read permission for `pxTCB` back
|
||||||
//@ close [1/2]sharedSeg_TCB_p(pxTCB, _);
|
//@ close [1/2]TCB_runState_p(pxTCB, _);
|
||||||
//@ close readOnly_sharedSeg_TCB_p(gTasks, gStates)(pxTCB);
|
//@ close readOnly_TCB_runState_p(gTasks, gStates)(pxTCB);
|
||||||
//@ foreach_unremove(pxTCB, gTasks);
|
//@ foreach_unremove(pxTCB, gTasks);
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_p(gTasks, gStates)) );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates)) );
|
||||||
|
|
||||||
// Get 2nd half of write permission for `gCurrentTCB`
|
// Get 2nd half of write permission for `gCurrentTCB`
|
||||||
//@ foreach_remove(gCurrentTCB, gTasks);
|
//@ foreach_remove(gCurrentTCB, gTasks);
|
||||||
//@ assert( foreach(remove(gCurrentTCB, gTasks), readOnly_sharedSeg_TCB_p(gTasks, gStates)) );
|
//@ assert( foreach(remove(gCurrentTCB, gTasks), readOnly_TCB_runState_p(gTasks, gStates)) );
|
||||||
|
|
||||||
/* If the task is not being executed by any core swap it in */
|
/* If the task is not being executed by any core swap it in */
|
||||||
pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING;
|
pxCurrentTCBs[ xCoreID ]->xTaskRunState = taskTASK_NOT_RUNNING;
|
||||||
//@ assert( foreach(remove(gCurrentTCB, gTasks), readOnly_sharedSeg_TCB_p(gTasks, gStates)) );
|
//@ assert( foreach(remove(gCurrentTCB, gTasks), readOnly_TCB_runState_p(gTasks, gStates)) );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates)) );
|
||||||
|
|
||||||
// New states list reflects state update above.
|
// New states list reflects state update above.
|
||||||
//@ list<TaskRunning_t> gStates1 = def_state1(gTasks, gStates, gCurrentTCB, pxTCB);
|
//@ list<TaskRunning_t> gStates1 = def_state1(gTasks, gStates, gCurrentTCB, pxTCB);
|
||||||
//@ assert( nth(index_of(pxTCB, gTasks), gStates1) == taskTASK_NOT_RUNNING);
|
//@ assert( nth(index_of(pxTCB, gTasks), gStates1) == taskTASK_NOT_RUNNING);
|
||||||
|
|
||||||
/*@ close_updated_foreach_readOnly_sharedSeg_TCB(gCurrentTCB, gTasks, gStates,
|
/*@ close_updated_foreach_readOnly_TCB_runState(gCurrentTCB, gTasks, gStates,
|
||||||
gStates1, taskTASK_NOT_RUNNING);
|
gStates1, taskTASK_NOT_RUNNING);
|
||||||
@*/
|
@*/
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStates1)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_p(gTasks, gStates1)) );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates)) );
|
||||||
/*@ stopUpdate_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
/*@ stopUpdate_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(gCurrentTCB, gTasks, gTasks, gStates, gStates1);
|
(gCurrentTCB, gTasks, gTasks, gStates, gStates1);
|
||||||
@*/
|
@*/
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates1)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates1)) );
|
||||||
|
|
||||||
|
|
||||||
// Get write permission for `pxTCB`
|
// Get write permission for `pxTCB`
|
||||||
//@ foreach_remove(pxTCB, gTasks);
|
//@ foreach_remove(pxTCB, gTasks);
|
||||||
//@ foreach_remove(pxTCB, gTasks);
|
//@ foreach_remove(pxTCB, gTasks);
|
||||||
//@ open readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates1)(pxTCB);
|
//@ open readOnly_TCB_runState_IF_not_running_p(gTasks, gStates1)(pxTCB);
|
||||||
|
|
||||||
#if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
#if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
||||||
pxPreviousTCB = pxCurrentTCBs[ xCoreID ];
|
pxPreviousTCB = pxCurrentTCBs[ xCoreID ];
|
||||||
#endif
|
#endif
|
||||||
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
|
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
|
||||||
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_sharedSeg_TCB_p(gTasks, gStates1)) );
|
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_TCB_runState_p(gTasks, gStates1)) );
|
||||||
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates1)) );
|
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_TCB_runState_IF_not_running_p(gTasks, gStates1)) );
|
||||||
/*@ list<TaskRunning_t> gStates2 =
|
/*@ list<TaskRunning_t> gStates2 =
|
||||||
def_state2(gTasks, gStates, gCurrentTCB, pxTCB, xCoreID);
|
def_state2(gTasks, gStates, gCurrentTCB, pxTCB, xCoreID);
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
/*@ close_updated_foreach_readOnly_sharedSeg_TCB(pxTCB, gTasks, gStates1,
|
/*@ close_updated_foreach_readOnly_TCB_runState(pxTCB, gTasks, gStates1,
|
||||||
gStates2, xCoreID);
|
gStates2, xCoreID);
|
||||||
@*/
|
@*/
|
||||||
/*@ startUpdate_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
/*@ startUpdate_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(pxTCB, gTasks, gStates1, gStates2, xCoreID);
|
(pxTCB, gTasks, gStates1, gStates2, xCoreID);
|
||||||
@*/
|
@*/
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStates2)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_p(gTasks, gStates2)) );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates2)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates2)) );
|
||||||
|
|
||||||
|
|
||||||
pxCurrentTCBs[ xCoreID ] = pxTCB;
|
pxCurrentTCBs[ xCoreID ] = pxTCB;
|
||||||
xTaskScheduled = pdTRUE;
|
xTaskScheduled = pdTRUE;
|
||||||
|
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gStates2)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_p(gTasks, gStates2)) );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates2)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates2)) );
|
||||||
//@ close exists_in_taskISRLockInv_p(gTasks, gStates2);
|
//@ close exists_in_taskISRLockInv_p(gTasks, gStates2);
|
||||||
|
|
||||||
// Putting back first have of write permission to `pxTCB`
|
// Putting back first have of write permission to `pxTCB`
|
||||||
//@ close [1/2]sharedSeg_TCB_p(pxTCB, _);
|
//@ close [1/2]TCB_runState_p(pxTCB, _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
|
else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
|
||||||
|
|
@ -1242,9 +1242,9 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
//@ assert( pxTCB->xTaskRunState != taskTASK_NOT_RUNNING );
|
//@ assert( pxTCB->xTaskRunState != taskTASK_NOT_RUNNING );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStates)) );
|
||||||
//@ assert( nth(index_of(pxTCB, gTasks), gStates) != taskTASK_NOT_RUNNING);
|
//@ assert( nth(index_of(pxTCB, gTasks), gStates) != taskTASK_NOT_RUNNING);
|
||||||
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_sharedSeg_TCB_p(gTasks, gStates)) );
|
//@ assert( foreach(remove(pxTCB, gTasks), readOnly_TCB_runState_p(gTasks, gStates)) );
|
||||||
|
|
||||||
/* 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;
|
||||||
|
|
@ -1254,13 +1254,13 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
= update(index_of(pxTCB, gTasks), xCoreID, gStates);
|
= update(index_of(pxTCB, gTasks), xCoreID, gStates);
|
||||||
@*/
|
@*/
|
||||||
//@ open exists_in_taskISRLockInv_p(gTasks, gStates);
|
//@ open exists_in_taskISRLockInv_p(gTasks, gStates);
|
||||||
/*@ scheduleRunning_in_foreach_readOnly_sharedSeg_TCB_IF_not_running
|
/*@ scheduleRunning_in_foreach_readOnly_TCB_runState_IF_not_running
|
||||||
(pxTCB, gTasks, gStates, gEquivStates, xCoreID);
|
(pxTCB, gTasks, gStates, gEquivStates, xCoreID);
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
//@ distinct_mem_remove(pxTCB, gTasks);
|
//@ distinct_mem_remove(pxTCB, gTasks);
|
||||||
//@ remove_result_subset(pxTCB, gTasks);
|
//@ remove_result_subset(pxTCB, gTasks);
|
||||||
/*@ update_foreach_readOnly_sharedSeg_TCB
|
/*@ update_foreach_readOnly_TCB_runState
|
||||||
(pxTCB, gTasks, remove(pxTCB, gTasks),
|
(pxTCB, gTasks, remove(pxTCB, gTasks),
|
||||||
gStates, gEquivStates, xCoreID);
|
gStates, gEquivStates, xCoreID);
|
||||||
@*/
|
@*/
|
||||||
|
|
@ -1270,16 +1270,16 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
// Put read permission for `pxTCB` back
|
// Put read permission for `pxTCB` back
|
||||||
//@ foreach_unremove(pxTCB, gTasks);
|
//@ foreach_unremove(pxTCB, gTasks);
|
||||||
|
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_p(gTasks, gEquivStates)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_p(gTasks, gEquivStates)) );
|
||||||
//@ close [1/2]sharedSeg_TCB_p(pxTCB, _);
|
//@ close [1/2]TCB_runState_p(pxTCB, _);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*@
|
/*@
|
||||||
if( !gPxTCB_not_running && pxTCB != gCurrentTCB ) {
|
if( !gPxTCB_not_running && pxTCB != gCurrentTCB ) {
|
||||||
assert( exists_in_taskISRLockInv_p(gTasks, gStates) );
|
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]TCB_runState_p(pxTCB, _);
|
||||||
close readOnly_sharedSeg_TCB_p(gTasks, gStates)(pxTCB);
|
close readOnly_TCB_runState_p(gTasks, gStates)(pxTCB);
|
||||||
foreach_unremove(pxTCB, gTasks);
|
foreach_unremove(pxTCB, gTasks);
|
||||||
}
|
}
|
||||||
@*/
|
@*/
|
||||||
|
|
@ -1325,8 +1325,8 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
}
|
}
|
||||||
|
|
||||||
//@ 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_TCB_runState_p(gTasks, gStatesEnd)) );
|
||||||
//@ assert( foreach(gTasks, readOnly_sharedSeg_TCB_IF_not_running_p(gTasks, gStatesEnd)) );
|
//@ assert( foreach(gTasks, readOnly_TCB_runState_IF_not_running_p(gTasks, gStatesEnd)) );
|
||||||
} while( pxTaskItem != pxLastTaskItem );
|
} while( pxTaskItem != pxLastTaskItem );
|
||||||
|
|
||||||
/* - If the loop above terminated via the break-branch,
|
/* - If the loop above terminated via the break-branch,
|
||||||
|
|
@ -4388,7 +4388,7 @@ void vTaskSwitchContext( BaseType_t xCoreID )
|
||||||
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
||||||
&*&
|
&*&
|
||||||
// read access to current task's stack pointer, etc
|
// read access to current task's stack pointer, etc
|
||||||
prvSeg_TCB_p(gCurrentTCB, ?ulFreeBytesOnStack);
|
TCB_stack_p(gCurrentTCB, ?ulFreeBytesOnStack);
|
||||||
|
|
||||||
@*/
|
@*/
|
||||||
/*@ ensures // all locks are released and interrupts remain disabled
|
/*@ ensures // all locks are released and interrupts remain disabled
|
||||||
|
|
@ -4403,7 +4403,7 @@ void vTaskSwitchContext( BaseType_t xCoreID )
|
||||||
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
||||||
&*&
|
&*&
|
||||||
// read access to current task's stack pointer, etc
|
// read access to current task's stack pointer, etc
|
||||||
prvSeg_TCB_p(gCurrentTCB, ulFreeBytesOnStack);
|
TCB_stack_p(gCurrentTCB, ulFreeBytesOnStack);
|
||||||
// Remark: the part of the post condition relating to TCBs will have to change.
|
// Remark: the part of the post condition relating to TCBs will have to change.
|
||||||
@*/
|
@*/
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue