Skip to content

Commit a80821e

Browse files
committed
also combine re-locking into the dequeue-and-unblock operation
1 parent 7589bc7 commit a80821e

File tree

2 files changed

+23
-22
lines changed

2 files changed

+23
-22
lines changed

src/shims/sync.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -606,9 +606,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
606606
if this.rwlock_is_locked(id) {
607607
// No more readers owning the lock. Give it to a writer if there
608608
// is any.
609-
if let Some(writer) = this.rwlock_dequeue_and_unblock_writer(id) {
610-
this.rwlock_writer_lock(id, writer);
611-
}
609+
this.rwlock_dequeue_and_lock_writer(id);
612610
}
613611
Ok(0)
614612
} else if Some(active_thread) == this.rwlock_writer_unlock(id) {
@@ -617,13 +615,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
617615
// We are prioritizing writers here against the readers. As a
618616
// result, not only readers can starve writers, but also writers can
619617
// starve readers.
620-
if let Some(writer) = this.rwlock_dequeue_and_unblock_writer(id) {
621-
// Give the lock to another writer.
622-
this.rwlock_writer_lock(id, writer);
618+
if this.rwlock_dequeue_and_lock_writer(id) {
619+
// Someone got the write lock, nice.
623620
} else {
624621
// Give the lock to all readers.
625-
while let Some(reader) = this.rwlock_dequeue_and_unblock_reader(id) {
626-
this.rwlock_reader_lock(id, reader);
622+
while this.rwlock_dequeue_and_lock_reader(id) {
623+
// Rinse and repeat.
627624
}
628625
}
629626
Ok(0)

src/sync.rs

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -170,9 +170,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
170170
mutex.owner = None;
171171
// The mutex is completely unlocked. Try transfering ownership
172172
// to another thread.
173-
if let Some(new_owner) = this.mutex_dequeue_and_unblock(id) {
174-
this.mutex_lock(id, new_owner);
175-
}
173+
this.mutex_dequeue_and_lock(id);
176174
}
177175
Ok(Some(old_lock_count))
178176
} else {
@@ -182,7 +180,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
182180
}
183181

184182
#[inline]
185-
/// Put the thread into the queue waiting for the lock.
183+
/// Put the thread into the queue waiting for the mutex.
186184
fn mutex_enqueue_and_block(&mut self, id: MutexId, thread: ThreadId) {
187185
let this = self.eval_context_mut();
188186
assert!(this.mutex_is_locked(id), "queing on unlocked mutex");
@@ -191,14 +189,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
191189
}
192190

193191
#[inline]
194-
/// Take a thread out of the queue waiting for the lock.
195-
fn mutex_dequeue_and_unblock(&mut self, id: MutexId) -> Option<ThreadId> {
192+
/// Take a thread out of the queue waiting for the mutex, and lock
193+
/// the mutex for it. Returns `true` if some thread has the mutex now.
194+
fn mutex_dequeue_and_lock(&mut self, id: MutexId) -> bool {
196195
let this = self.eval_context_mut();
197196
if let Some(thread) = this.machine.threads.sync.mutexes[id].queue.pop_front() {
198197
this.unblock_thread(thread);
199-
Some(thread)
198+
this.mutex_lock(id, thread);
199+
true
200200
} else {
201-
None
201+
false
202202
}
203203
}
204204

@@ -266,13 +266,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
266266

267267
#[inline]
268268
/// Take a reader out the queue waiting for the lock.
269-
fn rwlock_dequeue_and_unblock_reader(&mut self, id: RwLockId) -> Option<ThreadId> {
269+
/// Returns `true` if some thread got the rwlock.
270+
fn rwlock_dequeue_and_lock_reader(&mut self, id: RwLockId) -> bool {
270271
let this = self.eval_context_mut();
271272
if let Some(reader) = this.machine.threads.sync.rwlocks[id].reader_queue.pop_front() {
272273
this.unblock_thread(reader);
273-
Some(reader)
274+
this.rwlock_reader_lock(id, reader);
275+
true
274276
} else {
275-
None
277+
false
276278
}
277279
}
278280

@@ -306,13 +308,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
306308

307309
#[inline]
308310
/// Take the writer out the queue waiting for the lock.
309-
fn rwlock_dequeue_and_unblock_writer(&mut self, id: RwLockId) -> Option<ThreadId> {
311+
/// Returns `true` if some thread got the rwlock.
312+
fn rwlock_dequeue_and_lock_writer(&mut self, id: RwLockId) -> bool {
310313
let this = self.eval_context_mut();
311314
if let Some(writer) = this.machine.threads.sync.rwlocks[id].writer_queue.pop_front() {
312315
this.unblock_thread(writer);
313-
Some(writer)
316+
this.rwlock_writer_lock(id, writer);
317+
true
314318
} else {
315-
None
319+
false
316320
}
317321
}
318322

0 commit comments

Comments
 (0)