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