Skip to main content

ostd/sync/
rwlock.rs

1// SPDX-License-Identifier: MPL-2.0
2use vstd::atomic_ghost::*;
3use vstd::cell::{self, CellId, pcell::*};
4use vstd::prelude::*;
5use vstd::resource::Loc;
6#[cfg(feature = "irc11")]
7use vstd::thread_view::Objective;
8use vstd_extra::resource::ghost_resource::{count_auth::*, count_ghost::*, csum::*, excl::*};
9use vstd_extra::sum::*;
10use vstd_extra::{prelude::*, resource};
11
12use alloc::sync::Arc;
13use core::char::MAX;
14use core::{
15    cell::UnsafeCell,
16    fmt,
17    marker::PhantomData,
18    ops::{Deref, DerefMut},
19    sync::atomic::{
20        // AtomicUsize,
21        Ordering::{AcqRel, Acquire, Relaxed, Release},
22    },
23};
24
25use super::{
26    PreemptDisabled,
27    guard::{GuardTransfer, SpinGuardian},
28};
29
30verus! {
31
32/// The token reserved in the lock when the write permission is given out.
33type NoPerm<T> = EmptyCount<PointsTo<T>>;
34
35/// Half of the permission for read access, one for `RwLockUpgradeableGuard` and the other for all `RwLockReadGuard`s.
36type HalfPerm<T> = Count<PointsTo<T>>;
37
38/// The permission for read access can be further split into `MAX_READER` pieces.
39type ReadPerm<T> = (HalfPerm<T>, OneLeftKnowledge<HalfPerm<T>, NoPerm<T>, 3>);
40
41tracked struct RwPerms<T> {
42    /// This token tracks whether the write permission is given out. If it is `Left`, it stores the knowledge that
43    /// there are active readers because the existence of `HalfPerm` resource for read access.
44    /// If it is `Right`, we know there is an active writer and there is no active reader, because there is a `NoPerm`
45    /// indicating the absence of `PointsTo<T>`.
46    core_token: SumResource<HalfPerm<T>, NoPerm<T>, 3>,
47    /// The permission to retract a `READER` count. Its total quantity tracks the gap between
48    /// the number of `try_read` increments recorded in the lock atomic and the number of active
49    /// `RwLockReadGuard`s (created and ongoing creation that will succeed) represented by `read_guard_token`.
50    /// It can be splited up to `MAX_READER_MASK` pieces,
51    /// which allows at most `MAX_READER_MASK - 1` `try_read` attempts that will fail to acquire the lock.
52    read_retract_token: TokenResource<MAX_READER_MASK>,
53    /// The permission to retract the set of `UPGRADEABLE_READER` bit.
54    upread_retract_token: Option<UniqueToken>,
55    /// Tracks whether there is a live `RwLockUpgradeableGuard`, also stores half of the permission for read access.
56    upreader_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
57    /// Tracks the remaining read permissions, or an empty state while a writer owns the resource.
58    read_guard_token: CountResource<ReadPerm<T>, MAX_READER>,
59}
60
61#[cfg(feature = "irc11")]
62unsafe impl<T> Objective for RwPerms<T> {
63
64}
65
66ghost struct RwId {
67    core_token_id: Loc,
68    frac_id: Loc,
69    read_retract_token_id: Loc,
70    upread_retract_token_id: Loc,
71    read_guard_token_id: Loc,
72}
73
74/// The number of `try_read` operations recorded in the lock atomic (created and ongoing) can never reach `2*MAX_READER` to avoid overflow.
75/// **NOTE**: We *ASSUME* this property always holds without any proof. We believe this is true in practice because:
76/// - More than `2^61` `try_read` operations are required to trigger the overflow concurrently, which is absurd in real world scenarios.
77/// - If one tries to create a huge number (more than `2*MAX_READER`) of `RwLockReadGuard`s in a loop with `mem::forget`, it will take years and
78/// will be prevented by the `MAX_READER` check.
79pub closed spec fn no_max_reader_overflow(v: usize) -> bool {
80    v & MAX_READER_MASK < MAX_READER_MASK
81}
82
83struct_with_invariants! {
84/// Spin-based Read-write Lock
85///
86/// # Overview
87///
88/// This lock allows for multiple readers, or at most one writer to access
89/// at any point in time. The writer of this lock has exclusive access to
90/// modify the underlying data, while the readers are allowed shared and
91/// read-only access.
92///
93/// The writing and reading portions cannot be active simultaneously, when
94/// one portion is in progress, the other portion will spin-wait. This is
95/// suitable for scenarios where the lock is expected to be held for short
96/// periods of time, and the overhead of context switching is higher than
97/// the cost of spinning.
98///
99/// In addition to traditional read and write locks, this implementation
100/// provides the upgradeable read lock (`upread lock`). The `upread lock`
101/// can be upgraded to write locks atomically, useful in scenarios
102/// where a decision to write is made after reading.
103///
104/// The type parameter `T` represents the data that this lock is protecting.
105/// It is necessary for `T` to satisfy [`Send`] to be shared across tasks and
106/// [`Sync`] to permit concurrent access via readers. The [`Deref`] method (and
107/// [`DerefMut`] for the writer) is implemented for the RAII guards returned
108/// by the locking methods, which allows for the access to the protected data
109/// while the lock is held.
110///
111/// # Usage
112/// The lock can be used in scenarios where data needs to be read frequently
113/// but written to occasionally.
114///
115/// Use `upread lock` in scenarios where related checking is performed before
116/// modification to effectively avoid deadlocks and improve efficiency.
117///
118/// This lock should not be used in scenarios where lock-holding times are
119/// long as it can lead to CPU resource wastage due to spinning.
120///
121/// # About Guard
122///
123/// See the comments of [`SpinLock`].
124///
125/// # Examples
126///
127/// ```
128/// use ostd::sync::RwLock;
129///
130/// let lock = RwLock::new(5)
131///
132/// // many read locks can be held at once
133/// {
134///     let r1 = lock.read();
135///     let r2 = lock.read();
136///     assert_eq!(*r1, 5);
137///     assert_eq!(*r2, 5);
138///
139///     // Upgradeable read lock can share access to data with read locks
140///     let r3 = lock.upread();
141///     assert_eq!(*r3, 5);
142///     drop(r1);
143///     drop(r2);
144///     // read locks are dropped at this point
145///
146///     // An upread lock can only be upgraded successfully after all the
147///     // read locks are released, otherwise it will spin-wait.
148///     let mut w1 = r3.upgrade();
149///     *w1 += 1;
150///     assert_eq!(*w1, 6);
151/// }   // upread lock are dropped at this point
152///
153/// {
154///     // Only one write lock can be held at a time
155///     let mut w2 = lock.write();
156///     *w2 += 1;
157///     assert_eq!(*w2, 7);
158/// }   // write lock is dropped at this point
159/// ```
160///
161/// [`SpinLock`]: super::SpinLock
162pub struct RwLock<T  /* : ?Sized*/ , Guard /* = PreemptDisabled*/ > {
163    guard: PhantomData<Guard>,
164    /// The internal representation of the lock state is as follows:
165    /// - **Bit 63:** Writer lock.
166    /// - **Bit 62:** Upgradeable reader lock.
167    /// - **Bit 61:** Indicates if an upgradeable reader is being upgraded.
168    /// - **Bits 60-0:** Reader lock count.
169    lock: AtomicUsize<_, RwPerms<T>,_>,
170    // val: UnsafeCell<T>,
171    val: PCell<T>,
172    ghost_id: Ghost<RwId>,
173}
174
175/// This invariant holds at any time, i.e. not violated during any method execution.
176closed spec fn wf(self) -> bool {
177    invariant on lock with (val, guard, ghost_id) is (v: usize, g: RwPerms<T>) {
178        // BITS VALUE
179        let has_writer_bit: bool = (v & WRITER) != 0;
180        let has_upgrade_bit: bool = (v & UPGRADEABLE_READER) != 0;
181        let has_max_reader_bit: bool = (v & MAX_READER) != 0;
182        // The total number of `try_read` attempts recorded in the lock atomic, including created `RwLockReadGuard`s
183        // and those who are trying, no matter they will succeed or fail.
184        let total_reader_bits: int = (v & MAX_READER_MASK) as int;
185        // The clamped value represented in the counter bits. This counts the maximum number of active `RwLockReadGuard`s.
186        // NOTE: This does not mean there are actually this number of active `RwLockReadGuard`s. The actual number of successfully
187        // created/creating `RwLockReadGuard`s can be smaller than this number, because previously created `RwLockReadGuard`s may be dropped.
188        let reader_bits: int = if has_max_reader_bit { MAX_READER as int } else { (v & READER_MASK) as int };
189
190        // ACTUAL NUMBER OF ACTIVE GUARDS.
191        // The number is tracked by the ghost resources remained in the lock.
192        // By active, we mean from the perspective the lock, the permissions for these guards are given out.
193        // The actual guards may be still being created, but they must be successfully created finally.
194        // This invariant maintains the consistency between the ghost resources and the lock atomic value.
195
196        // Whether there is an active writer
197        let active_writer: bool = g.core_token.is_right();
198        // The number of active `RwLockUpgradeableGuard`, which can only be 0 or 1.
199        let active_upgrade_guard: bool = !active_writer && g.upreader_guard_token is None;
200        // The number of active `RwLockReadGuard`s.
201        let active_read_guards: int = if g.read_guard_token.is_resource_vacant() {
202            0
203        } else {
204            MAX_READER - g.read_guard_token.frac()
205        };
206        // The first `try_upread` that fails, which has not returned yet.
207        let pending_failed_upread_attempt: bool = g.upread_retract_token is None;
208        // The number of `try_read` attempts that will fail.
209        let failed_reader_attempts: int = MAX_READER_MASK - g.read_retract_token.frac();
210
211        &&& if g.core_token.is_left() {
212            let resource = g.read_guard_token.resource();
213            let read_half_cell_perm = resource.0;
214            let mode_knowledge = resource.1;
215            &&& !g.read_guard_token.is_resource_vacant()
216            &&& mode_knowledge.id() == ghost_id@.core_token_id
217            &&& read_half_cell_perm.id() == ghost_id@.frac_id
218            &&& read_half_cell_perm.resource().id() == val.id()
219            &&& read_half_cell_perm.frac() == 1
220        } else {
221            &&& g.upreader_guard_token is None
222            &&& g.read_guard_token.is_resource_vacant()
223        }
224        // The `UPGRADEABLE_READER` bit is set iff there is an active `RwLockUpgradeableGuard` or a pending failed `try_upread` attempt.
225        &&& has_upgrade_bit <==> (active_upgrade_guard || pending_failed_upread_attempt)
226        // An active `RwLockUpgradeableGuard` cannot coexist with a pending failed `try_upread` attempt.
227        &&& !(active_upgrade_guard && pending_failed_upread_attempt)
228        // The `READER` bits count the number of all active read guards and pending failed `try_read` attempts.
229        &&& total_reader_bits == active_read_guards + failed_reader_attempts
230        // There is an active `RwLockWriteGuard` iff the `WRITER` bit is set.
231        &&& active_writer <==> has_writer_bit
232        // The number of active `RwLockReadGaurd`s is less than or equal to the `READER` bits.
233        &&& 0 <= active_read_guards <= reader_bits <= total_reader_bits
234        // The core invariant of `RwLock`: there are no simultaneous active writers and readers.
235        &&& !(active_writer && (active_read_guards + if active_upgrade_guard { 1int } else { 0 }) > 0)
236        &&& g.core_token.id() == ghost_id@.core_token_id
237        &&& g.core_token.wf()
238        &&& g.core_token.is_left() ==> {
239            &&& !g.core_token.is_resource_owner()
240            &&& g.core_token.frac() == 1
241        }
242        &&& g.core_token.is_right() ==> {
243            let empty = g.core_token.resource_right();
244            &&& empty.id() == ghost_id@.frac_id
245            &&& g.core_token.frac() == 2
246            &&& g.core_token.has_resource()
247        }
248        &&& g.read_retract_token.wf()
249        &&& g.read_retract_token.id() == ghost_id@.read_retract_token_id
250        &&& g.upread_retract_token is Some ==>
251            {
252                let token = g.upread_retract_token->0;
253                &&& token.wf()
254                &&& token.id() == ghost_id@.upread_retract_token_id
255            }
256        &&& g.upreader_guard_token is Some ==> {
257            let token = g.upreader_guard_token->0;
258            wf_upgradeable_guard_token(ghost_id@.core_token_id, ghost_id@.frac_id, val.id(), token)
259        }
260        &&& g.read_guard_token.wf()
261        &&& g.read_guard_token.id() == ghost_id@.read_guard_token_id
262    }
263}
264
265}
266
267const READER: usize = 1;
268
269const WRITER: usize = 1 << (usize::BITS - 1);
270
271const UPGRADEABLE_READER: usize = 1 << (usize::BITS - 2);
272
273const BEING_UPGRADED: usize = 1 << (usize::BITS - 3);
274
275/// This bit is reserved as an overflow sentinel.
276/// We intentionally cap read guards before counter growth can affect
277/// `BEING_UPGRADED` / `UPGRADEABLE_READER` / `WRITER` bits.
278/// This is defense-in-depth with no extra runtime cost.
279///
280/// This follows the same strategy as Rust std's `Arc`,
281/// which uses `isize::MAX` as a sentinel to prevent its reference count
282/// from overflowing into values that could compromise safety.
283///
284/// On 64-bit platforms (the only targets Asterinas supports),
285/// a counter overflow is not a practical concern:
286/// incrementing one-by-one from zero to `MAX_READER` (2^60)
287/// would take hundreds of years even at billions of increments per second.
288/// Nevertheless, this sentinel provides an extra layer of safety at no runtime cost.
289const MAX_READER: usize = 1 << (usize::BITS - 4);
290
291/// Used only in verification. Excluding the `MAX_READER` bit.
292const READER_MASK: usize = usize::MAX >> 4;
293
294/// Used only in verification. Including the `MAX_READER` bit.
295const MAX_READER_MASK: usize = usize::MAX >> 3;
296
297impl<T, G> RwLock<T, G> {
298    /// Returns the unique [`CellId`](https://verus-lang.github.io/verus/verusdoc/vstd/cell/struct.CellId.html) of the internal `PCell<T>`.
299    pub closed spec fn cell_id(self) -> cell::CellId {
300        self.val.id()
301    }
302
303    pub closed spec fn core_token_id(self) -> Loc {
304        self.ghost_id@.core_token_id
305    }
306
307    pub closed spec fn frac_id(self) -> Loc {
308        self.ghost_id@.frac_id
309    }
310
311    pub closed spec fn upread_retract_token_id(self) -> Loc {
312        self.ghost_id@.upread_retract_token_id
313    }
314
315    pub closed spec fn read_guard_token_id(self) -> Loc {
316        self.ghost_id@.read_guard_token_id
317    }
318
319    /// Encapsulates the invariant described in the *Invariant* section of [`RwLock`].
320    #[verifier::type_invariant]
321    pub closed spec fn type_inv(self) -> bool {
322        self.wf()
323    }
324}
325
326closed spec fn wf_upgradeable_guard_token<T>(
327    core_token_id: Loc,
328    frac_id: Loc,
329    cell_id: CellId,
330    token: OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>,
331) -> bool {
332    let half_cell_perm = token.resource();
333    &&& token.id() == core_token_id
334    &&& half_cell_perm.id() == frac_id
335    &&& half_cell_perm.resource().id() == cell_id
336    &&& token.has_resource()
337    &&& half_cell_perm.frac() == 1
338    &&& half_cell_perm.has_authority()
339    &&& token.wf()
340}
341
342impl<T, G> RwLock<T, G> {
343    /// Creates a new spin-based read-write lock with an initial value.
344    pub const fn new(val: T) -> Self {
345        let (val, Tracked(perm)) = PCell::new(val);
346
347        // Proof code
348        proof {
349            lemma_consts_properties();
350        }
351        let tracked mut frac_perm = Count::<PointsTo<T>>::alloc(perm);
352        let tracked read_half_cell_perm = frac_perm.split(1int);
353        let ghost frac_id = frac_perm.id();
354        let tracked mut core_token = SumResource::alloc_left(frac_perm);
355        let tracked read_retract_token = TokenResource::<MAX_READER_MASK>::alloc(());
356        let tracked upread_retract_token = UniqueToken::alloc(());
357        let tracked upreader_guard_token = core_token.split_one_left_owner();
358        let tracked left_token = core_token.split_one_left_knowledge();
359        let tracked read_guard_token = CountResource::<ReadPerm<T>, MAX_READER>::alloc(
360            (read_half_cell_perm, left_token),
361        );
362        let ghost ghost_id = RwId {
363            frac_id,
364            core_token_id: core_token.id(),
365            upread_retract_token_id: upread_retract_token.id(),
366            read_retract_token_id: read_retract_token.id(),
367            read_guard_token_id: read_guard_token.id(),
368        };
369        let tracked perms = RwPerms {
370            core_token,
371            read_retract_token,
372            upread_retract_token: Some(upread_retract_token),
373            upreader_guard_token: Some(upreader_guard_token),
374            read_guard_token,
375        };
376
377        Self {
378            guard: PhantomData,
379            //lock: AtomicUsize::new(0),
380            lock: AtomicUsize::new(Ghost((val, PhantomData, Ghost(ghost_id))), 0, Tracked(perms)),
381            //val: UnsafeCell::new(val),
382            val: val,
383            ghost_id: Ghost(ghost_id),
384        }
385    }
386}
387
388#[verus_verify]
389impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLock<T, G> {
390    /// Acquires a read lock and spin-wait until it can be acquired.
391    ///
392    /// The calling thread will spin-wait until there are no writers or
393    /// upgrading upreaders present. There is no guarantee for the order
394    /// in which other readers or writers waiting simultaneously will
395    /// obtain the lock.
396    #[verifier::exec_allows_no_decreases_clause]
397    pub fn read(&self) -> RwLockReadGuard<'_, T, G> {
398        loop {
399            if let Some(readguard) = self.try_read() {
400                return readguard;
401            } else {
402                core::hint::spin_loop();
403            }
404        }
405    }
406
407    /// Acquires a write lock and spin-wait until it can be acquired.
408    ///
409    /// The calling thread will spin-wait until there are no other writers,
410    /// upreaders or readers present. There is no guarantee for the order
411    /// in which other readers or writers waiting simultaneously will
412    /// obtain the lock.
413    #[verifier::exec_allows_no_decreases_clause]
414    pub fn write(&self) -> RwLockWriteGuard<'_, T, G> {
415        loop {
416            if let Some(writeguard) = self.try_write() {
417                return writeguard;
418            } else {
419                core::hint::spin_loop();
420            }
421        }
422    }
423
424    /// Acquires an upreader and spin-wait until it can be acquired.
425    ///
426    /// The calling thread will spin-wait until there are no other writers,
427    /// or upreaders. There is no guarantee for the order in which other
428    /// readers or writers waiting simultaneously will obtain the lock.
429    ///
430    /// Upreader will not block new readers until it tries to upgrade. Upreader
431    /// and reader do not differ before invoking the upgrade method. However,
432    /// only one upreader can exist at any time to avoid deadlock in the
433    /// upgrade method.
434    #[verifier::exec_allows_no_decreases_clause]
435    pub fn upread(&self) -> RwLockUpgradeableGuard<'_, T, G> {
436        loop {
437            if let Some(guard) = self.try_upread() {
438                return guard;
439            } else {
440                core::hint::spin_loop();
441            }
442        }
443    }
444
445    /// Attempts to acquire a read lock.
446    ///
447    /// This function will never spin-wait and will return immediately.
448    #[verus_spec]
449    pub fn try_read(&self) -> Option<RwLockReadGuard<'_, T, G>> {
450        proof_decl!{
451            let tracked mut read_token: Option<Count<ReadPerm<T>,MAX_READER>> = None;
452            let tracked mut retract_read_token: Option<Token<MAX_READER_MASK>> = None;
453        }
454        proof!{
455            use_type_invariant(self);
456            lemma_consts_properties();
457        }
458        let guard = G::read_guard();
459
460        // let lock = self.lock.fetch_add(READER, Acquire);
461        let lock =
462            atomic_with_ghost!(
463            self.lock => fetch_add(READER);
464            update prev -> next;
465            ghost g => {
466                let prev_usize = prev as usize;
467                let next_usize = next as usize;
468                assume (no_max_reader_overflow(prev_usize));
469                lemma_consts_properties_value(prev_usize);
470                lemma_consts_properties_prev_next(prev_usize, next_usize);
471                if prev_usize & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
472                    read_token = Some(g.read_guard_token.split_one());
473                } else {
474                    retract_read_token = Some(g.read_retract_token.split_one());
475                }
476            }
477        );
478        if lock & (WRITER | MAX_READER | BEING_UPGRADED) == 0 {
479            Some(
480                RwLockReadGuard {
481                    inner: self,
482                    guard,
483                    tracked_token: Tracked(read_token.tracked_unwrap()),
484                },
485            )
486        } else {
487            // self.lock.fetch_sub(READER, Release);
488            atomic_with_ghost!(
489                self.lock => fetch_sub(READER);
490                update prev -> next;
491                ghost g => {
492                    let prev_usize = prev as usize;
493                    let next_usize = next as usize;
494                    lemma_consts_properties_value(next_usize);
495                    lemma_consts_properties_prev_next(prev_usize, next_usize);
496                    g.read_retract_token.combine(retract_read_token.tracked_unwrap());
497                }
498            );
499            None
500        }
501    }
502
503    /// Attempts to acquire a write lock.
504    ///
505    /// This function will never spin-wait and will return immediately.
506    #[verus_spec]
507    pub fn try_write(&self) -> Option<RwLockWriteGuard<'_, T, G>> {
508        proof_decl!{
509            let tracked mut guard_perm: Option<PointsTo<T>> = None;
510            let tracked mut guard_token: Option<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>> = None;
511        }
512        proof!{
513            use_type_invariant(self);
514            lemma_consts_properties();
515        }
516
517        let guard = G::guard();
518        // if self
519        //     .lock
520        //     .compare_exchange(0, WRITER, Acquire, Relaxed)
521        //     .is_ok()
522        if atomic_with_ghost!(
523            self.lock => compare_exchange(0, WRITER);
524            update prev -> next;
525            returning res;
526            ghost g => {
527                let prev_usize = prev as usize;
528                let next_usize = next as usize;
529                if res is Ok {
530                    // Retract the fractional permission for read access.
531                    let tracked read_resource = g.read_guard_token.take_resource();
532                    let tracked (read_half_cell_perm, left_token) = read_resource;
533                    g.core_token.join_one_left_knowledge(left_token);
534                    // Retract the fractional permission for upgradeable reader.
535                    let tracked upreader_guard_token = g.upreader_guard_token.tracked_take();
536                    g.core_token.join_one_left_owner(upreader_guard_token);
537                    // Combine the two halves of the permission for read access to get the full permission and give it out.
538                    let tracked mut pointsto = g.core_token.take_resource_left();
539                    pointsto.combine(read_half_cell_perm);
540                    let tracked (pointsto, empty) = pointsto.take_resource();
541                    guard_perm = Some(pointsto);
542                    g.core_token.change_to_right(empty);
543                    guard_token = Some(g.core_token.split_one_right_knowledge());
544                }
545            }
546        ).is_ok() {
547            Some(
548                RwLockWriteGuard {
549                    inner: self,
550                    guard,
551                    tracked_perm: Tracked(guard_perm.tracked_unwrap()),
552                    tracked_token: Tracked(guard_token.tracked_unwrap()),
553                },
554            )
555        } else {
556            None
557        }
558    }
559
560    /// Attempts to acquire an upread lock.
561    ///
562    /// This function will never spin-wait and will return immediately.
563    pub fn try_upread(&self) -> Option<RwLockUpgradeableGuard<'_, T, G>> {
564        proof_decl!{
565            let tracked mut upgrade_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
566            let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
567        }
568        proof!{
569            use_type_invariant(self);
570            lemma_consts_properties();
571        }
572        let guard = G::guard();
573        // let lock = self.lock.fetch_or(UPGRADEABLE_READER, Acquire) & (WRITER | UPGRADEABLE_READER);
574        let lock =
575            atomic_with_ghost!(
576            self.lock => fetch_or(UPGRADEABLE_READER);
577            update prev -> next;
578            ghost g => {
579                lemma_consts_properties_value(prev);
580                lemma_consts_properties_prev_next(prev, next);
581                if prev & (WRITER | UPGRADEABLE_READER) == 0 {
582                    upgrade_guard_token = Some(g.upreader_guard_token.tracked_take());
583                }
584                else if prev & (WRITER | UPGRADEABLE_READER) == WRITER {
585                    retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
586                }
587            }
588        )
589            & (WRITER | UPGRADEABLE_READER);
590        if lock == 0 {
591            return Some(
592                RwLockUpgradeableGuard {
593                    inner: self,
594                    guard,
595                    tracked_token: Tracked(upgrade_guard_token.tracked_unwrap()),
596                },
597            );
598        } else if lock == WRITER {
599            // self.lock.fetch_sub(UPGRADEABLE_READER, Release);
600            atomic_with_ghost!(
601                self.lock => fetch_sub(UPGRADEABLE_READER);
602                update prev -> next;
603                ghost g => {
604                    let prev_usize = prev as usize;
605                    let next_usize = next as usize;
606                    lemma_consts_properties_value(prev_usize);
607                    lemma_consts_properties_prev_next(prev_usize, next_usize);
608                    if g.upread_retract_token is Some {
609                        let tracked mut token = retract_upgrade_token.tracked_unwrap();
610                        token.validate_with_other(g.upread_retract_token.tracked_borrow());
611                    }
612                    else{
613                        g.upread_retract_token= retract_upgrade_token;
614                    }
615                }
616            );
617        }
618        None
619    }
620}
621
622/*
623impl<T, G: SpinGuardian> RwLock<T, G> {
624    /// Returns a mutable reference to the underlying data.
625    ///
626    /// This method is zero-cost: By holding a mutable reference to the lock, the compiler has
627    /// already statically guaranteed that access to the data is exclusive.
628    pub fn get_mut(&mut self) -> &mut T {
629        self.val.get_mut()
630    }
631
632    /// Returns a raw pointer to the underlying data.
633    ///
634    /// This method is safe, but it's up to the caller to ensure that access to the data behind it
635    /// is still safe.
636    pub(super) fn as_ptr(&self) -> *mut T {
637        self.val.get()
638    }
639}*/
640
641/* the trait `core::fmt::Debug` is not implemented for `vstd::cell::pcell::PCell<T>`
642impl<T: ?Sized + fmt::Debug, G> fmt::Debug for RwLock<T, G> {
643    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
644        fmt::Debug::fmt(&self.val, f)
645    }
646}*/
647
648/// Because there can be more than one readers to get the T's immutable ref,
649/// so T must be Sync to guarantee the sharing safety.
650#[verifier::external]
651unsafe impl<T: Send, G> Send for RwLock<T, G> {
652
653}
654
655#[verifier::external]
656unsafe impl<T: Send + Sync, G> Sync for RwLock<T, G> {
657
658}
659
660impl<T  /*: ?Sized*/ , G: SpinGuardian> !Send for RwLockWriteGuard<'_, T, G> {
661
662}
663
664#[verifier::external]
665unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockWriteGuard<'_, T, G> {
666
667}
668
669impl<T  /*: ?Sized*/ , G: SpinGuardian> !Send for RwLockReadGuard<'_, T, G> {
670
671}
672
673#[verifier::external]
674unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockReadGuard<'_, T, G> {
675
676}
677
678impl<T  /*: ?Sized*/ , G: SpinGuardian> !Send for RwLockUpgradeableGuard<'_, T, G> {
679
680}
681
682#[verifier::external]
683unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockUpgradeableGuard<'_, T, G> {
684
685}
686
687/// A guard that provides immutable data access.
688#[verifier::reject_recursive_types(T)]
689#[verifier::reject_recursive_types(G)]
690#[clippy::has_significant_drop]
691#[must_use]
692#[verus_verify]
693pub struct RwLockReadGuard<'a, T  /*: ?Sized*/ , G: SpinGuardian> {
694    guard: G::ReadGuard,
695    inner: &'a RwLock<T, G>,
696    tracked_token: Tracked<Count<ReadPerm<T>, MAX_READER>>,
697}
698
699/*
700impl<T: ?Sized, G: SpinGuardian> AsAtomicModeGuard for RwLockReadGuard<'_, T, G> {
701    fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
702        self.guard.as_atomic_mode_guard()
703    }
704}
705*/
706
707impl<'a, T, G: SpinGuardian> RwLockReadGuard<'a, T, G> {
708    #[verifier::type_invariant]
709    pub closed spec fn type_inv(self) -> bool {
710        let resource = self.tracked_token@.resource();
711        let read_half_cell_perm = resource.0;
712        let mode_knowledge = resource.1;
713        &&& self.inner.core_token_id() == mode_knowledge.id()
714        &&& self.inner.frac_id() == read_half_cell_perm.id()
715        &&& self.inner.cell_id() == read_half_cell_perm.resource().id()
716        &&& self.tracked_token@.id() == self.inner.read_guard_token_id()
717        &&& read_half_cell_perm.frac() == 1
718        &&& self.tracked_token@.frac() == 1
719    }
720
721    /// The value stored in the lock.
722    pub closed spec fn value(self) -> T {
723        *self.tracked_token@.resource().0.resource().value()
724    }
725
726    /// The value stored in the lock. It is an alias of `Self::value`.
727    pub open spec fn view(self) -> T {
728        self.value()
729    }
730}
731
732impl<T  /*: ?Sized*/ , G: SpinGuardian> Deref for RwLockReadGuard<'_, T, G> {
733    type Target = T;
734
735    #[verus_spec(returns self.view())]
736    fn deref(&self) -> &T {
737        proof!{
738            use_type_invariant(self);
739        }
740        // unsafe { &*self.inner.val.get() }
741        // The internal implementation of `PCell<T>::borrow` is exactly unsafe { &(*(*self.ucell).get()) },
742        // and here we verify that we have the permission to call `borrow`.
743        self.inner.val.borrow(
744            Tracked(self.tracked_token.borrow().tracked_borrow().0.tracked_borrow()),
745        )
746    }
747}
748
749/* impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Drop
750    for RwLockReadGuard_<T, R, G>
751{
752    fn drop(&mut self) {
753        self.inner.lock.fetch_sub(READER, Release);
754    }
755} */
756
757#[verus_verify]
758impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLockReadGuard<'_, T, G> {
759    /// VERUS LIMITATION: We implement `drop` and call it manually because Verus's support for `Drop` is incomplete for now.
760    #[verus_spec]
761    fn drop(self) {
762        proof! {
763            use_type_invariant(&self);
764            use_type_invariant(self.inner);
765            lemma_consts_properties();
766        }
767        proof_decl! {
768            let tracked token = self.tracked_token.get();
769        }
770        // self.inner.lock.fetch_sub(READER, Release);
771        atomic_with_ghost!(
772            self.inner.lock => fetch_sub(READER);
773            update prev -> next;
774            ghost g => {
775                let prev_usize = prev as usize;
776                let next_usize = next as usize;
777                assume (no_max_reader_overflow(prev_usize));
778                lemma_consts_properties_value(next_usize);
779                lemma_consts_properties_prev_next(prev_usize, next_usize);
780                g.core_token.validate_with_one_left_knowledge(&token.tracked_borrow().1);
781                g.read_guard_token.combine(token);
782            }
783        );
784    }
785}
786
787/*
788impl<T: ?Sized + fmt::Debug, G: SpinGuardian> fmt::Debug for RwLockReadGuard<'_, T, G> {
789    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
790        fmt::Debug::fmt(&**self, f)
791    }
792}*/
793
794/// A guard that provides mutable data access.
795#[verifier::reject_recursive_types(T)]
796#[verifier::reject_recursive_types(G)]
797pub struct RwLockWriteGuard<'a, T  /*: ?Sized*/ , G: SpinGuardian> {
798    guard: G::Guard,
799    inner: &'a RwLock<T, G>,
800    /// Ghost permission for verification
801    tracked_perm: Tracked<PointsTo<T>>,
802    tracked_token: Tracked<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>>,
803}
804
805impl<'a, T, G: SpinGuardian> RwLockWriteGuard<'a, T, G> {
806    #[verifier::type_invariant]
807    spec fn type_inv(self) -> bool {
808        &&& self.inner.cell_id() == self.tracked_perm@.id()
809        &&& self.inner.core_token_id() == self.tracked_token@.id()
810    }
811
812    /// The value stored in the lock.
813    pub closed spec fn value(self) -> T {
814        *self.tracked_perm@.value()
815    }
816
817    /// The value stored in the lock. It is an alias of `Self::value`.
818    pub open spec fn view(self) -> T {
819        self.value()
820    }
821}
822
823/*
824impl<T: ?Sized, G: SpinGuardian> AsAtomicModeGuard for RwLockWriteGuard<'_, T, G> {
825    fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
826        self.guard.as_atomic_mode_guard()
827    }
828}*/
829
830impl<T  /*: ?Sized*/ , G: SpinGuardian> Deref for RwLockWriteGuard<'_, T, G> {
831    type Target = T;
832
833    #[verus_spec(returns self.view())]
834    fn deref(&self) -> &T {
835        proof!{
836            use_type_invariant(self);
837        }
838        // unsafe { &*self.inner.val.get() }
839        // The internal implementation of `PCell<T>::borrow` is exactly unsafe { &(*(*self.ucell).get()) },
840        // and here we verify that we have the permission to call `borrow`.
841        self.inner.val.borrow(Tracked(self.tracked_perm.borrow()))
842    }
843}
844
845#[verus_verify]
846impl<T  /*: ?Sized*/ , G: SpinGuardian> DerefMut for RwLockWriteGuard<'_, T, G> {
847    #[verus_spec(ret =>
848        ensures
849            final(self).view() == *final(ret),
850            old(self).view() == *ret,
851    )]
852    fn deref_mut(&mut self) -> &mut Self::Target {
853        proof!{
854            use_type_invariant(&*self);
855        }
856        //unsafe { &mut *self.inner.val.get() }
857        self.inner.val.borrow_mut(Tracked(&mut *self.tracked_perm))
858    }
859}
860
861/*
862impl<T: ?Sized, G: SpinGuardian> Drop for RwLockWriteGuard<'_, T, G> {
863    fn drop(&mut self) {
864        self.inner.lock.fetch_and(!WRITER, Release);
865    }
866}*/
867
868impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLockWriteGuard<'_, T, G> {
869    /// VERUS LIMITATION: We implement `drop` and call it manually because Verus's support for `Drop` is incomplete for now.
870    pub fn drop(self) {
871        proof!{
872            use_type_invariant(&self);
873            use_type_invariant(self.inner);
874            lemma_consts_properties();
875        }
876        proof_decl! {
877            let tracked mut perm = self.tracked_perm.get();
878            let tracked token = self.tracked_token.get();
879        }
880        //self.inner.lock.fetch_and(!WRITER, Release);
881        atomic_with_ghost!{
882            self.inner.lock => fetch_and(!WRITER);
883            update prev -> next;
884            ghost g => {
885                let prev_usize = prev as usize;
886                let next_usize = next as usize;
887                lemma_consts_properties_prev_next(prev_usize, next_usize);
888                lemma_consts_properties_value(next_usize);
889                g.core_token.validate_with_one_right_knowledge(&token);
890                g.core_token.join_one_right_knowledge(token);
891                let tracked empty = g.core_token.take_resource_right();
892                let tracked mut full = empty.put_resource(perm);
893                let tracked read_half_cell_perm = full.split(1int);
894                g.core_token.change_to_left(full);
895                let tracked upreader_guard_token = g.core_token.split_one_left_owner();
896                g.upreader_guard_token = Some(upreader_guard_token);
897                let tracked left_token = g.core_token.split_one_left_knowledge();
898                g.read_guard_token.put_resource((read_half_cell_perm, left_token));
899            }
900        };
901    }
902}
903
904/*
905impl<T: ?Sized + fmt::Debug, G: SpinGuardian> fmt::Debug for RwLockWriteGuard<'_, T, G> {
906    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
907        fmt::Debug::fmt(&**self, f)
908    }
909}*/
910
911/// A guard that provides immutable data access but can be atomically
912/// upgraded to `RwLockWriteGuard`.
913#[verifier::reject_recursive_types(T)]
914#[verifier::reject_recursive_types(G)]
915pub struct RwLockUpgradeableGuard<'a, T  /*: ?Sized*/ , G: SpinGuardian> {
916    guard: G::Guard,
917    inner: &'a RwLock<T, G>,
918    tracked_token: Tracked<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
919}
920
921/*
922impl<T: ?Sized, G: SpinGuardian> AsAtomicModeGuard for RwLockUpgradeableGuard<'_, T, G> {
923    fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
924        self.guard.as_atomic_mode_guard()
925    }
926}*/
927
928impl<'a, T, G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
929    #[verifier::type_invariant]
930    pub closed spec fn type_inv(self) -> bool {
931        wf_upgradeable_guard_token(
932            self.inner.core_token_id(),
933            self.inner.frac_id(),
934            self.inner.cell_id(),
935            self.tracked_token@,
936        )
937    }
938
939    /// The value stored in the lock.
940    pub closed spec fn value(self) -> T {
941        *self.tracked_token@.resource().resource().value()
942    }
943
944    /// The value stored in the lock. It is an alias of `Self::value`.
945    pub open spec fn view(self) -> T {
946        self.value()
947    }
948}
949
950impl<'a, T  /*: ?Sized*/ , G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
951    /// Upgrades this upread guard to a write guard atomically.
952    ///
953    /// After calling this method, subsequent readers will be blocked
954    /// while previous readers remain unaffected. The calling thread
955    /// will spin-wait until previous readers finish.
956    #[verifier::exec_allows_no_decreases_clause]
957    pub fn upgrade(  /* mut */ self) -> RwLockWriteGuard<'a, T, G> {
958        let mut this = self;
959        proof! {
960            use_type_invariant(&this);
961            use_type_invariant(&this.inner);
962            lemma_consts_properties();
963        }
964        // self.inner.lock.fetch_or(BEING_UPGRADED, Acquire);
965        atomic_with_ghost!(
966            this.inner.lock => fetch_or(BEING_UPGRADED);
967            update prev -> next;
968            ghost g => {
969                lemma_consts_properties_prev_next(prev, next);
970            }
971        );
972        loop {
973            // self = match self.try_upgrade() {
974            this =
975            match this.try_upgrade() {
976                Ok(guard) => return guard,
977                Err(e) => e,
978            };
979        }
980    }
981
982    // [FIXED] BUG FOUND BY FV: deadlock. https://github.com/asterinas/asterinas/pull/3007
983    /// Attempts to upgrade this upread guard to a write guard atomically.
984    ///
985    /// This function will never spin-wait and will return immediately.
986    ///
987    /// This function is not exposed publicly because the `BEING_UPGRADED` bit
988    /// is set only in [`Self::upgrade`].
989    fn try_upgrade(  /* mut */ self) -> Result<RwLockWriteGuard<'a, T, G>, Self> {
990        proof! {
991            use_type_invariant(&self);
992            use_type_invariant(self.inner);
993            lemma_consts_properties();
994        }
995        let mut this = self;
996        proof_decl! {
997            let tracked mut upread_guard_token = this.tracked_token.get();
998            let tracked mut write_perm: Option<PointsTo<T>> = None;
999            let tracked mut err_upread_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
1000            let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
1001            let tracked mut write_guard_token = None;
1002        }
1003
1004        // let res = self.inner.lock.compare_exchange(
1005        //     UPGRADEABLE_READER | BEING_UPGRADED,
1006        //     WRITER | UPGRADEABLE_READER,
1007        //     AcqRel,
1008        //     Relaxed,
1009        // );
1010        let res =
1011            atomic_with_ghost!(
1012            this.inner.lock => compare_exchange(UPGRADEABLE_READER | BEING_UPGRADED, WRITER | UPGRADEABLE_READER);
1013            update prev -> next;
1014            returning res;
1015            ghost g => {
1016                lemma_consts_properties_prev_next(prev, next);
1017                if res is Ok {
1018                    g.core_token.validate_with_one_left_owner(&upread_guard_token);
1019                    if g.upreader_guard_token is Some {
1020                        upread_guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1021                    }
1022                    g.core_token.join_one_left_owner(upread_guard_token);
1023                    let tracked read_resource = g.read_guard_token.take_resource();
1024                    let tracked (read_half_cell_perm, left_token) = read_resource;
1025                    g.core_token.join_one_left_knowledge(left_token);
1026                    let tracked mut pointsto = g.core_token.take_resource_left();
1027                    pointsto.combine(read_half_cell_perm);
1028                    let tracked (pointsto, empty) = pointsto.take_resource();
1029                    write_perm = Some(pointsto);
1030                    g.core_token.change_to_right(empty);
1031                    write_guard_token = Some(g.core_token.split_one_right_knowledge());
1032                    retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
1033                } else {
1034                    err_upread_guard_token = Some(upread_guard_token);
1035                }
1036            }
1037        );
1038        if res.is_ok() {
1039            let inner = this.inner;
1040            let guard = this.guard.transfer_to();
1041            // drop(self);
1042            atomic_with_ghost!(
1043                inner.lock => fetch_sub(UPGRADEABLE_READER);
1044                update prev -> next;
1045                ghost g => {
1046                    let prev_usize = prev as usize;
1047                    let next_usize = next as usize;
1048                    lemma_consts_properties_value(prev_usize);
1049                    lemma_consts_properties_prev_next(prev_usize, next_usize);
1050                    let tracked mut token = retract_upgrade_token.tracked_unwrap();
1051                    if g.upread_retract_token is Some {
1052                        token.validate_with_other(g.upread_retract_token.tracked_borrow());
1053                    }
1054                    g.upread_retract_token = Some(token);
1055                }
1056            );
1057            Ok(
1058                RwLockWriteGuard {
1059                    inner,
1060                    guard,
1061                    tracked_perm: Tracked(write_perm.tracked_unwrap()),
1062                    tracked_token: Tracked(write_guard_token.tracked_unwrap()),
1063                },
1064            )
1065        } else {
1066            Err(
1067                RwLockUpgradeableGuard {
1068                    inner: this.inner,
1069                    guard: this.guard,
1070                    tracked_token: Tracked(err_upread_guard_token.tracked_unwrap()),
1071                },
1072            )
1073        }
1074    }
1075}
1076
1077impl<T  /*: ?Sized*/ , G: SpinGuardian> Deref for RwLockUpgradeableGuard<'_, T, G> {
1078    type Target = T;
1079
1080    #[verus_spec(returns self.view())]
1081    fn deref(&self) -> &T {
1082        proof!{
1083            use_type_invariant(self);
1084        }
1085        // unsafe { &*self.inner.val.get() }
1086        // The internal implementation of `PCell<T>::borrow` is exactly unsafe { &(*(*self.ucell).get()) },
1087        // and here we verify that we have the permission to call `borrow`.
1088        self.inner.val.borrow(
1089            Tracked(self.tracked_token.borrow().tracked_borrow().tracked_borrow()),
1090        )
1091    }
1092}
1093
1094/*
1095impl<T: ?Sized, G: SpinGuardian> Drop for RwLockUpgradeableGuard<'_, T, G> {
1096    fn drop(&mut self) {
1097        self.inner.lock.fetch_sub(UPGRADEABLE_READER, Release);
1098    }
1099}*/
1100
1101impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLockUpgradeableGuard<'_, T, G> {
1102    /// VERUS LIMITATION: We implement `drop` and call it manually because Verus's support for `Drop` is incomplete for now.
1103    pub fn drop(self) {
1104        proof! {
1105            use_type_invariant(&self);
1106            use_type_invariant(self.inner);
1107            lemma_consts_properties();
1108        }
1109        proof_decl!{
1110            let tracked guard_token = self.tracked_token.get();
1111        }
1112        //self.inner.lock.fetch_sub(UPGRADEABLE_READER, Release);
1113        atomic_with_ghost!(
1114            self.inner.lock => fetch_sub(UPGRADEABLE_READER);
1115            update prev -> next;
1116            ghost g => {
1117                let prev_usize = prev as usize;
1118                let next_usize = next as usize;
1119                lemma_consts_properties_value(prev_usize);
1120                lemma_consts_properties_prev_next(prev_usize, next_usize);
1121                g.core_token.validate_with_one_left_owner(&guard_token);
1122                if g.upreader_guard_token is Some {
1123                    guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1124                    assert(false);
1125                } else {
1126                    g.upreader_guard_token= Some(guard_token);
1127                }
1128            }
1129        );
1130    }
1131}
1132
1133/*
1134impl<T: ?Sized + fmt::Debug, G: SpinGuardian> fmt::Debug for RwLockUpgradeableGuard<'_, T, G> {
1135    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1136        fmt::Debug::fmt(&**self, f)
1137    }
1138}
1139*/
1140
1141#[verifier::bit_vector]
1142proof fn lemma_consts_properties()
1143    ensures
1144        0 & WRITER == 0,
1145        0 & UPGRADEABLE_READER == 0,
1146        0 & BEING_UPGRADED == 0,
1147        0 & READER_MASK == 0,
1148        0 & MAX_READER_MASK == 0,
1149        0 & MAX_READER == 0,
1150        0 & READER == 0,
1151        WRITER == 0x8000_0000_0000_0000,
1152        UPGRADEABLE_READER == 0x4000_0000_0000_0000,
1153        BEING_UPGRADED == 0x2000_0000_0000_0000,
1154        READER_MASK == 0x0FFF_FFFF_FFFF_FFFF,
1155        MAX_READER_MASK == 0x1FFF_FFFF_FFFF_FFFF,
1156        MAX_READER == 0x1000_0000_0000_0000,
1157        WRITER & WRITER == WRITER,
1158        WRITER & !WRITER == 0,
1159        WRITER & BEING_UPGRADED == 0,
1160        WRITER & READER_MASK == 0,
1161        WRITER & MAX_READER_MASK == 0,
1162        WRITER & MAX_READER == 0,
1163        WRITER & UPGRADEABLE_READER == 0,
1164        BEING_UPGRADED & WRITER == 0,
1165        BEING_UPGRADED & UPGRADEABLE_READER == 0,
1166        UPGRADEABLE_READER & BEING_UPGRADED == 0,
1167        UPGRADEABLE_READER & READER_MASK == 0,
1168        UPGRADEABLE_READER & MAX_READER_MASK == 0,
1169        UPGRADEABLE_READER & MAX_READER == 0,
1170        BEING_UPGRADED & READER_MASK == 0,
1171        BEING_UPGRADED & MAX_READER_MASK == 0,
1172        BEING_UPGRADED & MAX_READER == 0,
1173        (UPGRADEABLE_READER | BEING_UPGRADED) & WRITER == 0,
1174        (UPGRADEABLE_READER | BEING_UPGRADED) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1175        (UPGRADEABLE_READER | BEING_UPGRADED) & BEING_UPGRADED == BEING_UPGRADED,
1176        (UPGRADEABLE_READER | BEING_UPGRADED) & READER_MASK == 0,
1177        (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER_MASK == 0,
1178        (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER == 0,
1179        (WRITER | UPGRADEABLE_READER) & WRITER == WRITER,
1180        (WRITER | UPGRADEABLE_READER) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1181        (WRITER | UPGRADEABLE_READER) & BEING_UPGRADED == 0,
1182        (WRITER | UPGRADEABLE_READER) & READER_MASK == 0,
1183        (WRITER | UPGRADEABLE_READER) & MAX_READER_MASK == 0,
1184        (WRITER | UPGRADEABLE_READER) & MAX_READER == 0,
1185{
1186}
1187
1188#[verifier::bit_vector]
1189proof fn lemma_consts_properties_value(prev: usize)
1190    ensures
1191        no_max_reader_overflow(prev) ==> prev + READER <= usize::MAX,
1192        prev & (WRITER | MAX_READER | BEING_UPGRADED) == 0 ==> {
1193            &&& prev & WRITER == 0
1194            &&& prev & BEING_UPGRADED == 0
1195            &&& prev & MAX_READER == 0
1196        },
1197        prev & (WRITER | UPGRADEABLE_READER) == 0 ==> {
1198            &&& prev & WRITER == 0
1199            &&& prev & UPGRADEABLE_READER == 0
1200        },
1201        prev & MAX_READER == 0 ==> prev & READER_MASK == prev & MAX_READER_MASK,
1202        prev & MAX_READER != 0 ==> prev & MAX_READER_MASK >= MAX_READER,
1203        prev & (WRITER | UPGRADEABLE_READER) == WRITER ==> {
1204            &&& prev & UPGRADEABLE_READER == 0
1205            &&& prev & WRITER == WRITER
1206        },
1207        prev & UPGRADEABLE_READER != 0 ==> prev >= UPGRADEABLE_READER,
1208        prev & UPGRADEABLE_READER == 0 ==> {
1209            ||| prev & (WRITER | UPGRADEABLE_READER) == 0
1210            ||| prev & (WRITER | UPGRADEABLE_READER) == WRITER
1211        },
1212{
1213}
1214
1215#[verifier::bit_vector]
1216proof fn lemma_consts_properties_prev_next(prev: usize, next: usize)
1217    ensures
1218        prev & READER_MASK < MAX_READER,
1219        next == prev | UPGRADEABLE_READER ==> {
1220            &&& next & UPGRADEABLE_READER != 0
1221            &&& next & WRITER == prev & WRITER
1222            &&& next & READER_MASK == prev & READER_MASK
1223            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1224            &&& next & MAX_READER == prev & MAX_READER
1225            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1226        },
1227        next == prev | BEING_UPGRADED ==> {
1228            &&& next & BEING_UPGRADED != 0
1229            &&& next & WRITER == prev & WRITER
1230            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1231            &&& next & READER_MASK == prev & READER_MASK
1232            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1233            &&& next & MAX_READER == prev & MAX_READER
1234        },
1235        next == prev - UPGRADEABLE_READER && prev & UPGRADEABLE_READER != 0 ==> {
1236            &&& next & UPGRADEABLE_READER == 0
1237            &&& next & WRITER == prev & WRITER
1238            &&& next & READER_MASK == prev & READER_MASK
1239            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1240            &&& next & MAX_READER == prev & MAX_READER
1241            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1242        },
1243        next == prev - READER && prev & READER_MASK != 0 ==> {
1244            &&& next & READER_MASK == (prev & READER_MASK) - READER
1245            &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1246            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1247            &&& next & WRITER == prev & WRITER
1248            &&& next & MAX_READER == prev & MAX_READER
1249            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1250        },
1251        next == prev - READER && prev & MAX_READER_MASK != 0 ==> {
1252            &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1253            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1254            &&& next & WRITER == prev & WRITER
1255            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1256        },
1257        next == prev + READER && no_max_reader_overflow(prev) ==> {
1258            &&& next & READER_MASK == if (prev & READER_MASK) + READER == MAX_READER {
1259                0
1260            } else {
1261                (prev & READER_MASK) + READER
1262            }
1263            &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) + READER
1264            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1265            &&& next & WRITER == prev & WRITER
1266            &&& next & MAX_READER == if (prev & READER_MASK) + READER == MAX_READER {
1267                MAX_READER
1268            } else {
1269                prev & MAX_READER
1270            }
1271            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1272        },
1273        next == prev & !WRITER ==> {
1274            &&& next & WRITER == 0
1275            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1276            &&& next & READER_MASK == prev & READER_MASK
1277            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1278            &&& next & MAX_READER == prev & MAX_READER
1279            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1280        },
1281{
1282}
1283
1284} // verus!