Skip to content

Commit d9c2a9b

Browse files
committed
Revise mutex/rwlock memory layout for macOS compat
1 parent 011541a commit d9c2a9b

File tree

1 file changed

+28
-26
lines changed

1 file changed

+28
-26
lines changed

src/shims/sync.rs

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
7979

8080
// pthread_mutex_t is between 24 and 48 bytes, depending on the platform
8181
// memory layout:
82-
// bytes 0-3: count of how many times this mutex has been locked, as a u32
82+
// bytes 0-3: reserved for signature on macOS
83+
// bytes 4-7: count of how many times this mutex has been locked, as a u32
8384
// bytes 12-15: mutex kind, as an i32
8485
// (the kind should be at this offset for compatibility with the static
8586
// initializer macro)
@@ -112,7 +113,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
112113
};
113114

114115
let u32_layout = this.layout_of(this.tcx.types.u32)?;
115-
let locked_count_place = mutex_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
116+
let locked_count_place = mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
116117
this.write_scalar(Scalar::from_u32(0), locked_count_place.into())?;
117118

118119
let mutex_kind_place = mutex_place.offset(Size::from_bytes(12), MemPlaceMeta::None, i32_layout, &*this.tcx)?;
@@ -137,7 +138,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
137138
let kind = this.read_scalar(kind_place.into())?.not_undef()?;
138139

139140
let u32_layout = this.layout_of(this.tcx.types.u32)?;
140-
let locked_count_place = mutex_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
141+
let locked_count_place = mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
141142
let locked_count = this.read_scalar(locked_count_place.into())?.to_u32()?;
142143

143144
if kind == this.eval_libc("PTHREAD_MUTEX_NORMAL")? {
@@ -178,7 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
178179
let kind = this.read_scalar(kind_place.into())?.not_undef()?;
179180

180181
let u32_layout = this.layout_of(this.tcx.types.u32)?;
181-
let locked_count_place = mutex_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
182+
let locked_count_place = mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
182183
let locked_count = this.read_scalar(locked_count_place.into())?.to_u32()?;
183184

184185
if kind == this.eval_libc("PTHREAD_MUTEX_NORMAL")? ||
@@ -213,7 +214,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
213214
let kind = this.read_scalar(kind_place.into())?.not_undef()?;
214215

215216
let u32_layout = this.layout_of(this.tcx.types.u32)?;
216-
let locked_count_place = mutex_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
217+
let locked_count_place = mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
217218
let locked_count = this.read_scalar(locked_count_place.into())?.to_u32()?;
218219

219220
if kind == this.eval_libc("PTHREAD_MUTEX_NORMAL")? {
@@ -254,7 +255,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
254255
let mutex_place = this.deref_operand(mutex_op)?;
255256

256257
let u32_layout = this.layout_of(this.tcx.types.u32)?;
257-
let locked_count_place = mutex_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
258+
let locked_count_place = mutex_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
258259
if this.read_scalar(locked_count_place.into())?.to_u32()? != 0 {
259260
return this.eval_libc_i32("EBUSY");
260261
}
@@ -269,13 +270,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
269270

270271
// pthread_rwlock_t is between 32 and 56 bytes, depending on the platform
271272
// memory layout:
272-
// bytes 0-3: reader count, as a u32
273-
// bytes 4-7: writer count, as a u32
273+
// bytes 0-3: reserved for signature on macOS
274+
// bytes 4-7: reader count, as a u32
275+
// bytes 8-11: writer count, as a u32
274276

275277
fn pthread_rwlock_rdlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
276278
let this = self.eval_context_mut();
277279

278-
check_ptr_target_min_size(this, rwlock_op, 8)?;
280+
check_ptr_target_min_size(this, rwlock_op, 12)?;
279281

280282
let rwlock = this.read_scalar(rwlock_op)?.not_undef()?;
281283
if this.is_null(rwlock)? {
@@ -284,8 +286,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
284286
let rwlock_place = this.deref_operand(rwlock_op)?;
285287

286288
let u32_layout = this.layout_of(this.tcx.types.u32)?;
287-
let readers_place = rwlock_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
288-
let writers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
289+
let readers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
290+
let writers_place = rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, this)?;
289291
let readers = this.read_scalar(readers_place.into())?.to_u32()?;
290292
let writers = this.read_scalar(writers_place.into())?.to_u32()?;
291293
if writers != 0 {
@@ -299,7 +301,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
299301
fn pthread_rwlock_tryrdlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
300302
let this = self.eval_context_mut();
301303

302-
check_ptr_target_min_size(this, rwlock_op, 8)?;
304+
check_ptr_target_min_size(this, rwlock_op, 12)?;
303305

304306
let rwlock = this.read_scalar(rwlock_op)?.not_undef()?;
305307
if this.is_null(rwlock)? {
@@ -308,8 +310,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
308310
let rwlock_place = this.deref_operand(rwlock_op)?;
309311

310312
let u32_layout = this.layout_of(this.tcx.types.u32)?;
311-
let readers_place = rwlock_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
312-
let writers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
313+
let readers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
314+
let writers_place = rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, this)?;
313315
let readers = this.read_scalar(readers_place.into())?.to_u32()?;
314316
let writers = this.read_scalar(writers_place.into())?.to_u32()?;
315317
if writers != 0 {
@@ -323,7 +325,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
323325
fn pthread_rwlock_wrlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
324326
let this = self.eval_context_mut();
325327

326-
check_ptr_target_min_size(this, rwlock_op, 8)?;
328+
check_ptr_target_min_size(this, rwlock_op, 12)?;
327329

328330
let rwlock = this.read_scalar(rwlock_op)?.not_undef()?;
329331
if this.is_null(rwlock)? {
@@ -332,8 +334,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
332334
let rwlock_place = this.deref_operand(rwlock_op)?;
333335

334336
let u32_layout = this.layout_of(this.tcx.types.u32)?;
335-
let readers_place = rwlock_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
336-
let writers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
337+
let readers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
338+
let writers_place = rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, this)?;
337339
let readers = this.read_scalar(readers_place.into())?.to_u32()?;
338340
let writers = this.read_scalar(writers_place.into())?.to_u32()?;
339341
if readers != 0 {
@@ -349,7 +351,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
349351
fn pthread_rwlock_trywrlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
350352
let this = self.eval_context_mut();
351353

352-
check_ptr_target_min_size(this, rwlock_op, 8)?;
354+
check_ptr_target_min_size(this, rwlock_op, 12)?;
353355

354356
let rwlock = this.read_scalar(rwlock_op)?.not_undef()?;
355357
if this.is_null(rwlock)? {
@@ -358,8 +360,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
358360
let rwlock_place = this.deref_operand(rwlock_op)?;
359361

360362
let u32_layout = this.layout_of(this.tcx.types.u32)?;
361-
let readers_place = rwlock_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
362-
let writers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
363+
let readers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
364+
let writers_place = rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, this)?;
363365
let readers = this.read_scalar(readers_place.into())?.to_u32()?;
364366
let writers = this.read_scalar(writers_place.into())?.to_u32()?;
365367
if readers != 0 || writers != 0 {
@@ -373,7 +375,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
373375
fn pthread_rwlock_unlock(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
374376
let this = self.eval_context_mut();
375377

376-
check_ptr_target_min_size(this, rwlock_op, 8)?;
378+
check_ptr_target_min_size(this, rwlock_op, 12)?;
377379

378380
let rwlock = this.read_scalar(rwlock_op)?.not_undef()?;
379381
if this.is_null(rwlock)? {
@@ -382,8 +384,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
382384
let rwlock_place = this.deref_operand(rwlock_op)?;
383385

384386
let u32_layout = this.layout_of(this.tcx.types.u32)?;
385-
let readers_place = rwlock_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
386-
let writers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
387+
let readers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
388+
let writers_place = rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, this)?;
387389
let readers = this.read_scalar(readers_place.into())?.to_u32()?;
388390
let writers = this.read_scalar(writers_place.into())?.to_u32()?;
389391
if readers != 0 {
@@ -400,7 +402,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
400402
fn pthread_rwlock_destroy(&mut self, rwlock_op: OpTy<'tcx, Tag>) -> InterpResult<'tcx, i32> {
401403
let this = self.eval_context_mut();
402404

403-
check_ptr_target_min_size(this, rwlock_op, 8)?;
405+
check_ptr_target_min_size(this, rwlock_op, 12)?;
404406

405407
let rwlock = this.read_scalar(rwlock_op)?.not_undef()?;
406408
if this.is_null(rwlock)? {
@@ -409,11 +411,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
409411
let rwlock_place = this.deref_operand(rwlock_op)?;
410412

411413
let u32_layout = this.layout_of(this.tcx.types.u32)?;
412-
let readers_place = rwlock_place.offset(Size::ZERO, MemPlaceMeta::None, u32_layout, this)?;
414+
let readers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
413415
if this.read_scalar(readers_place.into())?.to_u32()? != 0 {
414416
return this.eval_libc_i32("EBUSY");
415417
}
416-
let writers_place = rwlock_place.offset(Size::from_bytes(4), MemPlaceMeta::None, u32_layout, this)?;
418+
let writers_place = rwlock_place.offset(Size::from_bytes(8), MemPlaceMeta::None, u32_layout, this)?;
417419
if this.read_scalar(writers_place.into())?.to_u32()? != 0 {
418420
return this.eval_libc_i32("EBUSY");
419421
}

0 commit comments

Comments
 (0)