@@ -202,6 +202,7 @@ fn condattr_set_clock_id<'mir, 'tcx: 'mir>(
202
202
// Our chosen memory layout for the emulated conditional variable (does not have
203
203
// to match the platform layout!):
204
204
205
+ // bytes 0-3: reserved for signature on macOS
205
206
// bytes 4-7: the conditional variable id as u32 or 0 if id is not assigned yet.
206
207
// bytes 8-11: the clock id constant as i32
207
208
@@ -275,19 +276,13 @@ fn release_cond_mutex<'mir, 'tcx: 'mir>(
275
276
active_thread : ThreadId ,
276
277
mutex : MutexId ,
277
278
) -> InterpResult < ' tcx > {
278
- if let Some ( ( owner_thread , current_locked_count ) ) = ecx. mutex_unlock ( mutex) {
279
- if current_locked_count != 0 {
280
- throw_unsup_format ! ( "awaiting on multiple times acquired lock is not supported" ) ;
279
+ if let Some ( ( old_owner_thread , old_locked_count ) ) = ecx. mutex_unlock ( mutex) ? {
280
+ if old_locked_count != 1 {
281
+ throw_unsup_format ! ( "awaiting on a lock acquired multiple times is not supported" ) ;
281
282
}
282
- if owner_thread != active_thread {
283
+ if old_owner_thread != active_thread {
283
284
throw_ub_format ! ( "awaiting on a mutex owned by a different thread" ) ;
284
285
}
285
- if let Some ( thread) = ecx. mutex_dequeue ( mutex) {
286
- // We have at least one thread waiting on this mutex. Transfer
287
- // ownership to it.
288
- ecx. mutex_lock ( mutex, thread) ;
289
- ecx. unblock_thread ( thread) ?;
290
- }
291
286
} else {
292
287
throw_ub_format ! ( "awaiting on unlocked mutex" ) ;
293
288
}
@@ -349,7 +344,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
349
344
mutexattr_get_kind ( this, attr_op) ?. not_undef ( ) ?
350
345
} ;
351
346
352
- let _ = mutex_get_or_create_id ( this, mutex_op) ?;
347
+ // Write 0 to use the same code path as the static initializers.
348
+ mutex_set_id ( this, mutex_op, Scalar :: from_i32 ( 0 ) ) ?;
349
+
353
350
mutex_set_kind ( this, mutex_op, kind) ?;
354
351
355
352
Ok ( 0 )
@@ -427,19 +424,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
427
424
let kind = mutex_get_kind ( this, mutex_op) ?. not_undef ( ) ?;
428
425
let id = mutex_get_or_create_id ( this, mutex_op) ?;
429
426
430
- if let Some ( ( owner_thread , current_locked_count ) ) = this. mutex_unlock ( id) {
431
- if owner_thread != this. get_active_thread ( ) ? {
427
+ if let Some ( ( old_owner_thread , _old_locked_count ) ) = this. mutex_unlock ( id) ? {
428
+ if old_owner_thread != this. get_active_thread ( ) ? {
432
429
throw_ub_format ! ( "called pthread_mutex_unlock on a mutex owned by another thread" ) ;
433
430
}
434
- if current_locked_count == 0 {
435
- // The mutex is unlocked.
436
- if let Some ( thread) = this. mutex_dequeue ( id) {
437
- // We have at least one thread waiting on this mutex. Transfer
438
- // ownership to it.
439
- this. mutex_lock ( id, thread) ;
440
- this. unblock_thread ( thread) ?;
441
- }
442
- }
443
431
Ok ( 0 )
444
432
} else {
445
433
if kind == this. eval_libc ( "PTHREAD_MUTEX_NORMAL" ) ? {
@@ -476,11 +464,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
476
464
let active_thread = this. get_active_thread ( ) ?;
477
465
478
466
if this. rwlock_is_write_locked ( id) {
479
- this. rwlock_enqueue_reader ( id, active_thread) ;
480
- this. block_thread ( active_thread) ?;
467
+ this. rwlock_enqueue_and_block_reader ( id, active_thread) ?;
481
468
Ok ( 0 )
482
469
} else {
483
- this. rwlock_reader_add ( id, active_thread) ;
470
+ this. rwlock_reader_lock ( id, active_thread) ;
484
471
Ok ( 0 )
485
472
}
486
473
}
@@ -494,7 +481,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
494
481
if this. rwlock_is_write_locked ( id) {
495
482
this. eval_libc_i32 ( "EBUSY" )
496
483
} else {
497
- this. rwlock_reader_add ( id, active_thread) ;
484
+ this. rwlock_reader_lock ( id, active_thread) ;
498
485
Ok ( 0 )
499
486
}
500
487
}
@@ -506,10 +493,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
506
493
let active_thread = this. get_active_thread ( ) ?;
507
494
508
495
if this. rwlock_is_locked ( id) {
509
- this. block_thread ( active_thread) ?;
510
- this. rwlock_enqueue_writer ( id, active_thread) ;
496
+ this. rwlock_enqueue_and_block_writer ( id, active_thread) ?;
511
497
} else {
512
- this. rwlock_writer_set ( id, active_thread) ;
498
+ this. rwlock_writer_lock ( id, active_thread) ;
513
499
}
514
500
515
501
Ok ( 0 )
@@ -524,7 +510,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
524
510
if this. rwlock_is_locked ( id) {
525
511
this. eval_libc_i32 ( "EBUSY" )
526
512
} else {
527
- this. rwlock_writer_set ( id, active_thread) ;
513
+ this. rwlock_writer_lock ( id, active_thread) ;
528
514
Ok ( 0 )
529
515
}
530
516
}
@@ -535,18 +521,18 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
535
521
let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
536
522
let active_thread = this. get_active_thread ( ) ?;
537
523
538
- if this. rwlock_reader_remove ( id, active_thread) {
524
+ if this. rwlock_reader_unlock ( id, active_thread) {
539
525
// The thread was a reader.
540
526
if this. rwlock_is_locked ( id) {
541
527
// No more readers owning the lock. Give it to a writer if there
542
528
// is any.
543
529
if let Some ( writer) = this. rwlock_dequeue_writer ( id) {
544
530
this. unblock_thread ( writer) ?;
545
- this. rwlock_writer_set ( id, writer) ;
531
+ this. rwlock_writer_lock ( id, writer) ;
546
532
}
547
533
}
548
534
Ok ( 0 )
549
- } else if Some ( active_thread) == this. rwlock_writer_remove ( id) {
535
+ } else if Some ( active_thread) == this. rwlock_writer_unlock ( id) {
550
536
// The thread was a writer.
551
537
//
552
538
// We are prioritizing writers here against the readers. As a
@@ -555,12 +541,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
555
541
if let Some ( writer) = this. rwlock_dequeue_writer ( id) {
556
542
// Give the lock to another writer.
557
543
this. unblock_thread ( writer) ?;
558
- this. rwlock_writer_set ( id, writer) ;
544
+ this. rwlock_writer_lock ( id, writer) ;
559
545
} else {
560
546
// Give the lock to all readers.
561
547
while let Some ( reader) = this. rwlock_dequeue_reader ( id) {
562
548
this. unblock_thread ( reader) ?;
563
- this. rwlock_reader_add ( id, reader) ;
549
+ this. rwlock_reader_lock ( id, reader) ;
564
550
}
565
551
}
566
552
Ok ( 0 )
@@ -586,6 +572,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
586
572
fn pthread_condattr_init ( & mut self , attr_op : OpTy < ' tcx , Tag > ) -> InterpResult < ' tcx , i32 > {
587
573
let this = self . eval_context_mut ( ) ;
588
574
575
+ // The default value of the clock attribute shall refer to the system
576
+ // clock.
577
+ // https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_condattr_setclock.html
589
578
let default_clock_id = this. eval_libc ( "CLOCK_REALTIME" ) ?;
590
579
condattr_set_clock_id ( this, attr_op, default_clock_id) ?;
591
580
@@ -647,7 +636,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
647
636
condattr_get_clock_id ( this, attr_op) ?. not_undef ( ) ?
648
637
} ;
649
638
650
- let _ = cond_get_or_create_id ( this, cond_op) ?;
639
+ // Write 0 to use the same code path as the static initializers.
640
+ cond_set_id ( this, cond_op, Scalar :: from_i32 ( 0 ) ) ?;
641
+
651
642
cond_set_clock_id ( this, cond_op, clock_id) ?;
652
643
653
644
Ok ( 0 )
0 commit comments