1use crate::{
2 ghost::{FnGhost, Perm, perm::PermTarget},
3 prelude::*,
4 std::sync::committer::Committer,
5};
6use core::sync::atomic::Ordering as OrderingTy;
7
8pub mod ordering {
9 pub struct SeqCst;
10}
11use ordering::SeqCst;
12
13macro_rules! impl_atomic {
14 ($( ($type:ty, $atomic_type:ident $(< $T:ident >)?) ),+) => { $(
15
16 #[doc = concat!("Creusot wrapper around [`std::sync::atomic::", stringify!($atomic_type), "`].")]
18 pub struct $atomic_type $(< $T >)?(::core::sync::atomic::$atomic_type $(< $T >)?);
19
20 impl $(< $T >)? PermTarget for $atomic_type $(< $T >)? {
21 type Value = $type;
22 type Objectiveness = ();
23 }
24
25 impl $(< $T >)? $atomic_type $(< $T >)? {
26 #[ensures(result.1.val() == val)]
27 #[ensures(*result.1.ward() == result.0)]
28 #[inline(always)]
29 #[trusted]
30 #[check(terminates)]
31 pub fn new(val: $type) -> (Self, Ghost<Perm<$atomic_type $(< $T >)?>>) {
32 (Self(::core::sync::atomic::$atomic_type::new(val)), Ghost::conjure())
33 }
34
35 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::into_inner`].")]
36 #[requires(self == *own.ward())]
37 #[ensures(result == own.val())]
38 #[inline(always)]
39 #[trusted]
40 #[allow(unused_variables)]
41 pub fn into_inner(self, own: Ghost<Perm<$atomic_type $(< $T >)?>>) -> $type {
42 self.0.into_inner()
43 }
44
45 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::compare_exchange`].")]
46 #[doc = ""]
47 #[doc = "The load and the store are always sequentially consistent."]
48 #[requires(forall<c: &mut Committer<Self, $type, SeqCst, SeqCst>>
49 !c.shot_store() ==> c.ward() == *self ==>
50 c.val_load().deep_model() == current.deep_model() ==>
51 c.val_store() == new ==>
52 f.precondition((Ok(c),)) && (f.postcondition_once((Ok(c),), ()) ==> (^c).shot_store())
53 )]
54 #[requires(forall<c: &Committer<Self, $type, SeqCst, ()>>
55 !c.shot_store() ==> c.ward() == *self ==>
56 c.val_load().deep_model() != current.deep_model() ==>
58 f.precondition((Err(c),))
59 )]
60 #[ensures(
61 match result {
62 Ok(result) => {
63 exists<c: &mut Committer<Self, $type, SeqCst, SeqCst>>
64 !c.shot_store() && c.ward() == *self &&
65 c.val_load().deep_model() == current.deep_model() &&
66 c.val_store() == new &&
67 result == c.val_load() &&
68 f.postcondition_once((Ok(c),), ())
69 },
70 Err(result) => {
71 exists<c: &Committer<Self, $type, SeqCst, ()>>
72 !c.shot_store() && c.ward() == *self &&
73 c.val_load().deep_model() != current.deep_model() &&
75 result == c.val_load() &&
76 f.postcondition_once((Err(c),), ())
77 }
78 }
79 )]
80 #[inline(always)]
81 #[trusted]
82 #[allow(unused_variables)]
83 pub fn compare_exchange<F>(&self, current: $type, new: $type, f: Ghost<F>) -> Result<$type, $type>
84 where
85 F: FnGhost + FnOnce(Result<
86 &mut Committer<Self, $type, SeqCst, SeqCst>,
87 &Committer<Self, $type, SeqCst, ()>
88 >,
89 )
90 {
91 self.0.compare_exchange(current, new, OrderingTy::SeqCst, OrderingTy::SeqCst)
92 }
93
94 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::compare_exchange_weak`].")]
95 #[doc = ""]
96 #[doc = "The load and the store are always sequentially consistent."]
97 #[requires(forall<c: &mut Committer<Self, $type, SeqCst, SeqCst>>
98 !c.shot_store() ==> c.ward() == *self ==>
99 c.val_load().deep_model() == current.deep_model() ==>
100 c.val_store() == new ==>
101 f.precondition((Ok(c),)) && (f.postcondition_once((Ok(c),), ()) ==> (^c).shot_store())
102 )]
103 #[requires(forall<c: &Committer<Self, $type, SeqCst, ()>>
104 !c.shot_store() ==> c.ward() == *self ==>
105 f.precondition((Err(c),))
106 )]
107 #[ensures(
108 match result {
109 Ok(result) => {
110 exists<c: &mut Committer<Self, $type, SeqCst, SeqCst>>
111 !c.shot_store() && c.ward() == *self &&
112 c.val_load().deep_model() == current.deep_model() &&
113 c.val_store() == new &&
114 result == c.val_load() &&
115 f.postcondition_once((Ok(c),), ())
116 },
117 Err(result) => {
118 exists<c: &Committer<Self, $type, SeqCst, ()>>
119 !c.shot_store() && c.ward() == *self &&
120 result == c.val_load() &&
121 f.postcondition_once((Err(c),), ())
122 }
123 }
124 )]
125 #[inline(always)]
126 #[trusted]
127 #[allow(unused_variables)]
128 pub fn compare_exchange_weak<F>(&self, current: $type, new: $type, f: Ghost<F>) -> Result<$type, $type>
129 where
130 F: FnGhost + FnOnce(Result<
131 &mut Committer<Self, $type, SeqCst, SeqCst>,
132 &Committer<Self, $type, SeqCst, ()>
133 >,
134 )
135 {
136 self.0.compare_exchange_weak(current, new, OrderingTy::SeqCst, OrderingTy::SeqCst)
137 }
138
139 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::load`].")]
140 #[doc = ""]
141 #[doc = "The load is always sequentially consistent."]
142 #[requires(forall<c: &Committer<Self, $type, SeqCst, ()>>
143 !c.shot_store() ==> c.ward() == *self ==> f.precondition((c,))
144 )]
145 #[ensures(exists<c: &Committer<Self, $type, SeqCst, ()>>
146 !c.shot_store() && c.ward() == *self && c.val_load() == result && f.postcondition_once((c,), ())
147 )]
148 #[inline(always)]
149 #[trusted]
150 #[allow(unused_variables)]
151 pub fn load<F>(&self, f: Ghost<F>) -> $type
152 where
153 F: FnGhost + FnOnce(&Committer<Self, $type, SeqCst, ()>),
154 {
155 self.0.load(OrderingTy::SeqCst)
156 }
157
158 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::store`].")]
159 #[doc = ""]
160 #[doc = "The store is always sequentially consistent."]
161 #[requires(forall<c: &mut Committer<Self, $type, (), SeqCst>>
162 !c.shot_store() ==> c.ward() == *self ==> c.val_store() == val ==>
163 f.precondition((c,)) && (f.postcondition_once((c,), ()) ==> (^c).shot_store())
164 )]
165 #[ensures(exists<c: &mut Committer<Self, $type, (), SeqCst>>
166 !c.shot_store() && c.ward() == *self && c.val_store() == val &&
167 f.postcondition_once((c,), ())
168 )]
169 #[inline(always)]
170 #[trusted]
171 #[allow(unused_variables)]
172 pub fn store<F>(&self, val: $type, f: Ghost<F>)
173 where
174 F: FnGhost + FnOnce(&mut Committer<Self, $type, (), SeqCst>),
175 {
176 self.0.store(val, OrderingTy::SeqCst)
177 }
178 }
179
180 )* };
181}
182
183macro_rules! impl_atomic_int {
184 ($( ($int_type:ty, $atomic_type:ident) ),+) => { $(
185
186 impl_atomic!(($int_type, $atomic_type));
187
188 impl $atomic_type {
189 #[doc = concat!("Wrapper for [`std::sync::atomic::", stringify!($atomic_type), "::fetch_add`].")]
190 #[doc = ""]
191 #[doc = "The load and the store are always sequentially consistent."]
192 #[requires(forall<c: &mut Committer<Self, $int_type, SeqCst, SeqCst>>
193 !c.shot_store() ==> c.ward() == *self ==> c.val_store() == val + c.val_load() ==>
194 f.precondition((c,)) && (f.postcondition_once((c,), ()) ==> (^c).shot_store())
195 )]
196 #[ensures(exists<c: &mut Committer<Self, $int_type, SeqCst, SeqCst>>
197 !c.shot_store() && c.ward() == *self && c.val_store() == val + c.val_load() &&
198 c.val_load() == result && f.postcondition_once((c,), ())
199 )]
200 #[inline(always)]
201 #[trusted]
202 #[allow(unused_variables)]
203 pub fn fetch_add<F>(&self, val: $int_type, f: Ghost<F>) -> $int_type
204 where
205 F: FnGhost + FnOnce(&mut Committer<Self, $int_type, SeqCst, SeqCst>),
206 {
207 self.0.fetch_add(val, OrderingTy::SeqCst)
208 }
209 }
210
211 )* };
212}
213
214impl_atomic! {
215 (bool, AtomicBool),
216 (*mut T, AtomicPtr<T>)
217}
218
219impl_atomic_int! {
220 (i8, AtomicI8),
221 (u8, AtomicU8),
222 (i16, AtomicI16),
223 (u16, AtomicU16),
224 (i32, AtomicI32),
225 (u32, AtomicU32),
226 (i64, AtomicI64),
227 (u64, AtomicU64),
228 (isize, AtomicIsize),
229 (usize, AtomicUsize)
230}