mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-12-11 14:15:12 -05:00
Extended lock invariants to justify safe access to ready tasks as well as scheduled task.
This commit is contained in:
parent
78de786d89
commit
fe5612cf4f
3 changed files with 166 additions and 51 deletions
93
tasks.c
93
tasks.c
|
|
@ -907,7 +907,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
taskISRLockInv_p()
|
taskISRLockInv_p()
|
||||||
&*&
|
&*&
|
||||||
// opened predicate `coreLocalInterruptInv_p()`
|
// opened predicate `coreLocalInterruptInv_p()`
|
||||||
pointer(&pxCurrentTCBs[coreID_f], ?gCurrentTCB) &*&
|
[0.5]pointer(&pxCurrentTCBs[coreID_f], ?gCurrentTCB) &*&
|
||||||
integer_(&xYieldPendings[coreID_f], sizeof(BaseType_t), true, _) &*&
|
integer_(&xYieldPendings[coreID_f], sizeof(BaseType_t), true, _) &*&
|
||||||
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
||||||
&*&
|
&*&
|
||||||
|
|
@ -960,7 +960,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
taskISRLockInv_p()
|
taskISRLockInv_p()
|
||||||
&*&
|
&*&
|
||||||
// opened predicate `coreLocalInterruptInv_p()`
|
// opened predicate `coreLocalInterruptInv_p()`
|
||||||
pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB) &*&
|
[0.5]pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB) &*&
|
||||||
// pubTCB_p(gCurrentTCB, 0) &*&
|
// pubTCB_p(gCurrentTCB, 0) &*&
|
||||||
integer_(&xYieldPendings[coreID_f], sizeof(BaseType_t), true, _) &*&
|
integer_(&xYieldPendings[coreID_f], sizeof(BaseType_t), true, _) &*&
|
||||||
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
coreLocalSeg_TCB_p(gCurrentTCB, 0)
|
||||||
|
|
@ -987,6 +987,16 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//@ open taskISRLockInv_p();
|
//@ open taskISRLockInv_p();
|
||||||
|
//@ assert( valid_sharedSeg_TCBs_p(?gTaskLists) );
|
||||||
|
|
||||||
|
// Eliminates exists predicate to avoid pattern matching conflicts
|
||||||
|
//@ open exists(gTaskLists);
|
||||||
|
|
||||||
|
// Get list containing currentTCB and ensure we matched the right variable
|
||||||
|
//@ assert( exists(?gCurrentTCB_category) );
|
||||||
|
//@ assert( mem(gCurrentTCB, gCurrentTCB_category) == true );
|
||||||
|
|
||||||
|
|
||||||
//@ open readyLists_p(?gCellLists, ?gOwnerLists);
|
//@ open readyLists_p(?gCellLists, ?gOwnerLists);
|
||||||
//@ List_array_p_index_within_limits(&pxReadyTasksLists, uxCurrentPriority);
|
//@ List_array_p_index_within_limits(&pxReadyTasksLists, uxCurrentPriority);
|
||||||
//@ List_array_split(pxReadyTasksLists, uxCurrentPriority);
|
//@ List_array_split(pxReadyTasksLists, uxCurrentPriority);
|
||||||
|
|
@ -1037,14 +1047,27 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
//@ mem_nth(uxCurrentPriority, gCellLists);
|
//@ mem_nth(uxCurrentPriority, gCellLists);
|
||||||
//@ assert( mem(gCells, gCellLists) == true);
|
//@ assert( mem(gCells, gCellLists) == true);
|
||||||
|
|
||||||
// Get access to `sharedSeg_TCB_p` predicates of current ready list.
|
// Prove that `mem(gOwners, gTaskLists) == true`
|
||||||
//@ open_owned_sharedSeg_TCBs(gOwnerLists, gOwners);
|
// Necessary to get access to `sharedSeg_TCB_p` predicates of
|
||||||
|
// current ready list in the loop
|
||||||
|
//@ assert( mem(gOwners, gOwnerLists) == true );
|
||||||
|
//@ assert( forall(gOwnerLists, (mem_list_elem)(gTaskLists) ) == true );
|
||||||
|
//@ forall_instantiate(gOwners, gOwnerLists, (mem_list_elem)(gTaskLists));
|
||||||
|
//@ assert( mem(gOwners, gTaskLists) == true );
|
||||||
|
///@ open_valid_sharedSeg_TCBs(gTaskLists, gOwners);
|
||||||
|
|
||||||
do
|
do
|
||||||
/*@ invariant
|
/*@ invariant
|
||||||
|
0 <= xCoreID &*& xCoreID < configNUM_CORES &*&
|
||||||
|
xCoreID == coreID_f() &*&
|
||||||
|
pointer(&pxCurrentTCBs[coreID_f], gCurrentTCB) &*&
|
||||||
mem(pxTaskItem, gCells) == true &*&
|
mem(pxTaskItem, gCells) == true &*&
|
||||||
xLIST(gReadyList, gSize, gIndex, gEnd, gCells, gVals, gOwners) &*&
|
xLIST(gReadyList, gSize, gIndex, gEnd, gCells, gVals, gOwners) &*&
|
||||||
foreach(gOwners, sharedSeg_TCB_p);
|
// foreach(gOwners, sharedSeg_TCB_p);
|
||||||
|
valid_sharedSeg_TCBs_p(gTaskLists) &*&
|
||||||
|
mem(gOwners, gTaskLists) == true &*&
|
||||||
|
mem(gCurrentTCB, gCurrentTCB_category) == true &*&
|
||||||
|
mem(gCurrentTCB_category, gTaskLists) == true;
|
||||||
@*/
|
@*/
|
||||||
{
|
{
|
||||||
TCB_t * pxTCB;
|
TCB_t * pxTCB;
|
||||||
|
|
@ -1083,6 +1106,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
//@ DLS_close_2(gTaskItem_final, gCells, gVals, gOwners);
|
//@ DLS_close_2(gTaskItem_final, gCells, gVals, gOwners);
|
||||||
|
|
||||||
// Getting access to fields of `pxTCB`
|
// Getting access to fields of `pxTCB`
|
||||||
|
//@ open_valid_sharedSeg_TCBs(gTaskLists, gOwners);
|
||||||
//@ foreach_remove(pxTCB, gOwners);
|
//@ foreach_remove(pxTCB, gOwners);
|
||||||
//@ open sharedSeg_TCB_p(pxTCB);
|
//@ open sharedSeg_TCB_p(pxTCB);
|
||||||
|
|
||||||
|
|
@ -1111,6 +1135,33 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
//@ assert( foreach(remove(pxTCB, gOwners), sharedSeg_TCB_p) );
|
||||||
|
//@ assert( gCurrentTCB == pxCurrentTCBs[ xCoreID ] );
|
||||||
|
/*@
|
||||||
|
if( gCurrentTCB == pxTCB ) {
|
||||||
|
// We can use the opened `sharedSeg_TCB_p` chunk
|
||||||
|
// for `pxTCB`.
|
||||||
|
} else {
|
||||||
|
if( gCurrentTCB_category == gOwners ) {
|
||||||
|
// `gCurrentTCB` is different from `pxTCB` but
|
||||||
|
// they belong to the same ready list.
|
||||||
|
|
||||||
|
assert( mem(gCurrentTCB, gOwners) == true );
|
||||||
|
mem_after_remove(gCurrentTCB, gOwners, pxTCB);
|
||||||
|
assert( mem(gCurrentTCB, remove(pxTCB, gOwners)) == true );
|
||||||
|
foreach_remove(gCurrentTCB, remove(pxTCB, gOwners));
|
||||||
|
} else {
|
||||||
|
assert( mem(gCurrentTCB_category, gTaskLists) == true );
|
||||||
|
mem_after_remove(gCurrentTCB_category, gTaskLists, gOwners);
|
||||||
|
assert( mem(gCurrentTCB_category, remove(gOwners, gTaskLists)) == true );
|
||||||
|
open_valid_sharedSeg_TCBs(remove(gOwners, gTaskLists),
|
||||||
|
gCurrentTCB_category);
|
||||||
|
foreach_remove(gCurrentTCB, gCurrentTCB_category);
|
||||||
|
}
|
||||||
|
|
||||||
|
open sharedSeg_TCB_p(gCurrentTCB);
|
||||||
|
}
|
||||||
|
@*/
|
||||||
/* 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;
|
||||||
#if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
#if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
|
||||||
|
|
@ -1119,6 +1170,36 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
|
pxTCB->xTaskRunState = ( TaskRunning_t ) xCoreID;
|
||||||
pxCurrentTCBs[ xCoreID ] = pxTCB;
|
pxCurrentTCBs[ xCoreID ] = pxTCB;
|
||||||
xTaskScheduled = pdTRUE;
|
xTaskScheduled = pdTRUE;
|
||||||
|
|
||||||
|
/*@
|
||||||
|
if( gCurrentTCB == pxTCB ) {
|
||||||
|
// We can used the opened `sharedSeg_TCB_p` chunk
|
||||||
|
// for `pxTCB`.
|
||||||
|
// => We don't have to close anything.
|
||||||
|
} else {
|
||||||
|
// Above, we extracted `sharedSeg_TCB_p(gCurrentTCB)`
|
||||||
|
// from the collection of all remaining shared TCB
|
||||||
|
// segments and opened it.
|
||||||
|
// => Close predicate and restore collection.
|
||||||
|
|
||||||
|
close sharedSeg_TCB_p(gCurrentTCB);
|
||||||
|
|
||||||
|
if( gCurrentTCB_category == gOwners ) {
|
||||||
|
// `gCurrentTCB` is different from `pxTCB` but
|
||||||
|
// they belong to the same ready list.
|
||||||
|
|
||||||
|
foreach_unremove(gCurrentTCB, remove(pxTCB, gOwners));
|
||||||
|
} else {
|
||||||
|
foreach_unremove(gCurrentTCB, gCurrentTCB_category);
|
||||||
|
close_valid_sharedSeg_TCBs(remove(gOwners, gTaskLists),
|
||||||
|
gCurrentTCB_category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@*/
|
||||||
|
|
||||||
|
// Ensure we restored the collection as it was
|
||||||
|
// at the beginning of the block.
|
||||||
|
//@ assert( foreach(remove(pxTCB, gOwners), sharedSeg_TCB_p) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
|
else if( pxTCB == pxCurrentTCBs[ xCoreID ] )
|
||||||
|
|
@ -1146,7 +1227,7 @@ static void prvYieldForTask( TCB_t * pxTCB,
|
||||||
}
|
}
|
||||||
} while( pxTaskItem != pxLastTaskItem );
|
} while( pxTaskItem != pxLastTaskItem );
|
||||||
|
|
||||||
//@ close_owned_sharedSeg_TCBs(gOwnerLists, gOwners);
|
//@ close_valid_sharedSeg_TCBs(gOwnerLists, gOwners);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: prove
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
/*@
|
/*@
|
||||||
lemma void head_drop_n_equals_nths<t>(list<t> xs, int n)
|
lemma void head_drop_n_equals_nths<t>(list<t> xs, int n)
|
||||||
requires n >= 0;
|
requires n >= 0;
|
||||||
|
|
@ -32,7 +32,7 @@ ensures head(drop(n, xs)) == nth(n, xs);
|
||||||
assume(false);
|
assume(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: prove
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
lemma void drop_index_equals_singleton_implies_last_element<t>(list<t> xs, t x)
|
lemma void drop_index_equals_singleton_implies_last_element<t>(list<t> xs, t x)
|
||||||
requires drop(index_of(x, xs), xs) == cons(x, nil);
|
requires drop(index_of(x, xs), xs) == cons(x, nil);
|
||||||
ensures index_of(x, xs) == length(xs) - 1;
|
ensures index_of(x, xs) == length(xs) - 1;
|
||||||
|
|
@ -50,7 +50,7 @@ ensures index_of(x, xs) == length(xs) - 1;
|
||||||
assume(false);
|
assume(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: prove
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
// Can we replace this by standard lemma `drop_n_plus_one`?
|
// Can we replace this by standard lemma `drop_n_plus_one`?
|
||||||
lemma void drop_cons<t>(list<t> xs, int n)
|
lemma void drop_cons<t>(list<t> xs, int n)
|
||||||
requires n < length(xs);
|
requires n < length(xs);
|
||||||
|
|
@ -70,7 +70,7 @@ ensures drop(n, xs) == cons(nth(n, xs), drop(n+1, xs));
|
||||||
assume(false);
|
assume(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: prove
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
lemma void nth_index<t>(list<t> xs, t x)
|
lemma void nth_index<t>(list<t> xs, t x)
|
||||||
requires mem(x, xs) == true;
|
requires mem(x, xs) == true;
|
||||||
ensures nth(index_of(x, xs), xs) == x;
|
ensures nth(index_of(x, xs), xs) == x;
|
||||||
|
|
@ -88,12 +88,12 @@ ensures nth(index_of(x, xs), xs) == x;
|
||||||
assume(false);
|
assume(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: prove
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
lemma void mem_prefix_implies_mem<t>(t x, list<t> xs, int n);
|
lemma void mem_prefix_implies_mem<t>(t x, list<t> xs, int n);
|
||||||
requires mem(x, take(n, xs)) == true;
|
requires mem(x, take(n, xs)) == true;
|
||||||
ensures mem(x, xs) == true;
|
ensures mem(x, xs) == true;
|
||||||
|
|
||||||
// TODO: prove
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
lemma void mem_suffix_implies_mem<t>(t x, list<t> xs, int n);
|
lemma void mem_suffix_implies_mem<t>(t x, list<t> xs, int n);
|
||||||
requires mem(x, drop(n, xs)) == true;
|
requires mem(x, drop(n, xs)) == true;
|
||||||
ensures mem(x, xs) == true;
|
ensures mem(x, xs) == true;
|
||||||
|
|
@ -102,6 +102,18 @@ ensures mem(x, xs) == true;
|
||||||
lemma void drop_n_plus_m<t>(list<t> xs, int n, int m);
|
lemma void drop_n_plus_m<t>(list<t> xs, int n, int m);
|
||||||
requires true;
|
requires true;
|
||||||
ensures drop(n, drop(m, xs)) == drop(n + m, xs);
|
ensures drop(n, drop(m, xs)) == drop(n + m, xs);
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
|
lemma void forall_instantiate<t>(t x, list<t> xs, fixpoint(t, bool) f);
|
||||||
|
requires forall(xs, f) == true &*& mem(x, xs) == true;
|
||||||
|
ensures forall(xs, f) == true &*& f(x) == true;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: Can we prove this in VeriFast or do we have to axiomatise?
|
||||||
|
lemma void mem_after_remove<t>(t x, list<t> xs, t r);
|
||||||
|
requires true;
|
||||||
|
ensures mem(x, remove(r, xs)) == (mem(x, xs) && x != r);
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ predicate interruptState_p(uint32_t coreID, uint32_t state);
|
||||||
fixpoint bool interruptsDisabled_f(uint32_t);
|
fixpoint bool interruptsDisabled_f(uint32_t);
|
||||||
|
|
||||||
predicate coreLocalInterruptInv_p() =
|
predicate coreLocalInterruptInv_p() =
|
||||||
pointer(&pxCurrentTCBs[coreID_f], ?currentTCB) &*&
|
[0.5]pointer(&pxCurrentTCBs[coreID_f], ?currentTCB) &*&
|
||||||
//pubTCB_p(currentTCB, 0) &*&
|
//pubTCB_p(currentTCB, 0) &*&
|
||||||
integer_(&xYieldPendings[coreID_f], sizeof(BaseType_t), true, _) &*&
|
integer_(&xYieldPendings[coreID_f], sizeof(BaseType_t), true, _) &*&
|
||||||
coreLocalSeg_TCB_p(currentTCB, ?gCriticalNesting);
|
coreLocalSeg_TCB_p(currentTCB, ?gCriticalNesting);
|
||||||
|
|
@ -85,17 +85,29 @@ predicate isrLockInv_p();
|
||||||
fixpoint int taskISRLockID_f();
|
fixpoint int taskISRLockID_f();
|
||||||
|
|
||||||
predicate taskISRLockInv_p() =
|
predicate taskISRLockInv_p() =
|
||||||
integer_((void*) &uxSchedulerSuspended, sizeof(UBaseType_t), false, _) &*&
|
// Access to global variables
|
||||||
integer_(&xSchedulerRunning, sizeof(BaseType_t), true, _)
|
[0.5]pointer(&pxCurrentTCBs[coreID_f], ?gCurrentTCB) &*&
|
||||||
|
integer_((void*) &uxSchedulerSuspended, sizeof(UBaseType_t), false, _) &*&
|
||||||
|
integer_(&xSchedulerRunning, sizeof(BaseType_t), true, _)
|
||||||
&*&
|
&*&
|
||||||
// top ready priority must be in range
|
// top ready priority must be in range
|
||||||
integer_((void*) &uxTopReadyPriority, sizeof(UBaseType_t), false, ?gTopReadyPriority) &*&
|
integer_((void*) &uxTopReadyPriority, sizeof(UBaseType_t), false, ?gTopReadyPriority) &*&
|
||||||
0 <= gTopReadyPriority &*& gTopReadyPriority < configMAX_PRIORITIES
|
0 <= gTopReadyPriority &*& gTopReadyPriority < configMAX_PRIORITIES
|
||||||
&*&
|
&*&
|
||||||
readyLists_p(?gCellLists, ?gOwnerLists)
|
// tasks / TCBs
|
||||||
&*&
|
exists<list<list<void*> > >(?gTaskLists)
|
||||||
// ∀owners ∈ gOwnerLists. ∀ow ∈ owners. sharedSeg_TCB_p(owner)
|
&*&
|
||||||
owned_sharedSeg_TCBs_p(gOwnerLists);
|
// ∀l ∈ gTaskLists. ∀t ∈ l. sharedSeg_TCB_p(l)
|
||||||
|
valid_sharedSeg_TCBs_p(gTaskLists)
|
||||||
|
&*&
|
||||||
|
readyLists_p(?gCellLists, ?gOwnerLists)
|
||||||
|
&*&
|
||||||
|
// gOwnerLists ⊆ gTaskLists
|
||||||
|
forall(gOwnerLists, (mem_list_elem)(gTaskLists)) == true
|
||||||
|
&*&
|
||||||
|
exists<list<void*> >(?gCurrentTCB_category) &*&
|
||||||
|
mem(gCurrentTCB_category, gTaskLists) == true &*&
|
||||||
|
mem(gCurrentTCB, gCurrentTCB_category) == true;
|
||||||
|
|
||||||
|
|
||||||
lemma void produce_taskISRLockInv();
|
lemma void produce_taskISRLockInv();
|
||||||
|
|
@ -113,43 +125,53 @@ requires locked_p( cons( pair(_, taskISRLockID_f()), ?otherLocks) ) &*&
|
||||||
ensures locked_p(otherLocks);
|
ensures locked_p(otherLocks);
|
||||||
|
|
||||||
|
|
||||||
|
// Auxiliary function that allows us to partially apply the list argument.
|
||||||
// ∀owners ∈ gOwnerLists. ∀ow ∈ owners. sharedSeg_TCB_p(owner)
|
//
|
||||||
predicate owned_sharedSeg_TCBs_p(list<list<void*> > ownerLists) =
|
// Notes:
|
||||||
foreach(ownerLists, foreach_sharedSeg_TCB_p);
|
// - Partial application of fixpoint functions in VeriFast is not documented.
|
||||||
|
// The syntax for partially application is `(<fixpoint_fct>)(<first_arg>)`
|
||||||
// ∀ow ∈ owners. sharedSeg_TCB_p(owner)
|
// - VeriFast only supports partially applying the first argument, e.g.,
|
||||||
predicate foreach_sharedSeg_TCB_p(list<void*> owners) =
|
// `(mem)(0)` is allowed but `(mem)(_)(nil)` is not.
|
||||||
foreach(owners, sharedSeg_TCB_p);
|
fixpoint bool mem_list_elem<t>(list<t> xs, t x) {
|
||||||
|
return mem(x, xs);
|
||||||
lemma void open_owned_sharedSeg_TCBs(list<list<void*> > ownerLists,
|
|
||||||
list<void*> owners)
|
|
||||||
requires
|
|
||||||
owned_sharedSeg_TCBs_p(ownerLists) &*&
|
|
||||||
mem(owners, ownerLists) == true;
|
|
||||||
ensures
|
|
||||||
owned_sharedSeg_TCBs_p(remove(owners, ownerLists)) &*&
|
|
||||||
foreach(owners, sharedSeg_TCB_p);
|
|
||||||
{
|
|
||||||
open owned_sharedSeg_TCBs_p(ownerLists);
|
|
||||||
foreach_remove(owners, ownerLists);
|
|
||||||
close owned_sharedSeg_TCBs_p(remove(owners, ownerLists));
|
|
||||||
open foreach_sharedSeg_TCB_p(owners);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lemma void close_owned_sharedSeg_TCBs(list<list<void*> > ownerLists,
|
// l ∈ taskLists. ∀t ∈ tasks. sharedSeg_TCB_p(t)
|
||||||
list<void*> owners)
|
predicate valid_sharedSeg_TCBs_p(list<list<void*> > taskLists) =
|
||||||
|
foreach(taskLists, foreach_sharedSeg_TCB_p);
|
||||||
|
|
||||||
|
// ∀t ∈ tasks. sharedSeg_TCB_p(t)
|
||||||
|
predicate foreach_sharedSeg_TCB_p(list<void*> tasks) =
|
||||||
|
foreach(tasks, sharedSeg_TCB_p);
|
||||||
|
|
||||||
|
lemma void open_valid_sharedSeg_TCBs(list<list<void*> > taskLists,
|
||||||
|
list<void*> tasks)
|
||||||
requires
|
requires
|
||||||
owned_sharedSeg_TCBs_p(remove(owners, ownerLists)) &*&
|
valid_sharedSeg_TCBs_p(taskLists) &*&
|
||||||
foreach(owners, sharedSeg_TCB_p) &*&
|
mem(tasks, taskLists) == true;
|
||||||
mem(owners, ownerLists) == true;
|
|
||||||
ensures
|
ensures
|
||||||
owned_sharedSeg_TCBs_p(ownerLists);
|
valid_sharedSeg_TCBs_p(remove(tasks, taskLists)) &*&
|
||||||
|
foreach(tasks, sharedSeg_TCB_p);
|
||||||
{
|
{
|
||||||
close foreach_sharedSeg_TCB_p(owners);
|
open valid_sharedSeg_TCBs_p(taskLists);
|
||||||
open owned_sharedSeg_TCBs_p(remove(owners, ownerLists));
|
foreach_remove(tasks, taskLists);
|
||||||
foreach_unremove(owners, ownerLists);
|
close valid_sharedSeg_TCBs_p(remove(tasks, taskLists));
|
||||||
close owned_sharedSeg_TCBs_p(ownerLists);
|
open foreach_sharedSeg_TCB_p(tasks);
|
||||||
|
}
|
||||||
|
|
||||||
|
lemma void close_valid_sharedSeg_TCBs(list<list<void*> > taskLists,
|
||||||
|
list<void*> tasks)
|
||||||
|
requires
|
||||||
|
valid_sharedSeg_TCBs_p(remove(tasks, taskLists)) &*&
|
||||||
|
foreach(tasks, sharedSeg_TCB_p) &*&
|
||||||
|
mem(tasks, taskLists) == true;
|
||||||
|
ensures
|
||||||
|
valid_sharedSeg_TCBs_p(taskLists);
|
||||||
|
{
|
||||||
|
close foreach_sharedSeg_TCB_p(tasks);
|
||||||
|
open valid_sharedSeg_TCBs_p(remove(tasks, taskLists));
|
||||||
|
foreach_unremove(tasks, taskLists);
|
||||||
|
close valid_sharedSeg_TCBs_p(taskLists);
|
||||||
}
|
}
|
||||||
@*/
|
@*/
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue