@@ -91,7 +91,7 @@ fn mutex_get_id<'mir, 'tcx: 'mir>(
91
91
ecx : & MiriEvalContext < ' mir , ' tcx > ,
92
92
mutex_op : & OpTy < ' tcx , Tag > ,
93
93
) -> 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 )
95
95
}
96
96
97
97
fn mutex_set_id < ' mir , ' tcx : ' mir > (
@@ -104,23 +104,31 @@ fn mutex_set_id<'mir, 'tcx: 'mir>(
104
104
4 ,
105
105
id,
106
106
layout_of_maybe_uninit ( ecx. tcx , ecx. tcx . types . u32 ) ,
107
- AtomicWriteOp :: Relaxed ,
107
+ AtomicWriteOp :: Release ,
108
108
)
109
109
}
110
110
111
111
fn mutex_get_or_create_id < ' mir , ' tcx : ' mir > (
112
112
ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
113
113
mutex_op : & OpTy < ' tcx , Tag > ,
114
114
) -> 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" ) {
119
128
let id = ecx. mutex_create ( ) ;
120
- mutex_set_id ( ecx, mutex_op, id. to_u32_scalar ( ) ) ?;
121
129
Ok ( id)
122
130
} else {
123
- Ok ( MutexId :: from_u32 ( id ) )
131
+ Ok ( MutexId :: from_u32 ( old . to_u32 ( ) . expect ( "layout is u32" ) ) )
124
132
}
125
133
}
126
134
@@ -135,7 +143,7 @@ fn rwlock_get_id<'mir, 'tcx: 'mir>(
135
143
ecx : & MiriEvalContext < ' mir , ' tcx > ,
136
144
rwlock_op : & OpTy < ' tcx , Tag > ,
137
145
) -> 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 )
139
147
}
140
148
141
149
fn rwlock_set_id < ' mir , ' tcx : ' mir > (
@@ -148,23 +156,31 @@ fn rwlock_set_id<'mir, 'tcx: 'mir>(
148
156
4 ,
149
157
id,
150
158
layout_of_maybe_uninit ( ecx. tcx , ecx. tcx . types . u32 ) ,
151
- AtomicWriteOp :: Relaxed ,
159
+ AtomicWriteOp :: Release ,
152
160
)
153
161
}
154
162
155
163
fn rwlock_get_or_create_id < ' mir , ' tcx : ' mir > (
156
164
ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
157
165
rwlock_op : & OpTy < ' tcx , Tag > ,
158
166
) -> 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" ) {
163
180
let id = ecx. rwlock_create ( ) ;
164
- rwlock_set_id ( ecx, rwlock_op, id. to_u32_scalar ( ) ) ?;
165
181
Ok ( id)
166
182
} else {
167
- Ok ( RwLockId :: from_u32 ( id ) )
183
+ Ok ( RwLockId :: from_u32 ( old . to_u32 ( ) . expect ( "layout is u32" ) ) )
168
184
}
169
185
}
170
186
@@ -207,7 +223,7 @@ fn cond_get_id<'mir, 'tcx: 'mir>(
207
223
ecx : & MiriEvalContext < ' mir , ' tcx > ,
208
224
cond_op : & OpTy < ' tcx , Tag > ,
209
225
) -> 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 )
211
227
}
212
228
213
229
fn cond_set_id < ' mir , ' tcx : ' mir > (
@@ -220,23 +236,32 @@ fn cond_set_id<'mir, 'tcx: 'mir>(
220
236
4 ,
221
237
id,
222
238
layout_of_maybe_uninit ( ecx. tcx , ecx. tcx . types . u32 ) ,
223
- AtomicWriteOp :: Relaxed ,
239
+ AtomicWriteOp :: Release ,
224
240
)
225
241
}
226
242
227
243
fn cond_get_or_create_id < ' mir , ' tcx : ' mir > (
228
244
ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
229
245
cond_op : & OpTy < ' tcx , Tag > ,
230
246
) -> 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" ) {
235
261
let id = ecx. condvar_create ( ) ;
236
- cond_set_id ( ecx, cond_op, id. to_u32_scalar ( ) ) ?;
237
262
Ok ( id)
238
263
} else {
239
- Ok ( CondvarId :: from_u32 ( id ) )
264
+ Ok ( CondvarId :: from_u32 ( old . to_u32 ( ) . expect ( "layout is u32" ) ) )
240
265
}
241
266
}
242
267
0 commit comments