Skip to content

Commit 7589bc7

Browse files
committed
sync cleanup: mark infallible ops as such; consistent combine en/dequeue with (un)block; comments
1 parent 508371a commit 7589bc7

File tree

8 files changed

+110
-104
lines changed

8 files changed

+110
-104
lines changed

src/shims/foreign_items/posix.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -254,14 +254,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
254254
"pthread_getspecific" => {
255255
let &[key] = check_arg_count(args)?;
256256
let key = this.force_bits(this.read_scalar(key)?.not_undef()?, key.layout.size)?;
257-
let active_thread = this.get_active_thread()?;
257+
let active_thread = this.get_active_thread();
258258
let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
259259
this.write_scalar(ptr, dest)?;
260260
}
261261
"pthread_setspecific" => {
262262
let &[key, new_ptr] = check_arg_count(args)?;
263263
let key = this.force_bits(this.read_scalar(key)?.not_undef()?, key.layout.size)?;
264-
let active_thread = this.get_active_thread()?;
264+
let active_thread = this.get_active_thread();
265265
let new_ptr = this.read_scalar(new_ptr)?.not_undef()?;
266266
this.machine.tls.store_tls(key, active_thread, this.test_null(new_ptr)?)?;
267267

src/shims/foreign_items/posix/macos.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
9898
let dtor = this.read_scalar(dtor)?.not_undef()?;
9999
let dtor = this.memory.get_fn(dtor)?.as_instance()?;
100100
let data = this.read_scalar(data)?.not_undef()?;
101-
let active_thread = this.get_active_thread()?;
101+
let active_thread = this.get_active_thread();
102102
this.machine.tls.set_macos_thread_dtor(active_thread, dtor, data)?;
103103
}
104104

src/shims/foreign_items/windows.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,14 +163,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
163163
"TlsGetValue" => {
164164
let &[key] = check_arg_count(args)?;
165165
let key = u128::from(this.read_scalar(key)?.to_u32()?);
166-
let active_thread = this.get_active_thread()?;
166+
let active_thread = this.get_active_thread();
167167
let ptr = this.machine.tls.load_tls(key, active_thread, this)?;
168168
this.write_scalar(ptr, dest)?;
169169
}
170170
"TlsSetValue" => {
171171
let &[key, new_ptr] = check_arg_count(args)?;
172172
let key = u128::from(this.read_scalar(key)?.to_u32()?);
173-
let active_thread = this.get_active_thread()?;
173+
let active_thread = this.get_active_thread();
174174
let new_ptr = this.read_scalar(new_ptr)?.not_undef()?;
175175
this.machine.tls.store_tls(key, active_thread, this.test_null(new_ptr)?)?;
176176

@@ -291,7 +291,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
291291
if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
292292
#[allow(non_snake_case)]
293293
let &[_lpCriticalSection] = check_arg_count(args)?;
294-
assert_eq!(this.get_total_thread_count()?, 1, "concurrency on Windows not supported");
294+
assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows not supported");
295295
// Nothing to do, not even a return value.
296296
// (Windows locks are reentrant, and we have only 1 thread,
297297
// so not doing any futher checks here is at least not incorrect.)
@@ -300,7 +300,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
300300
if this.frame().instance.to_string().starts_with("std::sys::windows::") => {
301301
#[allow(non_snake_case)]
302302
let &[_lpCriticalSection] = check_arg_count(args)?;
303-
assert_eq!(this.get_total_thread_count()?, 1, "concurrency on Windows not supported");
303+
assert_eq!(this.get_total_thread_count(), 1, "concurrency on Windows not supported");
304304
// There is only one thread, so this always succeeds and returns TRUE
305305
this.write_scalar(Scalar::from_i32(1), dest)?;
306306
}

src/shims/sync.rs

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -284,15 +284,16 @@ fn reacquire_cond_mutex<'mir, 'tcx: 'mir>(
284284
thread: ThreadId,
285285
mutex: MutexId,
286286
) -> InterpResult<'tcx> {
287+
ecx.unblock_thread(thread);
287288
if ecx.mutex_is_locked(mutex) {
288-
ecx.mutex_enqueue(mutex, thread);
289+
ecx.mutex_enqueue_and_block(mutex, thread);
289290
} else {
290291
ecx.mutex_lock(mutex, thread);
291-
ecx.unblock_thread(thread)?;
292292
}
293293
Ok(())
294294
}
295295

296+
/// After a thread waiting on a condvar was signalled:
296297
/// Reacquire the conditional variable and remove the timeout callback if any
297298
/// was registered.
298299
fn post_cond_signal<'mir, 'tcx: 'mir>(
@@ -303,12 +304,13 @@ fn post_cond_signal<'mir, 'tcx: 'mir>(
303304
reacquire_cond_mutex(ecx, thread, mutex)?;
304305
// Waiting for the mutex is not included in the waiting time because we need
305306
// 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(())
307309
}
308310

309311
/// Release the mutex associated with the condition variable because we are
310312
/// entering the waiting state.
311-
fn release_cond_mutex<'mir, 'tcx: 'mir>(
313+
fn release_cond_mutex_and_block<'mir, 'tcx: 'mir>(
312314
ecx: &mut MiriEvalContext<'mir, 'tcx>,
313315
active_thread: ThreadId,
314316
mutex: MutexId,
@@ -320,7 +322,7 @@ fn release_cond_mutex<'mir, 'tcx: 'mir>(
320322
} else {
321323
throw_ub_format!("awaiting on unlocked or owned by a different thread mutex");
322324
}
323-
ecx.block_thread(active_thread)?;
325+
ecx.block_thread(active_thread);
324326
Ok(())
325327
}
326328

@@ -411,14 +413,13 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
411413

412414
let kind = mutex_get_kind(this, mutex_op)?.not_undef()?;
413415
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();
415417

416418
if this.mutex_is_locked(id) {
417419
let owner_thread = this.mutex_get_owner(id);
418420
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);
422423
Ok(0)
423424
} else {
424425
// Trying to acquire the same mutex again.
@@ -449,7 +450,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
449450

450451
let kind = mutex_get_kind(this, mutex_op)?.not_undef()?;
451452
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();
453454

454455
if this.mutex_is_locked(id) {
455456
let owner_thread = this.mutex_get_owner(id);
@@ -482,7 +483,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
482483

483484
let kind = mutex_get_kind(this, mutex_op)?.not_undef()?;
484485
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();
486487

487488
if let Some(_old_locked_count) = this.mutex_unlock(id, active_thread)? {
488489
// The mutex was locked by the current thread.
@@ -528,10 +529,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
528529
let this = self.eval_context_mut();
529530

530531
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();
532533

533534
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);
535536
Ok(0)
536537
} else {
537538
this.rwlock_reader_lock(id, active_thread);
@@ -543,7 +544,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
543544
let this = self.eval_context_mut();
544545

545546
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();
547548

548549
if this.rwlock_is_write_locked(id) {
549550
this.eval_libc_i32("EBUSY")
@@ -557,22 +558,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
557558
let this = self.eval_context_mut();
558559

559560
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();
561562

562563
if this.rwlock_is_locked(id) {
563564
// Note: this will deadlock if the lock is already locked by this
564565
// thread in any way.
565566
//
566567
// Relevant documentation:
567568
// 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:
569570
// https://github.com/rust-lang/rust/issues/53127
570571
//
571572
// FIXME: Detect and report the deadlock proactively. (We currently
572573
// report the deadlock only when no thread can continue execution,
573574
// but we could detect that this lock is already locked and report
574575
// an error.)
575-
this.rwlock_enqueue_and_block_writer(id, active_thread)?;
576+
this.rwlock_enqueue_and_block_writer(id, active_thread);
576577
} else {
577578
this.rwlock_writer_lock(id, active_thread);
578579
}
@@ -584,7 +585,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
584585
let this = self.eval_context_mut();
585586

586587
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();
588589

589590
if this.rwlock_is_locked(id) {
590591
this.eval_libc_i32("EBUSY")
@@ -598,15 +599,14 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
598599
let this = self.eval_context_mut();
599600

600601
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();
602603

603604
if this.rwlock_reader_unlock(id, active_thread) {
604605
// The thread was a reader.
605606
if this.rwlock_is_locked(id) {
606607
// No more readers owning the lock. Give it to a writer if there
607608
// 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) {
610610
this.rwlock_writer_lock(id, writer);
611611
}
612612
}
@@ -617,14 +617,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
617617
// We are prioritizing writers here against the readers. As a
618618
// result, not only readers can starve writers, but also writers can
619619
// starve readers.
620-
if let Some(writer) = this.rwlock_dequeue_writer(id) {
620+
if let Some(writer) = this.rwlock_dequeue_and_unblock_writer(id) {
621621
// Give the lock to another writer.
622-
this.unblock_thread(writer)?;
623622
this.rwlock_writer_lock(id, writer);
624623
} else {
625624
// 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) {
628626
this.rwlock_reader_lock(id, reader);
629627
}
630628
}
@@ -753,9 +751,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
753751

754752
let id = cond_get_or_create_id(this, cond_op)?;
755753
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();
757755

758-
release_cond_mutex(this, active_thread, mutex_id)?;
756+
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
759757
this.condvar_wait(id, active_thread, mutex_id);
760758

761759
Ok(0)
@@ -774,9 +772,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
774772

775773
let id = cond_get_or_create_id(this, cond_op)?;
776774
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();
778776

779-
release_cond_mutex(this, active_thread, mutex_id)?;
777+
release_cond_mutex_and_block(this, active_thread, mutex_id)?;
780778
this.condvar_wait(id, active_thread, mutex_id);
781779

782780
// 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
823821

824822
Ok(())
825823
}),
826-
)?;
824+
);
827825

828826
Ok(())
829827
}
@@ -833,7 +831,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
833831

834832
let id = cond_get_or_create_id(this, cond_op)?;
835833
if this.condvar_is_awaited(id) {
836-
throw_ub_format!("destroyed an awaited conditional variable");
834+
throw_ub_format!("destroying an awaited conditional variable");
837835
}
838836
cond_set_id(this, cond_op, ScalarMaybeUninit::Uninit)?;
839837
cond_set_clock_id(this, cond_op, ScalarMaybeUninit::Uninit)?;

src/shims/thread.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
1919
For example, Miri does not detect data races yet.",
2020
);
2121

22-
let new_thread_id = this.create_thread()?;
22+
let new_thread_id = this.create_thread();
2323
// Also switch to new thread so that we can push the first stackframe.
24-
let old_thread_id = this.set_active_thread(new_thread_id)?;
24+
let old_thread_id = this.set_active_thread(new_thread_id);
2525

2626
let thread_info_place = this.deref_operand(thread)?;
2727
this.write_scalar(
@@ -47,7 +47,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
4747
StackPopCleanup::None { cleanup: true },
4848
)?;
4949

50-
this.set_active_thread(old_thread_id)?;
50+
this.set_active_thread(old_thread_id);
5151

5252
Ok(0)
5353
}
@@ -82,7 +82,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
8282
fn pthread_self(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
8383
let this = self.eval_context_mut();
8484

85-
let thread_id = this.get_active_thread()?;
85+
let thread_id = this.get_active_thread();
8686
this.write_scalar(Scalar::from_uint(thread_id.to_u32(), dest.layout.size), dest)
8787
}
8888

@@ -105,10 +105,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
105105
// byte. Since `read_c_str` returns the string without the null
106106
// byte, we need to truncate to 15.
107107
name.truncate(15);
108-
this.set_active_thread_name(name)?;
108+
this.set_active_thread_name(name);
109109
} else if option == this.eval_libc_i32("PR_GET_NAME")? {
110110
let address = this.read_scalar(arg2)?.not_undef()?;
111-
let mut name = this.get_active_thread_name()?.to_vec();
111+
let mut name = this.get_active_thread_name().to_vec();
112112
name.push(0u8);
113113
assert!(name.len() <= 16);
114114
this.memory.write_bytes(address, name)?;
@@ -127,15 +127,15 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
127127
this.assert_target_os("macos", "pthread_setname_np");
128128

129129
let name = this.memory.read_c_str(name)?.to_owned();
130-
this.set_active_thread_name(name)?;
130+
this.set_active_thread_name(name);
131131

132132
Ok(())
133133
}
134134

135135
fn sched_yield(&mut self) -> InterpResult<'tcx, i32> {
136136
let this = self.eval_context_mut();
137137

138-
this.yield_active_thread()?;
138+
this.yield_active_thread();
139139

140140
Ok(0)
141141
}

0 commit comments

Comments
 (0)