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