@@ -79,6 +79,7 @@ tracked struct RwPerms<T> {
7979}
8080
8181ghost struct RwId {
82+ cell_perm_id: Loc ,
8283 upgrade_retract_token_id: Loc ,
8384 read_retract_token_id: Loc ,
8485}
@@ -216,12 +217,13 @@ closed spec fn wf(self) -> bool {
216217 } else {
217218 2 int
218219 }
220+ &&& ( v & UPGRADEABLE_READER ) != 0usize && ( v & WRITER ) == 0usize ==> g. cell_perm is Some
221+ &&& g. cell_perm is Some ==> g. cell_perm->Some_0 . id( ) == v_id@. cell_perm_id
219222 &&& 0 <= successful_read_guards <= reader_count <= total_reader_attempts
220223 &&& 1 <= g. read_retract_token. frac( ) <= V_MAX_READ_RETRACT_FRACS
221224 &&& match g. cell_perm {
222225 None => {
223226 &&& has_writer
224- &&& ( v & BEING_UPGRADED ) == 0usize
225227 }
226228 Some ( perm) => {
227229 &&& !has_writer
@@ -257,6 +259,10 @@ impl<T, G> RwLock<T, G> {
257259 self . val. id( )
258260 }
259261
262+ pub closed spec fn cell_perm_id( self ) -> Loc {
263+ self . v_id@. cell_perm_id
264+ }
265+
260266 pub closed spec fn upgrade_retract_token_id( self ) -> Loc {
261267 self . v_id@. upgrade_retract_token_id
262268 }
@@ -846,6 +852,7 @@ verus! {
846852impl <T , R : Deref <Target = RwLock <T , G >> + Clone , G : SpinGuardian > RwLockReadGuard_ <T , R , G > {
847853 #[ verifier:: type_invariant]
848854 pub closed spec fn type_inv( self ) -> bool {
855+ &&& self . inner. deref_spec( ) . cell_perm_id( ) == self . v_perm@. id( )
849856 &&& self . inner. deref_spec( ) . cell_id( ) == self . v_perm@. resource( ) . id( )
850857 &&& self . v_perm@. frac( ) == 1
851858 }
@@ -1043,13 +1050,13 @@ verus! {
10431050impl <T , R : Deref <Target = RwLock <T , G >> + Clone , G : SpinGuardian > RwLockUpgradeableGuard_ <T , R , G > {
10441051 #[ verifier:: type_invariant]
10451052 pub closed spec fn type_inv( self ) -> bool {
1053+ &&& self . inner. deref_spec( ) . cell_perm_id( ) == self . v_perm@. id( )
10461054 &&& self . inner. deref_spec( ) . cell_id( ) == self . v_perm@. resource( ) . id( )
10471055 &&& self . v_perm@. frac( ) == 1
10481056 }
10491057}
10501058
1051- } // verus!
1052-
1059+ #[ verus_verify]
10531060impl <T /*: ?Sized*/ , R : Deref <Target = RwLock <T , G >> + Clone , G : SpinGuardian >
10541061 RwLockUpgradeableGuard_ <T , R , G >
10551062{
@@ -1058,13 +1065,48 @@ impl<T /*: ?Sized*/, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian>
10581065 /// After calling this method, subsequent readers will be blocked
10591066 /// while previous readers remain unaffected. The calling thread
10601067 /// will spin-wait until previous readers finish.
1061- #[ verifier:: external_body]
1068+ #[ verus_spec]
1069+ #[ verifier:: exec_allows_no_decreases_clause]
10621070 pub fn upgrade( self ) -> RwLockWriteGuard_ <T , R , G > {
10631071 let mut this = self ;
1072+ let lock = this. inner. deref( ) ;
1073+ proof! {
1074+ use_type_invariant( & this) ;
1075+ use_type_invariant( lock) ;
1076+ lemma_consts_properties( ) ;
1077+ }
10641078 // self.inner.lock.fetch_or(BEING_UPGRADED, Acquire);
10651079 atomic_with_ghost!(
1066- & this. inner. lock => fetch_or( BEING_UPGRADED ) ;
1067- ghost g => { }
1080+ & lock. lock => fetch_or( BEING_UPGRADED ) ;
1081+ update prev -> next;
1082+ ghost g => {
1083+ assert( next == prev | BEING_UPGRADED ) ;
1084+ assert( next & WRITER == prev & WRITER ) by ( bit_vector)
1085+ requires
1086+ next == prev | BEING_UPGRADED ,
1087+ BEING_UPGRADED & WRITER == 0 ,
1088+ ;
1089+ assert( next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER ) by ( bit_vector)
1090+ requires
1091+ next == prev | BEING_UPGRADED ,
1092+ BEING_UPGRADED & UPGRADEABLE_READER == 0 ,
1093+ ;
1094+ assert( next & READER_MASK == prev & READER_MASK ) by ( bit_vector)
1095+ requires
1096+ next == prev | BEING_UPGRADED ,
1097+ BEING_UPGRADED & READER_MASK == 0 ,
1098+ ;
1099+ assert( next & MAX_READER_MASK == prev & MAX_READER_MASK ) by ( bit_vector)
1100+ requires
1101+ next == prev | BEING_UPGRADED ,
1102+ BEING_UPGRADED & MAX_READER_MASK == 0 ,
1103+ ;
1104+ assert( next & MAX_READER == prev & MAX_READER ) by ( bit_vector)
1105+ requires
1106+ next == prev | BEING_UPGRADED ,
1107+ BEING_UPGRADED & MAX_READER == 0 ,
1108+ ;
1109+ }
10681110 ) ;
10691111 loop {
10701112 this = match this. try_upgrade( ) {
@@ -1076,31 +1118,131 @@ impl<T /*: ?Sized*/, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian>
10761118 /// Attempts to upgrade this upread guard to a write guard atomically.
10771119 ///
10781120 /// This function will never spin-wait and will return immediately.
1079- #[ verifier :: external_body ]
1121+ #[ verus_spec ]
10801122 pub fn try_upgrade( self ) -> Result <RwLockWriteGuard_ <T , R , G >, Self > {
1123+ proof_decl! {
1124+ let tracked mut lock_perm: Option <RwFrac <T >> = None ;
1125+ let tracked mut write_perm: Option <PointsTo <T >> = None ;
1126+ let ghost mut lock_perm_id: Option <Loc > = None ;
1127+ let ghost mut up_perm_id: Option <Loc > = None ;
1128+ let ghost mut canon_perm_id: Option <Loc > = None ;
1129+ }
1130+ let lock = self . inner. deref( ) ;
1131+ proof! {
1132+ use_type_invariant( & self ) ;
1133+ use_type_invariant( lock) ;
1134+ lemma_consts_properties( ) ;
1135+ self . inner. deref_spec_eq( ) ;
1136+ assert( self . inner. deref_spec( ) == lock) ;
1137+ up_perm_id = Some ( self . v_perm@. id( ) ) ;
1138+ canon_perm_id = Some ( lock. cell_perm_id( ) ) ;
1139+ assert( up_perm_id->Some_0 == canon_perm_id->Some_0 ) ;
1140+ }
10811141 // let res = self.inner.lock.compare_exchange(
10821142 // UPGRADEABLE_READER | BEING_UPGRADED,
10831143 // WRITER | UPGRADEABLE_READER,
10841144 // AcqRel,
10851145 // Relaxed,
10861146 // );
10871147 let res = atomic_with_ghost!(
1088- & self . inner. lock => compare_exchange( UPGRADEABLE_READER | BEING_UPGRADED , WRITER ) ;
1148+ & lock. lock => compare_exchange( UPGRADEABLE_READER | BEING_UPGRADED , WRITER ) ;
1149+ update prev -> next;
10891150 returning res;
1090- ghost g => { }
1151+ ghost g => {
1152+ if res is Ok {
1153+ assert( prev == UPGRADEABLE_READER | BEING_UPGRADED ) ;
1154+ assert( next == WRITER ) ;
1155+ assert( prev & WRITER == 0usize ) by ( bit_vector)
1156+ requires
1157+ prev == UPGRADEABLE_READER | BEING_UPGRADED ,
1158+ WRITER & UPGRADEABLE_READER == 0 ,
1159+ WRITER & BEING_UPGRADED == 0 ,
1160+ ;
1161+ assert( prev & UPGRADEABLE_READER == UPGRADEABLE_READER ) by ( bit_vector)
1162+ requires
1163+ prev == UPGRADEABLE_READER | BEING_UPGRADED ,
1164+ UPGRADEABLE_READER & BEING_UPGRADED == 0 ,
1165+ ;
1166+ assert( prev & READER_MASK == 0usize ) by ( bit_vector)
1167+ requires
1168+ prev == UPGRADEABLE_READER | BEING_UPGRADED ,
1169+ UPGRADEABLE_READER & READER_MASK == 0 ,
1170+ BEING_UPGRADED & READER_MASK == 0 ,
1171+ ;
1172+ assert( prev & MAX_READER_MASK == 0usize ) by ( bit_vector)
1173+ requires
1174+ prev == UPGRADEABLE_READER | BEING_UPGRADED ,
1175+ UPGRADEABLE_READER & MAX_READER_MASK == 0 ,
1176+ BEING_UPGRADED & MAX_READER_MASK == 0 ,
1177+ ;
1178+ assert( prev & MAX_READER == 0usize ) by ( bit_vector)
1179+ requires
1180+ prev == UPGRADEABLE_READER | BEING_UPGRADED ,
1181+ UPGRADEABLE_READER & MAX_READER == 0 ,
1182+ BEING_UPGRADED & MAX_READER == 0 ,
1183+ ;
1184+ assert( g. cell_perm is Some ) ;
1185+ assert( 0 <= ( ( V_MAX_PERM_FRACS as int) - g. cell_perm->Some_0 . frac( ) ) - 1 ) ;
1186+ assert( ( ( V_MAX_PERM_FRACS as int) - g. cell_perm->Some_0 . frac( ) ) - 1 <= 0 ) ;
1187+ assert( g. cell_perm->Some_0 . frac( ) == ( V_MAX_PERM_FRACS as int) - 1 ) ;
1188+ assert( g. cell_perm->Some_0 . id( ) == lock. cell_perm_id( ) ) ;
1189+ lock_perm_id = Some ( g. cell_perm->Some_0 . id( ) ) ;
1190+ lock_perm = Some ( g. cell_perm. tracked_take( ) ) ;
1191+ }
1192+ }
10911193 ) ;
10921194 if res. is_ok( ) {
1093- let this = core:: mem:: ManuallyDrop :: new ( self ) ;
1094- let inner = this. inner . clone ( ) ;
1095- let guard = unsafe { core:: ptr:: read ( & this. guard ) } ;
1096- Ok ( RwLockWriteGuard_ { inner, guard, v_perm : Tracked :: assume_new ( ) } )
1195+ let mut this = core:: mem:: ManuallyDrop :: new( self ) ;
1196+ let inner = unsafe { Self :: get_inner( & this) } ;
1197+ let guard = unsafe { Self :: get_guard( & this) } ;
1198+ let Tracked ( up_perm) = unsafe { Self :: get_v_perm( & this) } ;
1199+ proof! {
1200+ let tracked mut rem = lock_perm. tracked_unwrap( ) ;
1201+ assert( rem. id( ) == lock_perm_id->Some_0 ) ;
1202+ assert( lock_perm_id->Some_0 == canon_perm_id->Some_0 ) ;
1203+ assert( up_perm == this@. v_perm@) ;
1204+ assert( this@. v_perm@. id( ) == up_perm_id->Some_0 ) ;
1205+ assert( up_perm. id( ) == this@. v_perm@. id( ) ) ;
1206+ let ghost up_cell_id = up_perm. resource( ) . id( ) ;
1207+ assert( up_cell_id == inner. deref_spec( ) . cell_id( ) ) ;
1208+ rem. combine( up_perm) ;
1209+ assert( rem. frac( ) == V_MAX_PERM_FRACS as int) ;
1210+ let tracked ( full_perm, _) = rem. take_resource( ) ;
1211+ assert( full_perm. id( ) == up_cell_id) ;
1212+ write_perm = Some ( full_perm) ;
1213+ }
1214+ Ok ( RwLockWriteGuard_ { inner, guard, v_perm: Tracked ( write_perm. tracked_unwrap( ) ) } )
10971215 } else {
10981216 Err ( self )
10991217 }
11001218 }
1219+
1220+ #[ verifier:: external_body]
1221+ unsafe fn get_guard( me: & core:: mem:: ManuallyDrop <Self >) -> G :: Guard {
1222+ core:: ptr:: read( & me. guard)
1223+ }
1224+
1225+ #[ verifier:: external_body]
1226+ #[ verus_spec(
1227+ ret =>
1228+ ensures
1229+ ret. deref_spec( ) == me@. inner. deref_spec( ) ,
1230+ ) ]
1231+ unsafe fn get_inner( me: & core:: mem:: ManuallyDrop <Self >) -> R {
1232+ core:: ptr:: read( & me. inner)
1233+ }
1234+
1235+ #[ verifier:: external_body]
1236+ #[ verus_spec(
1237+ ret =>
1238+ ensures
1239+ ret@ == me@. v_perm@,
1240+ ) ]
1241+ unsafe fn get_v_perm( me: & core:: mem:: ManuallyDrop <Self >) -> Tracked <RwFrac <T >> {
1242+ core:: ptr:: read( & me. v_perm)
1243+ }
11011244}
11021245
1103- verus ! {
11041246impl <T /*: ?Sized*/ , R : Deref <Target = RwLock <T , G >> + Clone , G : SpinGuardian > Deref
11051247 for RwLockUpgradeableGuard_ <T , R , G >
11061248{
@@ -1164,6 +1306,15 @@ proof fn lemma_consts_properties()
11641306 WRITER & MAX_READER_MASK == 0 ,
11651307 WRITER & MAX_READER == 0 ,
11661308 WRITER & UPGRADEABLE_READER == 0 ,
1309+ BEING_UPGRADED & WRITER == 0 ,
1310+ BEING_UPGRADED & UPGRADEABLE_READER == 0 ,
1311+ UPGRADEABLE_READER & BEING_UPGRADED == 0 ,
1312+ UPGRADEABLE_READER & READER_MASK == 0 ,
1313+ UPGRADEABLE_READER & MAX_READER_MASK == 0 ,
1314+ UPGRADEABLE_READER & MAX_READER == 0 ,
1315+ BEING_UPGRADED & READER_MASK == 0 ,
1316+ BEING_UPGRADED & MAX_READER_MASK == 0 ,
1317+ BEING_UPGRADED & MAX_READER == 0 ,
11671318{
11681319 assert( 0 & WRITER == 0 ) by ( compute_only) ;
11691320 assert( 0 & UPGRADEABLE_READER == 0 ) by ( compute_only) ;
@@ -1184,6 +1335,15 @@ proof fn lemma_consts_properties()
11841335 assert( WRITER & MAX_READER_MASK == 0 ) by ( compute_only) ;
11851336 assert( WRITER & MAX_READER == 0 ) by ( compute_only) ;
11861337 assert( WRITER & UPGRADEABLE_READER == 0 ) by ( compute_only) ;
1338+ assert( BEING_UPGRADED & WRITER == 0 ) by ( compute_only) ;
1339+ assert( BEING_UPGRADED & UPGRADEABLE_READER == 0 ) by ( compute_only) ;
1340+ assert( UPGRADEABLE_READER & BEING_UPGRADED == 0 ) by ( compute_only) ;
1341+ assert( UPGRADEABLE_READER & READER_MASK == 0 ) by ( compute_only) ;
1342+ assert( UPGRADEABLE_READER & MAX_READER_MASK == 0 ) by ( compute_only) ;
1343+ assert( UPGRADEABLE_READER & MAX_READER == 0 ) by ( compute_only) ;
1344+ assert( BEING_UPGRADED & READER_MASK == 0 ) by ( compute_only) ;
1345+ assert( BEING_UPGRADED & MAX_READER_MASK == 0 ) by ( compute_only) ;
1346+ assert( BEING_UPGRADED & MAX_READER == 0 ) by ( compute_only) ;
11871347}
11881348
11891349proof fn lemma_consts_properties_value( prev: usize )
0 commit comments