Skip to content

Commit 9135232

Browse files
committed
use enum for condvar locks
1 parent 1fc1d65 commit 9135232

File tree

3 files changed

+42
-22
lines changed

3 files changed

+42
-22
lines changed

src/concurrency/sync.rs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -116,15 +116,19 @@ struct RwLock {
116116

117117
declare_id!(CondvarId);
118118

119+
#[derive(Debug)]
120+
pub enum CondvarLock {
121+
Mutex(MutexId),
122+
RwLock { id: RwLockId, shared: bool },
123+
}
124+
119125
/// A thread waiting on a conditional variable.
120126
#[derive(Debug)]
121127
struct CondvarWaiter {
122128
/// The thread that is waiting on this variable.
123129
thread: ThreadId,
124130
/// The mutex or rwlock on which the thread is waiting.
125-
lock: u32,
126-
/// If the lock is shared or exclusive
127-
shared: bool,
131+
lock: CondvarLock,
128132
}
129133

130134
/// The conditional variable state.
@@ -571,16 +575,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
571575
}
572576

573577
/// Mark that the thread is waiting on the conditional variable.
574-
fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, lock: u32, shared: bool) {
578+
fn condvar_wait(&mut self, id: CondvarId, thread: ThreadId, lock: CondvarLock) {
575579
let this = self.eval_context_mut();
576580
let waiters = &mut this.machine.threads.sync.condvars[id].waiters;
577581
assert!(waiters.iter().all(|waiter| waiter.thread != thread), "thread is already waiting");
578-
waiters.push_back(CondvarWaiter { thread, lock, shared });
582+
waiters.push_back(CondvarWaiter { thread, lock });
579583
}
580584

581585
/// Wake up some thread (if there is any) sleeping on the conditional
582586
/// variable.
583-
fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, u32, bool)> {
587+
fn condvar_signal(&mut self, id: CondvarId) -> Option<(ThreadId, CondvarLock)> {
584588
let this = self.eval_context_mut();
585589
let current_thread = this.get_active_thread();
586590
let condvar = &mut this.machine.threads.sync.condvars[id];
@@ -594,7 +598,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
594598
if let Some(data_race) = data_race {
595599
data_race.validate_lock_acquire(&condvar.data_race, waiter.thread);
596600
}
597-
(waiter.thread, waiter.lock, waiter.shared)
601+
(waiter.thread, waiter.lock)
598602
})
599603
}
600604

src/shims/unix/sync.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::time::SystemTime;
33
use rustc_hir::LangItem;
44
use rustc_middle::ty::{layout::TyAndLayout, query::TyCtxtAt, Ty};
55

6+
use crate::concurrency::sync::CondvarLock;
67
use crate::concurrency::thread::{MachineCallback, Time};
78
use crate::*;
89

@@ -696,9 +697,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
696697
fn pthread_cond_signal(&mut self, cond_op: &OpTy<'tcx, Provenance>) -> InterpResult<'tcx, i32> {
697698
let this = self.eval_context_mut();
698699
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
699-
if let Some((thread, mutex, shared)) = this.condvar_signal(id) {
700-
assert!(!shared);
701-
post_cond_signal(this, thread, MutexId::from_u32(mutex))?;
700+
if let Some((thread, lock)) = this.condvar_signal(id) {
701+
if let CondvarLock::Mutex(mutex) = lock {
702+
post_cond_signal(this, thread, mutex)?;
703+
} else {
704+
panic!("condvar should not have an rwlock on unix");
705+
}
702706
}
703707

704708
Ok(0)
@@ -711,9 +715,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
711715
let this = self.eval_context_mut();
712716
let id = this.condvar_get_or_create_id(cond_op, CONDVAR_ID_OFFSET)?;
713717

714-
while let Some((thread, mutex, shared)) = this.condvar_signal(id) {
715-
assert!(!shared);
716-
post_cond_signal(this, thread, MutexId::from_u32(mutex))?;
718+
while let Some((thread, lock)) = this.condvar_signal(id) {
719+
if let CondvarLock::Mutex(mutex) = lock {
720+
post_cond_signal(this, thread, mutex)?;
721+
} else {
722+
panic!("condvar should not have an rwlock on unix");
723+
}
717724
}
718725

719726
Ok(0)
@@ -731,7 +738,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
731738
let active_thread = this.get_active_thread();
732739

733740
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
734-
this.condvar_wait(id, active_thread, mutex_id.to_u32(), false);
741+
this.condvar_wait(id, active_thread, CondvarLock::Mutex(mutex_id));
735742

736743
Ok(0)
737744
}
@@ -770,7 +777,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
770777
};
771778

772779
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
773-
this.condvar_wait(id, active_thread, mutex_id.to_u32(), false);
780+
this.condvar_wait(id, active_thread, CondvarLock::Mutex(mutex_id));
774781

775782
// We return success for now and override it in the timeout callback.
776783
this.write_scalar(Scalar::from_i32(0), dest)?;

src/shims/windows/sync.rs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::time::Duration;
33
use rustc_target::abi::Size;
44

55
use crate::concurrency::init_once::InitOnceStatus;
6+
use crate::concurrency::sync::CondvarLock;
67
use crate::concurrency::thread::MachineCallback;
78
use crate::*;
89

@@ -403,7 +404,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
403404
}
404405

405406
this.block_thread(active_thread);
406-
this.condvar_wait(condvar_id, active_thread, lock_id.to_u32(), shared);
407+
this.condvar_wait(condvar_id, active_thread, CondvarLock::RwLock { id: lock_id, shared });
407408

408409
if let Some(timeout_time) = timeout_time {
409410
struct Callback<'tcx> {
@@ -454,9 +455,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
454455
let this = self.eval_context_mut();
455456
let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?;
456457

457-
if let Some((thread, lock, shared)) = this.condvar_signal(condvar_id) {
458-
this.reacquire_cond_lock(thread, RwLockId::from_u32(lock), shared)?;
459-
this.unregister_timeout_callback_if_exists(thread);
458+
if let Some((thread, lock)) = this.condvar_signal(condvar_id) {
459+
if let CondvarLock::RwLock { id, shared } = lock {
460+
this.reacquire_cond_lock(thread, id, shared)?;
461+
this.unregister_timeout_callback_if_exists(thread);
462+
} else {
463+
panic!("mutexes should not exist on windows");
464+
}
460465
}
461466

462467
Ok(())
@@ -469,9 +474,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
469474
let this = self.eval_context_mut();
470475
let condvar_id = this.condvar_get_or_create_id(condvar_op, CONDVAR_ID_OFFSET)?;
471476

472-
while let Some((thread, lock, shared)) = this.condvar_signal(condvar_id) {
473-
this.reacquire_cond_lock(thread, RwLockId::from_u32(lock), shared)?;
474-
this.unregister_timeout_callback_if_exists(thread);
477+
while let Some((thread, lock)) = this.condvar_signal(condvar_id) {
478+
if let CondvarLock::RwLock { id, shared } = lock {
479+
this.reacquire_cond_lock(thread, id, shared)?;
480+
this.unregister_timeout_callback_if_exists(thread);
481+
} else {
482+
panic!("mutexes should not exist on windows");
483+
}
475484
}
476485

477486
Ok(())

0 commit comments

Comments
 (0)