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