1#[cfg(creusot)]
2use crate::sync_view::Objective;
3
4use crate::{
5 ghost::{Container, FnGhost, perm::Perm},
6 logic::FMap,
7 prelude::*,
8 sync_view::{HasTimestamp, SyncView, Timestamp},
9};
10use core::marker::PhantomData;
11
12macro_rules! impl_atomic {
13 ($( ($type:ty, $atomic_type:ident $(< $T:ident >)?) ),+) => { $(
14
15 #[doc = concat!("Creusot wrapper around [`std::sync::atomic::", stringify!($atomic_type), "`].")]
16 pub struct $atomic_type $(< $T >)?(::std::sync::atomic::$atomic_type $(< $T >)?);
17
18 unsafe impl $(< $T >)? Send for Perm<$atomic_type $(< $T >)?> {}
19 unsafe impl $(< $T >)? Sync for Perm<$atomic_type $(< $T >)?> {}
20
21 #[cfg(creusot)]
22 #[trusted]
23 impl $(< $T >)? Objective for Perm<$atomic_type $(< $T >)?> {}
24
25 impl $(< $T >)? Container for $atomic_type $(< $T >)? {
26 type Value = FMap<Timestamp, ($type, SyncView)>;
27
28 #[logic(open, inline)]
29 fn is_disjoint(&self, _: &Self::Value, other: &Self, _: &Self::Value) -> bool {
30 self != other
31 }
32 }
33
34 impl $(< $T >)? HasTimestamp for $atomic_type $(< $T >)? {
35 #[logic(opaque)]
36 fn get_timestamp(self, _: SyncView) -> Timestamp {
37 dead
38 }
39
40 #[logic(law)]
41 #[requires(x.le_log(y))]
42 #[ensures(self.get_timestamp(x).le_log(self.get_timestamp(y)))]
43 #[trusted]
44 fn get_timestamp_monotonic(self, x: SyncView, y: SyncView) {}
45 }
46
47 impl $(< $T >)? $atomic_type $(< $T >)? {
48 #[ensures(*result.1.val() == FMap::singleton(result.0.get_timestamp(^view), (val, **view)))]
49 #[ensures(*result.1.ward() == result.0)]
50 #[trusted]
51 #[check(terminates)]
52 #[allow(unused_variables)]
53 pub fn new(val: $type, view: Ghost<&mut SyncView>) -> (Self, Ghost<Box<Perm<$atomic_type $(< $T >)?>>>) {
54 (Self(std::sync::atomic::$atomic_type::new(val)), Ghost::conjure())
55 }
56
57 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::load`].")]
60 #[requires(forall<c: &LoadCommitter<$type, Self>> c.ward() == *self ==> f.precondition((c,)))]
61 #[ensures(exists<c: &LoadCommitter<$type, Self>>
62 c.ward() == *self && c.val() == result && f.postcondition_once((c,), ())
63 )]
64 #[trusted]
65 #[allow(unused_variables)]
66 pub fn load<F>(&self, f: Ghost<F>) -> $type
67 where
68 F: FnGhost + FnOnce(&LoadCommitter<$type, Self>),
69 {
70 self.0.load(if cfg!(feature = "sc-drf") {
71 ::std::sync::atomic::Ordering::SeqCst
72 } else {
73 ::std::sync::atomic::Ordering::Acquire
74 })
75 }
76
77 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::store`].")]
78 #[requires(forall<c: &mut StoreCommitter<$type, Self>> !c.shot() ==> c.ward() == *self ==> c.val() == val ==>
79 f.precondition((c,)) && f.postcondition_once((c,), ()) ==> (^c).shot()
80 )]
81 #[ensures(exists<c: &mut StoreCommitter<$type, Self>>
82 !c.shot() && c.ward() == *self && c.val() == val &&
83 f.postcondition_once((c,), ())
84 )]
85 #[trusted]
86 #[allow(unused_variables)]
87 pub fn store<F>(&self, val: $type, f: Ghost<F>)
88 where
89 F: FnGhost + FnOnce(&mut StoreCommitter<$type, Self>),
90 {
91 self.0.store(
92 val,
93 if cfg!(feature = "sc-drf") {
94 ::std::sync::atomic::Ordering::SeqCst
95 } else {
96 ::std::sync::atomic::Ordering::Release
97 },
98 )
99 }
100 }
101
102 )* };
103}
104
105macro_rules! impl_atomic_int {
106 ($( ($int_type:ty, $atomic_type:ident) ),+) => { $(
107
108 impl_atomic!(($int_type, $atomic_type));
109
110 )* };
113}
114
115impl_atomic! {
116 (bool, AtomicBool),
117 (*mut T, AtomicPtr<T>)
118}
119
120impl_atomic_int! {
121 (i8, AtomicI8),
122 (u8, AtomicU8),
123 (i16, AtomicI16),
124 (u16, AtomicU16),
125 (i32, AtomicI32),
126 (u32, AtomicU32),
127 (i64, AtomicI64),
128 (u64, AtomicU64),
129 (isize, AtomicIsize),
130 (usize, AtomicUsize)
131}
132
133#[opaque]
141pub struct LoadCommitter<T, C: Container<Value = FMap<Timestamp, (T, SyncView)>>>(
142 PhantomData<(T, C)>,
143);
144
145impl<T, C: Container<Value = FMap<Timestamp, (T, SyncView)>> + HasTimestamp> LoadCommitter<T, C> {
146 #[logic(opaque)]
150 pub fn ward(self) -> C {
151 dead
152 }
153
154 #[logic(opaque)]
156 pub fn val(self) -> T {
157 dead
158 }
159
160 #[requires(self.ward() == *own.ward())]
164 #[ensures((*view).le_log(^view))]
165 #[ensures(self.ward().get_timestamp(*view) <= result)]
166 #[ensures(result <= self.ward().get_timestamp(^view))]
167 #[ensures(match own.val().get(result) {
168 Some((v, v_view)) => v == self.val() && v_view.le_log(^view),
169 None => false
170 })]
171 #[check(ghost)]
172 #[trusted]
173 #[allow(unused_variables)]
174 pub fn shoot(&self, own: &Perm<C>, view: &mut SyncView) -> Timestamp {
175 panic!("Should not be called outside ghost code")
176 }
177}
178
179#[opaque]
182pub struct StoreCommitter<T, C: Container<Value = FMap<Timestamp, (T, SyncView)>>>(
183 PhantomData<(T, C)>,
184);
185
186impl<T, C: Container<Value = FMap<Timestamp, (T, SyncView)>> + HasTimestamp> StoreCommitter<T, C> {
187 #[logic(opaque)]
189 pub fn shot(self) -> bool {
190 dead
191 }
192
193 #[logic(opaque)]
197 pub fn ward(self) -> C {
198 dead
199 }
200
201 #[logic(opaque)]
203 pub fn val(self) -> T {
204 dead
205 }
206
207 #[requires(!(*self).shot())]
211 #[requires(self.ward() == *(*own).ward())]
212 #[ensures((^self).shot())]
213 #[ensures((*self).ward() == (^self).ward() && (*self).val() == (^self).val())]
214 #[ensures((*own).ward() == (^own).ward())]
215 #[ensures((*view).le_log(^view))]
216 #[ensures((*self).ward().get_timestamp(*view) < result)]
217 #[ensures(result <= (*self).ward().get_timestamp(^view))]
218 #[ensures((*own).val().get(result) == None)]
219 #[ensures(*(^own).val() == (*own).val().insert(result, ((*self).val(), (*view))))]
220 #[check(ghost)]
221 #[trusted]
222 #[allow(unused_variables)]
223 pub fn shoot(&mut self, own: &mut Perm<C>, view: &mut SyncView) -> Timestamp {
224 panic!("Should not be called outside ghost code")
225 }
226}