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                    guard,
482                    inner: self,
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                    guard,
550                    inner: self,
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                    guard,
594                    inner: self,
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    /// Returns a mutable reference to the underlying data.
621    ///
622    /// This method is zero-cost: By holding a mutable reference to the lock, the compiler has
623    /// already statically guaranteed that access to the data is exclusive.
624    pub fn get_mut(&mut self) -> &mut T {
625        self.val.get_mut()
626    }
627
628    /// Returns a raw pointer to the underlying data.
629    ///
630    /// This method is safe, but it's up to the caller to ensure that access to the data behind it
631    /// is still safe.
632    pub(super) fn as_ptr(&self) -> *mut T {
633        self.val.get()
634    }*/
635
636}
637
638/* the trait `core::fmt::Debug` is not implemented for `vstd::cell::pcell::PCell<T>`
639impl<T: ?Sized + fmt::Debug, G> fmt::Debug for RwLock<T, G> {
640    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
641        fmt::Debug::fmt(&self.val, f)
642    }
643}*/
644
645/// Because there can be more than one readers to get the T's immutable ref,
646/// so T must be Sync to guarantee the sharing safety.
647#[verifier::external]
648unsafe impl<T: Send, G> Send for RwLock<T, G> {
649
650}
651
652#[verifier::external]
653unsafe impl<T: Send + Sync, G> Sync for RwLock<T, G> {
654
655}
656
657impl<T  /*: ?Sized*/ , G: SpinGuardian> !Send for RwLockWriteGuard<'_, T, G> {
658
659}
660
661#[verifier::external]
662unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockWriteGuard<'_, T, G> {
663
664}
665
666impl<T  /*: ?Sized*/ , G: SpinGuardian> !Send for RwLockReadGuard<'_, T, G> {
667
668}
669
670#[verifier::external]
671unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockReadGuard<'_, T, G> {
672
673}
674
675impl<T  /*: ?Sized*/ , G: SpinGuardian> !Send for RwLockUpgradeableGuard<'_, T, G> {
676
677}
678
679#[verifier::external]
680unsafe impl<T: Sync, G: SpinGuardian> Sync for RwLockUpgradeableGuard<'_, T, G> {
681
682}
683
684/// A guard that provides immutable data access.
685#[verifier::reject_recursive_types(T)]
686#[verifier::reject_recursive_types(G)]
687#[clippy::has_significant_drop]
688#[must_use]
689#[verus_verify]
690pub struct RwLockReadGuard<'a, T  /*: ?Sized*/ , G: SpinGuardian> {
691    guard: G::ReadGuard,
692    inner: &'a RwLock<T, G>,
693    tracked_token: Tracked<Count<ReadPerm<T>, MAX_READER>>,
694}
695
696/*
697impl<T: ?Sized, G: SpinGuardian> AsAtomicModeGuard for RwLockReadGuard<'_, T, G> {
698    fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
699        self.guard.as_atomic_mode_guard()
700    }
701}
702*/
703
704impl<'a, T, G: SpinGuardian> RwLockReadGuard<'a, T, G> {
705    #[verifier::type_invariant]
706    pub closed spec fn type_inv(self) -> bool {
707        let resource = self.tracked_token@.resource();
708        let read_half_cell_perm = resource.0;
709        let mode_knowledge = resource.1;
710        &&& self.inner.core_token_id() == mode_knowledge.id()
711        &&& self.inner.frac_id() == read_half_cell_perm.id()
712        &&& self.inner.cell_id() == read_half_cell_perm.resource().id()
713        &&& self.tracked_token@.id() == self.inner.read_guard_token_id()
714        &&& read_half_cell_perm.frac() == 1
715        &&& self.tracked_token@.frac() == 1
716    }
717
718    /// The value stored in the lock.
719    pub closed spec fn value(self) -> T {
720        *self.tracked_token@.resource().0.resource().value()
721    }
722
723    /// The value stored in the lock. It is an alias of `Self::value`.
724    pub open spec fn view(self) -> T {
725        self.value()
726    }
727}
728
729impl<T  /*: ?Sized*/ , G: SpinGuardian> Deref for RwLockReadGuard<'_, T, G> {
730    type Target = T;
731
732    #[verus_spec(returns self.view())]
733    fn deref(&self) -> &T {
734        proof!{
735            use_type_invariant(self);
736        }
737        // unsafe { &*self.inner.val.get() }
738        // The internal implementation of `PCell<T>::borrow` is exactly unsafe { &(*(*self.ucell).get()) },
739        // and here we verify that we have the permission to call `borrow`.
740        self.inner.val.borrow(
741            Tracked(self.tracked_token.borrow().tracked_borrow().0.tracked_borrow()),
742        )
743    }
744}
745
746/* impl<T: ?Sized, R: Deref<Target = RwLock<T, G>> + Clone, G: SpinGuardian> Drop
747    for RwLockReadGuard_<T, R, G>
748{
749    fn drop(&mut self) {
750        self.inner.lock.fetch_sub(READER, Release);
751    }
752} */
753
754#[verus_verify]
755impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLockReadGuard<'_, T, G> {
756    /// VERUS LIMITATION: We implement `drop` and call it manually because Verus's support for `Drop` is incomplete for now.
757    #[verus_spec]
758    fn drop(self) {
759        proof! {
760            use_type_invariant(&self);
761            use_type_invariant(self.inner);
762            lemma_consts_properties();
763        }
764        proof_decl! {
765            let tracked token = self.tracked_token.get();
766        }
767        // self.inner.lock.fetch_sub(READER, Release);
768        atomic_with_ghost!(
769            self.inner.lock => fetch_sub(READER);
770            update prev -> next;
771            ghost g => {
772                let prev_usize = prev as usize;
773                let next_usize = next as usize;
774                assume (no_max_reader_overflow(prev_usize));
775                lemma_consts_properties_value(next_usize);
776                lemma_consts_properties_prev_next(prev_usize, next_usize);
777                g.core_token.validate_with_one_left_knowledge(&token.tracked_borrow().1);
778                g.read_guard_token.combine(token);
779            }
780        );
781    }
782}
783
784/*
785impl<T: ?Sized + fmt::Debug, G: SpinGuardian> fmt::Debug for RwLockReadGuard<'_, T, G> {
786    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
787        fmt::Debug::fmt(&**self, f)
788    }
789}*/
790
791/// A guard that provides mutable data access.
792#[verifier::reject_recursive_types(T)]
793#[verifier::reject_recursive_types(G)]
794pub struct RwLockWriteGuard<'a, T  /*: ?Sized*/ , G: SpinGuardian> {
795    guard: G::Guard,
796    inner: &'a RwLock<T, G>,
797    /// Ghost permission for verification
798    tracked_perm: Tracked<PointsTo<T>>,
799    tracked_token: Tracked<OneRightKnowledge<HalfPerm<T>, NoPerm<T>, 3>>,
800}
801
802impl<'a, T, G: SpinGuardian> RwLockWriteGuard<'a, T, G> {
803    #[verifier::type_invariant]
804    spec fn type_inv(self) -> bool {
805        &&& self.inner.cell_id() == self.tracked_perm@.id()
806        &&& self.inner.core_token_id() == self.tracked_token@.id()
807    }
808
809    /// The value stored in the lock.
810    pub closed spec fn value(self) -> T {
811        *self.tracked_perm@.value()
812    }
813
814    /// The value stored in the lock. It is an alias of `Self::value`.
815    pub open spec fn view(self) -> T {
816        self.value()
817    }
818}
819
820/*
821impl<T: ?Sized, G: SpinGuardian> AsAtomicModeGuard for RwLockWriteGuard<'_, T, G> {
822    fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
823        self.guard.as_atomic_mode_guard()
824    }
825}*/
826
827impl<T  /*: ?Sized*/ , G: SpinGuardian> Deref for RwLockWriteGuard<'_, T, G> {
828    type Target = T;
829
830    #[verus_spec(returns self.view())]
831    fn deref(&self) -> &T {
832        proof!{
833            use_type_invariant(self);
834        }
835        // unsafe { &*self.inner.val.get() }
836        // The internal implementation of `PCell<T>::borrow` is exactly unsafe { &(*(*self.ucell).get()) },
837        // and here we verify that we have the permission to call `borrow`.
838        self.inner.val.borrow(Tracked(self.tracked_perm.borrow()))
839    }
840}
841
842#[verus_verify]
843impl<T  /*: ?Sized*/ , G: SpinGuardian> DerefMut for RwLockWriteGuard<'_, T, G> {
844    #[verus_spec(ret =>
845        ensures
846            final(self).view() == *final(ret),
847            old(self).view() == *ret,
848    )]
849    fn deref_mut(&mut self) -> &mut Self::Target {
850        proof!{
851            use_type_invariant(&*self);
852        }
853        //unsafe { &mut *self.inner.val.get() }
854        self.inner.val.borrow_mut(Tracked(&mut *self.tracked_perm))
855    }
856}
857
858/*
859impl<T: ?Sized, G: SpinGuardian> Drop for RwLockWriteGuard<'_, T, G> {
860    fn drop(&mut self) {
861        self.inner.lock.fetch_and(!WRITER, Release);
862    }
863}*/
864
865impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLockWriteGuard<'_, T, G> {
866    /// VERUS LIMITATION: We implement `drop` and call it manually because Verus's support for `Drop` is incomplete for now.
867    pub fn drop(self) {
868        proof!{
869            use_type_invariant(&self);
870            use_type_invariant(self.inner);
871            lemma_consts_properties();
872        }
873        proof_decl! {
874            let tracked mut perm = self.tracked_perm.get();
875            let tracked token = self.tracked_token.get();
876        }
877        //self.inner.lock.fetch_and(!WRITER, Release);
878        atomic_with_ghost!{
879            self.inner.lock => fetch_and(!WRITER);
880            update prev -> next;
881            ghost g => {
882                let prev_usize = prev as usize;
883                let next_usize = next as usize;
884                lemma_consts_properties_prev_next(prev_usize, next_usize);
885                lemma_consts_properties_value(next_usize);
886                g.core_token.validate_with_one_right_knowledge(&token);
887                g.core_token.join_one_right_knowledge(token);
888                let tracked empty = g.core_token.take_resource_right();
889                let tracked mut full = empty.put_resource(perm);
890                let tracked read_half_cell_perm = full.split(1int);
891                g.core_token.change_to_left(full);
892                let tracked upreader_guard_token = g.core_token.split_one_left_owner();
893                g.upreader_guard_token = Some(upreader_guard_token);
894                let tracked left_token = g.core_token.split_one_left_knowledge();
895                g.read_guard_token.put_resource((read_half_cell_perm, left_token));
896            }
897        };
898    }
899}
900
901/*
902impl<T: ?Sized + fmt::Debug, G: SpinGuardian> fmt::Debug for RwLockWriteGuard<'_, T, G> {
903    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
904        fmt::Debug::fmt(&**self, f)
905    }
906}*/
907
908/// A guard that provides immutable data access but can be atomically
909/// upgraded to `RwLockWriteGuard`.
910#[verifier::reject_recursive_types(T)]
911#[verifier::reject_recursive_types(G)]
912pub struct RwLockUpgradeableGuard<'a, T  /*: ?Sized*/ , G: SpinGuardian> {
913    guard: G::Guard,
914    inner: &'a RwLock<T, G>,
915    tracked_token: Tracked<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>>,
916}
917
918/*
919impl<T: ?Sized, G: SpinGuardian> AsAtomicModeGuard for RwLockUpgradeableGuard<'_, T, G> {
920    fn as_atomic_mode_guard(&self) -> &dyn crate::task::atomic_mode::InAtomicMode {
921        self.guard.as_atomic_mode_guard()
922    }
923}*/
924
925impl<'a, T, G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
926    #[verifier::type_invariant]
927    pub closed spec fn type_inv(self) -> bool {
928        wf_upgradeable_guard_token(
929            self.inner.core_token_id(),
930            self.inner.frac_id(),
931            self.inner.cell_id(),
932            self.tracked_token@,
933        )
934    }
935
936    /// The value stored in the lock.
937    pub closed spec fn value(self) -> T {
938        *self.tracked_token@.resource().resource().value()
939    }
940
941    /// The value stored in the lock. It is an alias of `Self::value`.
942    pub open spec fn view(self) -> T {
943        self.value()
944    }
945}
946
947impl<'a, T  /*: ?Sized*/ , G: SpinGuardian> RwLockUpgradeableGuard<'a, T, G> {
948    /// Upgrades this upread guard to a write guard atomically.
949    ///
950    /// After calling this method, subsequent readers will be blocked
951    /// while previous readers remain unaffected. The calling thread
952    /// will spin-wait until previous readers finish.
953    #[verifier::exec_allows_no_decreases_clause]
954    pub fn upgrade(mut self) -> RwLockWriteGuard<'a, T, G> {
955        proof! {
956            use_type_invariant(&self);
957            use_type_invariant(&self.inner);
958            lemma_consts_properties();
959        }
960        // self.inner.lock.fetch_or(BEING_UPGRADED, Acquire);
961        atomic_with_ghost!(
962            self.inner.lock => fetch_or(BEING_UPGRADED);
963            update prev -> next;
964            ghost g => {
965                lemma_consts_properties_prev_next(prev, next);
966            }
967        );
968        loop {
969            self =
970            match self.try_upgrade() {
971                Ok(guard) => return guard,
972                Err(e) => e,
973            };
974        }
975    }
976
977    // [FIXED] BUG FOUND BY FV: deadlock. https://github.com/asterinas/asterinas/pull/3007
978    /// Attempts to upgrade this upread guard to a write guard atomically.
979    ///
980    /// This function will never spin-wait and will return immediately.
981    ///
982    /// This function is not exposed publicly because the `BEING_UPGRADED` bit
983    /// is set only in [`Self::upgrade`].
984    fn try_upgrade(mut self) -> Result<RwLockWriteGuard<'a, T, G>, Self> {
985        proof! {
986            use_type_invariant(&self);
987            use_type_invariant(self.inner);
988            lemma_consts_properties();
989        }
990        proof_decl! {
991            let tracked mut upread_guard_token = self.tracked_token.get();
992            let tracked mut write_perm: Option<PointsTo<T>> = None;
993            let tracked mut err_upread_guard_token: Option<OneLeftOwner<HalfPerm<T>, NoPerm<T>, 3>> = None;
994            let tracked mut retract_upgrade_token: Option<UniqueToken> = None;
995            let tracked mut write_guard_token = None;
996        }
997
998        // let res = self.inner.lock.compare_exchange(
999        //     UPGRADEABLE_READER | BEING_UPGRADED,
1000        //     WRITER | UPGRADEABLE_READER,
1001        //     AcqRel,
1002        //     Relaxed,
1003        // );
1004        let res =
1005            atomic_with_ghost!(
1006            self.inner.lock => compare_exchange(UPGRADEABLE_READER | BEING_UPGRADED, WRITER | UPGRADEABLE_READER);
1007            update prev -> next;
1008            returning res;
1009            ghost g => {
1010                lemma_consts_properties_prev_next(prev, next);
1011                if res is Ok {
1012                    g.core_token.validate_with_one_left_owner(&upread_guard_token);
1013                    if g.upreader_guard_token is Some {
1014                        upread_guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1015                    }
1016                    g.core_token.join_one_left_owner(upread_guard_token);
1017                    let tracked read_resource = g.read_guard_token.take_resource();
1018                    let tracked (read_half_cell_perm, left_token) = read_resource;
1019                    g.core_token.join_one_left_knowledge(left_token);
1020                    let tracked mut pointsto = g.core_token.take_resource_left();
1021                    pointsto.combine(read_half_cell_perm);
1022                    let tracked (pointsto, empty) = pointsto.take_resource();
1023                    write_perm = Some(pointsto);
1024                    g.core_token.change_to_right(empty);
1025                    write_guard_token = Some(g.core_token.split_one_right_knowledge());
1026                    retract_upgrade_token = Some(g.upread_retract_token.tracked_take());
1027                } else {
1028                    err_upread_guard_token = Some(upread_guard_token);
1029                }
1030            }
1031        );
1032        if res.is_ok() {
1033            let guard = self.guard.transfer_to();
1034            let inner = self.inner;
1035            // drop(self);
1036            atomic_with_ghost!(
1037                inner.lock => fetch_sub(UPGRADEABLE_READER);
1038                update prev -> next;
1039                ghost g => {
1040                    let prev_usize = prev as usize;
1041                    let next_usize = next as usize;
1042                    lemma_consts_properties_value(prev_usize);
1043                    lemma_consts_properties_prev_next(prev_usize, next_usize);
1044                    let tracked mut token = retract_upgrade_token.tracked_unwrap();
1045                    if g.upread_retract_token is Some {
1046                        token.validate_with_other(g.upread_retract_token.tracked_borrow());
1047                    }
1048                    g.upread_retract_token = Some(token);
1049                }
1050            );
1051            Ok(
1052                RwLockWriteGuard {
1053                    guard,
1054                    inner,
1055                    tracked_perm: Tracked(write_perm.tracked_unwrap()),
1056                    tracked_token: Tracked(write_guard_token.tracked_unwrap()),
1057                },
1058            )
1059        } else {
1060            Err(
1061                RwLockUpgradeableGuard {
1062                    guard: self.guard,
1063                    inner: self.inner,
1064                    tracked_token: Tracked(err_upread_guard_token.tracked_unwrap()),
1065                },
1066            )
1067        }
1068    }
1069}
1070
1071impl<T  /*: ?Sized*/ , G: SpinGuardian> Deref for RwLockUpgradeableGuard<'_, T, G> {
1072    type Target = T;
1073
1074    #[verus_spec(returns self.view())]
1075    fn deref(&self) -> &T {
1076        proof!{
1077            use_type_invariant(self);
1078        }
1079        // unsafe { &*self.inner.val.get() }
1080        // The internal implementation of `PCell<T>::borrow` is exactly unsafe { &(*(*self.ucell).get()) },
1081        // and here we verify that we have the permission to call `borrow`.
1082        self.inner.val.borrow(
1083            Tracked(self.tracked_token.borrow().tracked_borrow().tracked_borrow()),
1084        )
1085    }
1086}
1087
1088/*
1089impl<T: ?Sized, G: SpinGuardian> Drop for RwLockUpgradeableGuard<'_, T, G> {
1090    fn drop(&mut self) {
1091        self.inner.lock.fetch_sub(UPGRADEABLE_READER, Release);
1092    }
1093}*/
1094
1095impl<T  /*: ?Sized*/ , G: SpinGuardian> RwLockUpgradeableGuard<'_, T, G> {
1096    /// VERUS LIMITATION: We implement `drop` and call it manually because Verus's support for `Drop` is incomplete for now.
1097    pub fn drop(self) {
1098        proof! {
1099            use_type_invariant(&self);
1100            use_type_invariant(self.inner);
1101            lemma_consts_properties();
1102        }
1103        proof_decl!{
1104            let tracked guard_token = self.tracked_token.get();
1105        }
1106        //self.inner.lock.fetch_sub(UPGRADEABLE_READER, Release);
1107        atomic_with_ghost!(
1108            self.inner.lock => fetch_sub(UPGRADEABLE_READER);
1109            update prev -> next;
1110            ghost g => {
1111                let prev_usize = prev as usize;
1112                let next_usize = next as usize;
1113                lemma_consts_properties_value(prev_usize);
1114                lemma_consts_properties_prev_next(prev_usize, next_usize);
1115                g.core_token.validate_with_one_left_owner(&guard_token);
1116                if g.upreader_guard_token is Some {
1117                    guard_token.validate_with_one_left_owner(g.upreader_guard_token.tracked_borrow());
1118                    assert(false);
1119                } else {
1120                    g.upreader_guard_token= Some(guard_token);
1121                }
1122            }
1123        );
1124    }
1125}
1126
1127/*
1128impl<T: ?Sized + fmt::Debug, G: SpinGuardian> fmt::Debug for RwLockUpgradeableGuard<'_, T, G> {
1129    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1130        fmt::Debug::fmt(&**self, f)
1131    }
1132}
1133*/
1134
1135#[verifier::bit_vector]
1136proof fn lemma_consts_properties()
1137    ensures
1138        0 & WRITER == 0,
1139        0 & UPGRADEABLE_READER == 0,
1140        0 & BEING_UPGRADED == 0,
1141        0 & READER_MASK == 0,
1142        0 & MAX_READER_MASK == 0,
1143        0 & MAX_READER == 0,
1144        0 & READER == 0,
1145        WRITER == 0x8000_0000_0000_0000,
1146        UPGRADEABLE_READER == 0x4000_0000_0000_0000,
1147        BEING_UPGRADED == 0x2000_0000_0000_0000,
1148        READER_MASK == 0x0FFF_FFFF_FFFF_FFFF,
1149        MAX_READER_MASK == 0x1FFF_FFFF_FFFF_FFFF,
1150        MAX_READER == 0x1000_0000_0000_0000,
1151        WRITER & WRITER == WRITER,
1152        WRITER & !WRITER == 0,
1153        WRITER & BEING_UPGRADED == 0,
1154        WRITER & READER_MASK == 0,
1155        WRITER & MAX_READER_MASK == 0,
1156        WRITER & MAX_READER == 0,
1157        WRITER & UPGRADEABLE_READER == 0,
1158        BEING_UPGRADED & WRITER == 0,
1159        BEING_UPGRADED & UPGRADEABLE_READER == 0,
1160        UPGRADEABLE_READER & BEING_UPGRADED == 0,
1161        UPGRADEABLE_READER & READER_MASK == 0,
1162        UPGRADEABLE_READER & MAX_READER_MASK == 0,
1163        UPGRADEABLE_READER & MAX_READER == 0,
1164        BEING_UPGRADED & READER_MASK == 0,
1165        BEING_UPGRADED & MAX_READER_MASK == 0,
1166        BEING_UPGRADED & MAX_READER == 0,
1167        (UPGRADEABLE_READER | BEING_UPGRADED) & WRITER == 0,
1168        (UPGRADEABLE_READER | BEING_UPGRADED) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1169        (UPGRADEABLE_READER | BEING_UPGRADED) & BEING_UPGRADED == BEING_UPGRADED,
1170        (UPGRADEABLE_READER | BEING_UPGRADED) & READER_MASK == 0,
1171        (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER_MASK == 0,
1172        (UPGRADEABLE_READER | BEING_UPGRADED) & MAX_READER == 0,
1173        (WRITER | UPGRADEABLE_READER) & WRITER == WRITER,
1174        (WRITER | UPGRADEABLE_READER) & UPGRADEABLE_READER == UPGRADEABLE_READER,
1175        (WRITER | UPGRADEABLE_READER) & BEING_UPGRADED == 0,
1176        (WRITER | UPGRADEABLE_READER) & READER_MASK == 0,
1177        (WRITER | UPGRADEABLE_READER) & MAX_READER_MASK == 0,
1178        (WRITER | UPGRADEABLE_READER) & MAX_READER == 0,
1179{
1180}
1181
1182#[verifier::bit_vector]
1183proof fn lemma_consts_properties_value(prev: usize)
1184    ensures
1185        no_max_reader_overflow(prev) ==> prev + READER <= usize::MAX,
1186        prev & (WRITER | MAX_READER | BEING_UPGRADED) == 0 ==> {
1187            &&& prev & WRITER == 0
1188            &&& prev & BEING_UPGRADED == 0
1189            &&& prev & MAX_READER == 0
1190        },
1191        prev & (WRITER | UPGRADEABLE_READER) == 0 ==> {
1192            &&& prev & WRITER == 0
1193            &&& prev & UPGRADEABLE_READER == 0
1194        },
1195        prev & MAX_READER == 0 ==> prev & READER_MASK == prev & MAX_READER_MASK,
1196        prev & MAX_READER != 0 ==> prev & MAX_READER_MASK >= MAX_READER,
1197        prev & (WRITER | UPGRADEABLE_READER) == WRITER ==> {
1198            &&& prev & UPGRADEABLE_READER == 0
1199            &&& prev & WRITER == WRITER
1200        },
1201        prev & UPGRADEABLE_READER != 0 ==> prev >= UPGRADEABLE_READER,
1202        prev & UPGRADEABLE_READER == 0 ==> {
1203            ||| prev & (WRITER | UPGRADEABLE_READER) == 0
1204            ||| prev & (WRITER | UPGRADEABLE_READER) == WRITER
1205        },
1206{
1207}
1208
1209#[verifier::bit_vector]
1210proof fn lemma_consts_properties_prev_next(prev: usize, next: usize)
1211    ensures
1212        prev & READER_MASK < MAX_READER,
1213        next == prev | UPGRADEABLE_READER ==> {
1214            &&& next & UPGRADEABLE_READER != 0
1215            &&& next & WRITER == prev & WRITER
1216            &&& next & READER_MASK == prev & READER_MASK
1217            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1218            &&& next & MAX_READER == prev & MAX_READER
1219            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1220        },
1221        next == prev | BEING_UPGRADED ==> {
1222            &&& next & BEING_UPGRADED != 0
1223            &&& next & WRITER == prev & WRITER
1224            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1225            &&& next & READER_MASK == prev & READER_MASK
1226            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1227            &&& next & MAX_READER == prev & MAX_READER
1228        },
1229        next == prev - UPGRADEABLE_READER && prev & UPGRADEABLE_READER != 0 ==> {
1230            &&& next & UPGRADEABLE_READER == 0
1231            &&& next & WRITER == prev & WRITER
1232            &&& next & READER_MASK == prev & READER_MASK
1233            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1234            &&& next & MAX_READER == prev & MAX_READER
1235            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1236        },
1237        next == prev - READER && prev & READER_MASK != 0 ==> {
1238            &&& next & READER_MASK == (prev & READER_MASK) - READER
1239            &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1240            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1241            &&& next & WRITER == prev & WRITER
1242            &&& next & MAX_READER == prev & MAX_READER
1243            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1244        },
1245        next == prev - READER && prev & MAX_READER_MASK != 0 ==> {
1246            &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) - READER
1247            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1248            &&& next & WRITER == prev & WRITER
1249            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1250        },
1251        next == prev + READER && no_max_reader_overflow(prev) ==> {
1252            &&& next & READER_MASK == if (prev & READER_MASK) + READER == MAX_READER {
1253                0
1254            } else {
1255                (prev & READER_MASK) + READER
1256            }
1257            &&& next & MAX_READER_MASK == (prev & MAX_READER_MASK) + READER
1258            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1259            &&& next & WRITER == prev & WRITER
1260            &&& next & MAX_READER == if (prev & READER_MASK) + READER == MAX_READER {
1261                MAX_READER
1262            } else {
1263                prev & MAX_READER
1264            }
1265            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1266        },
1267        next == prev & !WRITER ==> {
1268            &&& next & WRITER == 0
1269            &&& next & UPGRADEABLE_READER == prev & UPGRADEABLE_READER
1270            &&& next & READER_MASK == prev & READER_MASK
1271            &&& next & MAX_READER_MASK == prev & MAX_READER_MASK
1272            &&& next & MAX_READER == prev & MAX_READER
1273            &&& next & BEING_UPGRADED == prev & BEING_UPGRADED
1274        },
1275{
1276}
1277
1278} // verus!