@@ -40,13 +40,40 @@ use crate::{
40
40
41
41
pub type AllocExtra = StoreBufferAlloc ;
42
42
43
+ const STORE_BUFFER_LIMIT : usize = 128 ;
44
+
43
45
#[ derive( Debug , Clone ) ]
44
46
pub struct StoreBufferAlloc {
45
47
/// Store buffer of each atomic object in this allocation
46
48
// Behind a RefCell because we need to allocate/remove on read access
47
49
store_buffer : RefCell < AllocationMap < StoreBuffer > > ,
48
50
}
49
51
52
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
53
+ pub struct StoreBuffer {
54
+ // Stores to this location in modification order
55
+ buffer : VecDeque < StoreElement > ,
56
+ }
57
+
58
+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
59
+ pub struct StoreElement {
60
+ /// The identifier of the vector index, corresponding to a thread
61
+ /// that performed the store.
62
+ store_index : VectorIdx ,
63
+
64
+ /// Whether this store is SC.
65
+ is_seqcst : bool ,
66
+
67
+ /// The timestamp of the storing thread when it performed the store
68
+ timestamp : VTimestamp ,
69
+ /// The value of this store
70
+ val : ScalarMaybeUninit < Tag > ,
71
+
72
+ /// Timestamp of first loads from this store element by each thread
73
+ /// Behind a RefCell to keep load op take &self
74
+ loads : RefCell < FxHashMap < VectorIdx , VTimestamp > > ,
75
+ }
76
+
50
77
impl StoreBufferAlloc {
51
78
pub fn new_allocation ( ) -> Self {
52
79
Self { store_buffer : RefCell :: new ( AllocationMap :: new ( ) ) }
@@ -105,13 +132,6 @@ impl StoreBufferAlloc {
105
132
}
106
133
}
107
134
108
- const STORE_BUFFER_LIMIT : usize = 128 ;
109
- #[ derive( Debug , Clone , PartialEq , Eq ) ]
110
- pub struct StoreBuffer {
111
- // Stores to this location in modification order
112
- buffer : VecDeque < StoreElement > ,
113
- }
114
-
115
135
impl Default for StoreBuffer {
116
136
fn default ( ) -> Self {
117
137
let mut buffer = VecDeque :: new ( ) ;
@@ -175,7 +195,11 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
175
195
176
196
/// Selects a valid store element in the buffer.
177
197
/// The buffer does not contain the value used to initialise the atomic object
178
- /// so a fresh atomic object has an empty store buffer until an explicit store.
198
+ /// so a fresh atomic object has an empty store buffer and this function
199
+ /// will return `None`. In this case, the caller should ensure that the non-buffered
200
+ /// value from `MiriEvalContext::read_scalar()` is observed by the program, which is
201
+ /// the initial value of the atomic object. `MiriEvalContext::read_scalar()` is always
202
+ /// the latest value in modification order so it is always correct to be observed by any thread.
179
203
fn fetch_store < R : rand:: Rng + ?Sized > (
180
204
& self ,
181
205
is_seqcst : bool ,
@@ -294,25 +318,6 @@ impl<'mir, 'tcx: 'mir> StoreBuffer {
294
318
}
295
319
}
296
320
297
- #[ derive( Debug , Clone , PartialEq , Eq ) ]
298
- pub struct StoreElement {
299
- /// The identifier of the vector index, corresponding to a thread
300
- /// that performed the store.
301
- store_index : VectorIdx ,
302
-
303
- /// Whether this store is SC.
304
- is_seqcst : bool ,
305
-
306
- /// The timestamp of the storing thread when it performed the store
307
- timestamp : VTimestamp ,
308
- /// The value of this store
309
- val : ScalarMaybeUninit < Tag > ,
310
-
311
- /// Timestamp of first loads from this store element by each thread
312
- /// Behind a RefCell to keep load op take &self
313
- loads : RefCell < FxHashMap < VectorIdx , VTimestamp > > ,
314
- }
315
-
316
321
impl StoreElement {
317
322
/// ATOMIC LOAD IMPL in the paper
318
323
/// Unlike the operational semantics in the paper, we don't need to keep track
0 commit comments