@@ -91,7 +91,7 @@ fn mutex_get_id<'mir, 'tcx: 'mir>(
9191 ecx : & MiriEvalContext < ' mir , ' tcx > ,
9292 mutex_op : & OpTy < ' tcx , Tag > ,
9393) -> InterpResult < ' tcx , ScalarMaybeUninit < Tag > > {
94- ecx. read_scalar_at_offset_atomic ( mutex_op, 4 , ecx. machine . layouts . u32 , AtomicReadOp :: Relaxed )
94+ ecx. read_scalar_at_offset_atomic ( mutex_op, 4 , ecx. machine . layouts . u32 , AtomicReadOp :: Acquire )
9595}
9696
9797fn mutex_set_id < ' mir , ' tcx : ' mir > (
@@ -104,23 +104,31 @@ fn mutex_set_id<'mir, 'tcx: 'mir>(
104104 4 ,
105105 id,
106106 layout_of_maybe_uninit ( ecx. tcx , ecx. tcx . types . u32 ) ,
107- AtomicWriteOp :: Relaxed ,
107+ AtomicWriteOp :: Release ,
108108 )
109109}
110110
111111fn mutex_get_or_create_id < ' mir , ' tcx : ' mir > (
112112 ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
113113 mutex_op : & OpTy < ' tcx , Tag > ,
114114) -> InterpResult < ' tcx , MutexId > {
115- let id = mutex_get_id ( ecx, mutex_op) ?. to_u32 ( ) ?;
116- if id == 0 {
117- // 0 is a default value and also not a valid mutex id. Need to allocate
118- // a new mutex.
115+ let value_place = ecx. offset_and_layout_to_place ( mutex_op, 4 , ecx. machine . layouts . u32 ) ?;
116+ let ( old, success) = ecx
117+ . atomic_compare_exchange_scalar (
118+ & value_place,
119+ & ImmTy :: from_uint ( 0u32 , ecx. machine . layouts . u32 ) ,
120+ ecx. mutex_next_id ( ) . to_u32_scalar ( ) . into ( ) ,
121+ AtomicRwOp :: AcqRel ,
122+ AtomicReadOp :: Acquire ,
123+ false ,
124+ ) ?
125+ . to_scalar_pair ( ) ?;
126+
127+ if success. to_bool ( ) . expect ( "compare_exchange's second return value is a bool" ) {
119128 let id = ecx. mutex_create ( ) ;
120- mutex_set_id ( ecx, mutex_op, id. to_u32_scalar ( ) ) ?;
121129 Ok ( id)
122130 } else {
123- Ok ( MutexId :: from_u32 ( id ) )
131+ Ok ( MutexId :: from_u32 ( old . to_u32 ( ) . expect ( "layout is u32" ) ) )
124132 }
125133}
126134
@@ -135,7 +143,7 @@ fn rwlock_get_id<'mir, 'tcx: 'mir>(
135143 ecx : & MiriEvalContext < ' mir , ' tcx > ,
136144 rwlock_op : & OpTy < ' tcx , Tag > ,
137145) -> InterpResult < ' tcx , ScalarMaybeUninit < Tag > > {
138- ecx. read_scalar_at_offset_atomic ( rwlock_op, 4 , ecx. machine . layouts . u32 , AtomicReadOp :: Relaxed )
146+ ecx. read_scalar_at_offset_atomic ( rwlock_op, 4 , ecx. machine . layouts . u32 , AtomicReadOp :: Acquire )
139147}
140148
141149fn rwlock_set_id < ' mir , ' tcx : ' mir > (
@@ -148,23 +156,31 @@ fn rwlock_set_id<'mir, 'tcx: 'mir>(
148156 4 ,
149157 id,
150158 layout_of_maybe_uninit ( ecx. tcx , ecx. tcx . types . u32 ) ,
151- AtomicWriteOp :: Relaxed ,
159+ AtomicWriteOp :: Release ,
152160 )
153161}
154162
155163fn rwlock_get_or_create_id < ' mir , ' tcx : ' mir > (
156164 ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
157165 rwlock_op : & OpTy < ' tcx , Tag > ,
158166) -> InterpResult < ' tcx , RwLockId > {
159- let id = rwlock_get_id ( ecx, rwlock_op) ?. to_u32 ( ) ?;
160- if id == 0 {
161- // 0 is a default value and also not a valid rwlock id. Need to allocate
162- // a new read-write lock.
167+ let value_place = ecx. offset_and_layout_to_place ( rwlock_op, 4 , ecx. machine . layouts . u32 ) ?;
168+ let ( old, success) = ecx
169+ . atomic_compare_exchange_scalar (
170+ & value_place,
171+ & ImmTy :: from_uint ( 0u32 , ecx. machine . layouts . u32 ) ,
172+ ecx. rwlock_next_id ( ) . to_u32_scalar ( ) . into ( ) ,
173+ AtomicRwOp :: AcqRel ,
174+ AtomicReadOp :: Acquire ,
175+ false ,
176+ ) ?
177+ . to_scalar_pair ( ) ?;
178+
179+ if success. to_bool ( ) . expect ( "compare_exchange's second return value is a bool" ) {
163180 let id = ecx. rwlock_create ( ) ;
164- rwlock_set_id ( ecx, rwlock_op, id. to_u32_scalar ( ) ) ?;
165181 Ok ( id)
166182 } else {
167- Ok ( RwLockId :: from_u32 ( id ) )
183+ Ok ( RwLockId :: from_u32 ( old . to_u32 ( ) . expect ( "layout is u32" ) ) )
168184 }
169185}
170186
@@ -207,7 +223,7 @@ fn cond_get_id<'mir, 'tcx: 'mir>(
207223 ecx : & MiriEvalContext < ' mir , ' tcx > ,
208224 cond_op : & OpTy < ' tcx , Tag > ,
209225) -> InterpResult < ' tcx , ScalarMaybeUninit < Tag > > {
210- ecx. read_scalar_at_offset_atomic ( cond_op, 4 , ecx. machine . layouts . u32 , AtomicReadOp :: Relaxed )
226+ ecx. read_scalar_at_offset_atomic ( cond_op, 4 , ecx. machine . layouts . u32 , AtomicReadOp :: Acquire )
211227}
212228
213229fn cond_set_id < ' mir , ' tcx : ' mir > (
@@ -220,23 +236,32 @@ fn cond_set_id<'mir, 'tcx: 'mir>(
220236 4 ,
221237 id,
222238 layout_of_maybe_uninit ( ecx. tcx , ecx. tcx . types . u32 ) ,
223- AtomicWriteOp :: Relaxed ,
239+ AtomicWriteOp :: Release ,
224240 )
225241}
226242
227243fn cond_get_or_create_id < ' mir , ' tcx : ' mir > (
228244 ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
229245 cond_op : & OpTy < ' tcx , Tag > ,
230246) -> InterpResult < ' tcx , CondvarId > {
231- let id = cond_get_id ( ecx, cond_op) ?. to_u32 ( ) ?;
232- if id == 0 {
233- // 0 is a default value and also not a valid conditional variable id.
234- // Need to allocate a new id.
247+ let value_place = ecx. offset_and_layout_to_place ( cond_op, 4 , ecx. machine . layouts . u32 ) ?;
248+
249+ let ( old, success) = ecx
250+ . atomic_compare_exchange_scalar (
251+ & value_place,
252+ & ImmTy :: from_uint ( 0u32 , ecx. machine . layouts . u32 ) ,
253+ ecx. condvar_next_id ( ) . to_u32_scalar ( ) . into ( ) ,
254+ AtomicRwOp :: AcqRel ,
255+ AtomicReadOp :: Acquire ,
256+ false ,
257+ ) ?
258+ . to_scalar_pair ( ) ?;
259+
260+ if success. to_bool ( ) . expect ( "compare_exchange's second return value is a bool" ) {
235261 let id = ecx. condvar_create ( ) ;
236- cond_set_id ( ecx, cond_op, id. to_u32_scalar ( ) ) ?;
237262 Ok ( id)
238263 } else {
239- Ok ( CondvarId :: from_u32 ( id ) )
264+ Ok ( CondvarId :: from_u32 ( old . to_u32 ( ) . expect ( "layout is u32" ) ) )
240265 }
241266}
242267
0 commit comments