@@ -284,15 +284,16 @@ fn reacquire_cond_mutex<'mir, 'tcx: 'mir>(
284
284
thread : ThreadId ,
285
285
mutex : MutexId ,
286
286
) -> InterpResult < ' tcx > {
287
+ ecx. unblock_thread ( thread) ;
287
288
if ecx. mutex_is_locked ( mutex) {
288
- ecx. mutex_enqueue ( mutex, thread) ;
289
+ ecx. mutex_enqueue_and_block ( mutex, thread) ;
289
290
} else {
290
291
ecx. mutex_lock ( mutex, thread) ;
291
- ecx. unblock_thread ( thread) ?;
292
292
}
293
293
Ok ( ( ) )
294
294
}
295
295
296
+ /// After a thread waiting on a condvar was signalled:
296
297
/// Reacquire the conditional variable and remove the timeout callback if any
297
298
/// was registered.
298
299
fn post_cond_signal < ' mir , ' tcx : ' mir > (
@@ -303,12 +304,13 @@ fn post_cond_signal<'mir, 'tcx: 'mir>(
303
304
reacquire_cond_mutex ( ecx, thread, mutex) ?;
304
305
// Waiting for the mutex is not included in the waiting time because we need
305
306
// to acquire the mutex always even if we get a timeout.
306
- ecx. unregister_timeout_callback_if_exists ( thread)
307
+ ecx. unregister_timeout_callback_if_exists ( thread) ;
308
+ Ok ( ( ) )
307
309
}
308
310
309
311
/// Release the mutex associated with the condition variable because we are
310
312
/// entering the waiting state.
311
- fn release_cond_mutex < ' mir , ' tcx : ' mir > (
313
+ fn release_cond_mutex_and_block < ' mir , ' tcx : ' mir > (
312
314
ecx : & mut MiriEvalContext < ' mir , ' tcx > ,
313
315
active_thread : ThreadId ,
314
316
mutex : MutexId ,
@@ -320,7 +322,7 @@ fn release_cond_mutex<'mir, 'tcx: 'mir>(
320
322
} else {
321
323
throw_ub_format ! ( "awaiting on unlocked or owned by a different thread mutex" ) ;
322
324
}
323
- ecx. block_thread ( active_thread) ? ;
325
+ ecx. block_thread ( active_thread) ;
324
326
Ok ( ( ) )
325
327
}
326
328
@@ -411,14 +413,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
411
413
412
414
let kind = mutex_get_kind ( this, mutex_op) ?. not_undef ( ) ?;
413
415
let id = mutex_get_or_create_id ( this, mutex_op) ?;
414
- let active_thread = this. get_active_thread ( ) ? ;
416
+ let active_thread = this. get_active_thread ( ) ;
415
417
416
418
if this. mutex_is_locked ( id) {
417
419
let owner_thread = this. mutex_get_owner ( id) ;
418
420
if owner_thread != active_thread {
419
- // Block the active thread.
420
- this. block_thread ( active_thread) ?;
421
- this. mutex_enqueue ( id, active_thread) ;
421
+ // Enqueue the active thread.
422
+ this. mutex_enqueue_and_block ( id, active_thread) ;
422
423
Ok ( 0 )
423
424
} else {
424
425
// Trying to acquire the same mutex again.
@@ -449,7 +450,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
449
450
450
451
let kind = mutex_get_kind ( this, mutex_op) ?. not_undef ( ) ?;
451
452
let id = mutex_get_or_create_id ( this, mutex_op) ?;
452
- let active_thread = this. get_active_thread ( ) ? ;
453
+ let active_thread = this. get_active_thread ( ) ;
453
454
454
455
if this. mutex_is_locked ( id) {
455
456
let owner_thread = this. mutex_get_owner ( id) ;
@@ -482,7 +483,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
482
483
483
484
let kind = mutex_get_kind ( this, mutex_op) ?. not_undef ( ) ?;
484
485
let id = mutex_get_or_create_id ( this, mutex_op) ?;
485
- let active_thread = this. get_active_thread ( ) ? ;
486
+ let active_thread = this. get_active_thread ( ) ;
486
487
487
488
if let Some ( _old_locked_count) = this. mutex_unlock ( id, active_thread) ? {
488
489
// The mutex was locked by the current thread.
@@ -528,10 +529,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
528
529
let this = self . eval_context_mut ( ) ;
529
530
530
531
let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
531
- let active_thread = this. get_active_thread ( ) ? ;
532
+ let active_thread = this. get_active_thread ( ) ;
532
533
533
534
if this. rwlock_is_write_locked ( id) {
534
- this. rwlock_enqueue_and_block_reader ( id, active_thread) ? ;
535
+ this. rwlock_enqueue_and_block_reader ( id, active_thread) ;
535
536
Ok ( 0 )
536
537
} else {
537
538
this. rwlock_reader_lock ( id, active_thread) ;
@@ -543,7 +544,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
543
544
let this = self . eval_context_mut ( ) ;
544
545
545
546
let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
546
- let active_thread = this. get_active_thread ( ) ? ;
547
+ let active_thread = this. get_active_thread ( ) ;
547
548
548
549
if this. rwlock_is_write_locked ( id) {
549
550
this. eval_libc_i32 ( "EBUSY" )
@@ -557,22 +558,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
557
558
let this = self . eval_context_mut ( ) ;
558
559
559
560
let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
560
- let active_thread = this. get_active_thread ( ) ? ;
561
+ let active_thread = this. get_active_thread ( ) ;
561
562
562
563
if this. rwlock_is_locked ( id) {
563
564
// Note: this will deadlock if the lock is already locked by this
564
565
// thread in any way.
565
566
//
566
567
// Relevant documentation:
567
568
// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_rwlock_wrlock.html
568
- // An in depth discussion on this topic:
569
+ // An in- depth discussion on this topic:
569
570
// https://github.com/rust-lang/rust/issues/53127
570
571
//
571
572
// FIXME: Detect and report the deadlock proactively. (We currently
572
573
// report the deadlock only when no thread can continue execution,
573
574
// but we could detect that this lock is already locked and report
574
575
// an error.)
575
- this. rwlock_enqueue_and_block_writer ( id, active_thread) ? ;
576
+ this. rwlock_enqueue_and_block_writer ( id, active_thread) ;
576
577
} else {
577
578
this. rwlock_writer_lock ( id, active_thread) ;
578
579
}
@@ -584,7 +585,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
584
585
let this = self . eval_context_mut ( ) ;
585
586
586
587
let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
587
- let active_thread = this. get_active_thread ( ) ? ;
588
+ let active_thread = this. get_active_thread ( ) ;
588
589
589
590
if this. rwlock_is_locked ( id) {
590
591
this. eval_libc_i32 ( "EBUSY" )
@@ -598,15 +599,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
598
599
let this = self . eval_context_mut ( ) ;
599
600
600
601
let id = rwlock_get_or_create_id ( this, rwlock_op) ?;
601
- let active_thread = this. get_active_thread ( ) ? ;
602
+ let active_thread = this. get_active_thread ( ) ;
602
603
603
604
if this. rwlock_reader_unlock ( id, active_thread) {
604
605
// The thread was a reader.
605
606
if this. rwlock_is_locked ( id) {
606
607
// No more readers owning the lock. Give it to a writer if there
607
608
// is any.
608
- if let Some ( writer) = this. rwlock_dequeue_writer ( id) {
609
- this. unblock_thread ( writer) ?;
609
+ if let Some ( writer) = this. rwlock_dequeue_and_unblock_writer ( id) {
610
610
this. rwlock_writer_lock ( id, writer) ;
611
611
}
612
612
}
@@ -617,14 +617,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
617
617
// We are prioritizing writers here against the readers. As a
618
618
// result, not only readers can starve writers, but also writers can
619
619
// starve readers.
620
- if let Some ( writer) = this. rwlock_dequeue_writer ( id) {
620
+ if let Some ( writer) = this. rwlock_dequeue_and_unblock_writer ( id) {
621
621
// Give the lock to another writer.
622
- this. unblock_thread ( writer) ?;
623
622
this. rwlock_writer_lock ( id, writer) ;
624
623
} else {
625
624
// Give the lock to all readers.
626
- while let Some ( reader) = this. rwlock_dequeue_reader ( id) {
627
- this. unblock_thread ( reader) ?;
625
+ while let Some ( reader) = this. rwlock_dequeue_and_unblock_reader ( id) {
628
626
this. rwlock_reader_lock ( id, reader) ;
629
627
}
630
628
}
@@ -753,9 +751,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
753
751
754
752
let id = cond_get_or_create_id ( this, cond_op) ?;
755
753
let mutex_id = mutex_get_or_create_id ( this, mutex_op) ?;
756
- let active_thread = this. get_active_thread ( ) ? ;
754
+ let active_thread = this. get_active_thread ( ) ;
757
755
758
- release_cond_mutex ( this, active_thread, mutex_id) ?;
756
+ release_cond_mutex_and_block ( this, active_thread, mutex_id) ?;
759
757
this. condvar_wait ( id, active_thread, mutex_id) ;
760
758
761
759
Ok ( 0 )
@@ -774,9 +772,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
774
772
775
773
let id = cond_get_or_create_id ( this, cond_op) ?;
776
774
let mutex_id = mutex_get_or_create_id ( this, mutex_op) ?;
777
- let active_thread = this. get_active_thread ( ) ? ;
775
+ let active_thread = this. get_active_thread ( ) ;
778
776
779
- release_cond_mutex ( this, active_thread, mutex_id) ?;
777
+ release_cond_mutex_and_block ( this, active_thread, mutex_id) ?;
780
778
this. condvar_wait ( id, active_thread, mutex_id) ;
781
779
782
780
// We return success for now and override it in the timeout callback.
@@ -823,7 +821,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
823
821
824
822
Ok ( ( ) )
825
823
} ) ,
826
- ) ? ;
824
+ ) ;
827
825
828
826
Ok ( ( ) )
829
827
}
@@ -833,7 +831,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
833
831
834
832
let id = cond_get_or_create_id ( this, cond_op) ?;
835
833
if this. condvar_is_awaited ( id) {
836
- throw_ub_format ! ( "destroyed an awaited conditional variable" ) ;
834
+ throw_ub_format ! ( "destroying an awaited conditional variable" ) ;
837
835
}
838
836
cond_set_id ( this, cond_op, ScalarMaybeUninit :: Uninit ) ?;
839
837
cond_set_clock_id ( this, cond_op, ScalarMaybeUninit :: Uninit ) ?;
0 commit comments