Skip to content

Commit 8b5a983

Browse files
committed
Small changes.
1 parent 0838347 commit 8b5a983

File tree

4 files changed

+30
-45
lines changed

4 files changed

+30
-45
lines changed

src/shims/sync.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,8 @@ fn cond_set_clock_id<'mir, 'tcx: 'mir>(
254254
set_at_offset(ecx, cond_op, 8, clock_id, ecx.machine.layouts.i32, PTHREAD_COND_T_MIN_SIZE)
255255
}
256256

257-
/// Try to reacquire the mutex associated with the condition variable after we were signaled.
257+
/// Try to reacquire the mutex associated with the condition variable after we
258+
/// were signaled.
258259
fn reacquire_cond_mutex<'mir, 'tcx: 'mir>(
259260
ecx: &mut MiriEvalContext<'mir, 'tcx>,
260261
thread: ThreadId,
@@ -269,6 +270,17 @@ fn reacquire_cond_mutex<'mir, 'tcx: 'mir>(
269270
Ok(())
270271
}
271272

273+
/// Reacquire the conditional variable and remove the timeout callback if any
274+
/// was registered.
275+
fn post_cond_signal<'mir, 'tcx: 'mir>(
276+
ecx: &mut MiriEvalContext<'mir, 'tcx>,
277+
thread: ThreadId,
278+
mutex: MutexId,
279+
) -> InterpResult<'tcx> {
280+
reacquire_cond_mutex(ecx, thread, mutex)?;
281+
ecx.unregister_timeout_callback_if_exists(thread)
282+
}
283+
272284
/// Release the mutex associated with the condition variable because we are
273285
/// entering the waiting state.
274286
fn release_cond_mutex<'mir, 'tcx: 'mir>(
@@ -648,8 +660,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
648660
let this = self.eval_context_mut();
649661
let id = cond_get_or_create_id(this, cond_op)?;
650662
if let Some((thread, mutex)) = this.condvar_signal(id) {
651-
reacquire_cond_mutex(this, thread, mutex)?;
652-
this.unregister_timeout_callback_if_exists(thread)?;
663+
post_cond_signal(this, thread, mutex)?;
653664
}
654665

655666
Ok(0)
@@ -660,8 +671,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
660671
let id = cond_get_or_create_id(this, cond_op)?;
661672

662673
while let Some((thread, mutex)) = this.condvar_signal(id) {
663-
reacquire_cond_mutex(this, thread, mutex)?;
664-
this.unregister_timeout_callback_if_exists(thread)?;
674+
post_cond_signal(this, thread, mutex)?;
665675
}
666676

667677
Ok(0)
@@ -730,21 +740,22 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
730740
} else if clock_id == this.eval_libc_i32("CLOCK_MONOTONIC")? {
731741
Time::Monotonic(this.machine.time_anchor.checked_add(duration).unwrap())
732742
} else {
733-
throw_ub_format!("Unsupported clock id.");
743+
throw_unsup_format!("Unsupported clock id.");
734744
};
735745

736746
// Register the timeout callback.
737747
this.register_timeout_callback(
738748
active_thread,
739749
timeout_time,
740750
Box::new(move |ecx| {
741-
// Try to reacquire the mutex.
751+
// We are not waiting for the condvar any more, wait for the
752+
// mutex instead.
742753
reacquire_cond_mutex(ecx, active_thread, mutex_id)?;
743754

744755
// Remove the thread from the conditional variable.
745756
ecx.condvar_remove_waiter(id, active_thread);
746757

747-
// Set the timeout value.
758+
// Set the return value: we timed out.
748759
let timeout = ecx.eval_libc_i32("ETIMEDOUT")?;
749760
ecx.write_scalar(Scalar::from_i32(timeout), dest)?;
750761

src/sync.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx
179179
/// Put the thread into the queue waiting for the lock.
180180
fn mutex_enqueue(&mut self, id: MutexId, thread: ThreadId) {
181181
let this = self.eval_context_mut();
182+
assert!(this.mutex_is_locked(id), "queing on unlocked mutex");
182183
this.machine.threads.sync.mutexes[id].queue.push_back(thread);
183184
}
184185

tests/run-pass/concurrency/libc_pthread_cond.rs

Lines changed: 7 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ extern crate libc;
1111
use std::mem;
1212
use std::time::Instant;
1313

14-
fn test_timed_wait_timeout_monotonic() {
14+
fn test_timed_wait_timeout(clock_id: i32) {
1515
unsafe {
1616
let mut attr: libc::pthread_condattr_t = mem::zeroed();
1717
assert_eq!(libc::pthread_condattr_init(&mut attr as *mut _), 0);
18-
assert_eq!(libc::pthread_condattr_setclock(&mut attr as *mut _, libc::CLOCK_MONOTONIC), 0);
18+
assert_eq!(libc::pthread_condattr_setclock(&mut attr as *mut _, clock_id), 0);
1919

2020
let mut cond: libc::pthread_cond_t = mem::zeroed();
2121
assert_eq!(libc::pthread_cond_init(&mut cond as *mut _, &attr as *const _), 0);
@@ -24,7 +24,7 @@ fn test_timed_wait_timeout_monotonic() {
2424
let mut mutex: libc::pthread_mutex_t = mem::zeroed();
2525

2626
let mut now: libc::timespec = mem::zeroed();
27-
assert_eq!(libc::clock_gettime(libc::CLOCK_MONOTONIC, &mut now), 0);
27+
assert_eq!(libc::clock_gettime(clock_id, &mut now), 0);
2828
let timeout = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: now.tv_nsec };
2929

3030
assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
@@ -33,43 +33,15 @@ fn test_timed_wait_timeout_monotonic() {
3333
libc::pthread_cond_timedwait(&mut cond as *mut _, &mut mutex as *mut _, &timeout),
3434
libc::ETIMEDOUT
3535
);
36-
assert!(current_time.elapsed().as_millis() >= 900);
37-
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
38-
assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
39-
assert_eq!(libc::pthread_cond_destroy(&mut cond as *mut _), 0);
40-
}
41-
}
42-
43-
fn test_timed_wait_timeout_realtime() {
44-
unsafe {
45-
let mut attr: libc::pthread_condattr_t = mem::zeroed();
46-
assert_eq!(libc::pthread_condattr_init(&mut attr as *mut _), 0);
47-
assert_eq!(libc::pthread_condattr_setclock(&mut attr as *mut _, libc::CLOCK_REALTIME), 0);
48-
49-
let mut cond: libc::pthread_cond_t = mem::zeroed();
50-
assert_eq!(libc::pthread_cond_init(&mut cond as *mut _, &attr as *const _), 0);
51-
assert_eq!(libc::pthread_condattr_destroy(&mut attr as *mut _), 0);
52-
53-
let mut mutex: libc::pthread_mutex_t = mem::zeroed();
54-
55-
let mut now: libc::timespec = mem::zeroed();
56-
assert_eq!(libc::clock_gettime(libc::CLOCK_REALTIME, &mut now), 0);
57-
let timeout = libc::timespec { tv_sec: now.tv_sec + 1, tv_nsec: now.tv_nsec };
58-
59-
assert_eq!(libc::pthread_mutex_lock(&mut mutex as *mut _), 0);
60-
let current_time = Instant::now();
61-
assert_eq!(
62-
libc::pthread_cond_timedwait(&mut cond as *mut _, &mut mutex as *mut _, &timeout),
63-
libc::ETIMEDOUT
64-
);
65-
assert!(current_time.elapsed().as_millis() >= 900);
36+
let elapsed_time = current_time.elapsed().as_millis();
37+
assert!(900 <= elapsed_time && elapsed_time <= 1100);
6638
assert_eq!(libc::pthread_mutex_unlock(&mut mutex as *mut _), 0);
6739
assert_eq!(libc::pthread_mutex_destroy(&mut mutex as *mut _), 0);
6840
assert_eq!(libc::pthread_cond_destroy(&mut cond as *mut _), 0);
6941
}
7042
}
7143

7244
fn main() {
73-
test_timed_wait_timeout_monotonic();
74-
test_timed_wait_timeout_realtime();
45+
test_timed_wait_timeout(libc::CLOCK_MONOTONIC);
46+
test_timed_wait_timeout(libc::CLOCK_REALTIME);
7547
}

tests/run-pass/concurrency/sync.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,17 @@ fn check_conditional_variables_notify_one() {
3535
let pair = Arc::new((Mutex::new(false), Condvar::new()));
3636
let pair2 = pair.clone();
3737

38-
// Inside of our lock, spawn a new thread, and then wait for it to start.
38+
// Spawn a new thread.
3939
thread::spawn(move || {
40+
thread::yield_now();
4041
let (lock, cvar) = &*pair2;
4142
let mut started = lock.lock().unwrap();
4243
*started = true;
4344
// We notify the condvar that the value has changed.
4445
cvar.notify_one();
4546
});
4647

47-
// Wait for the thread to start up.
48+
// Wait for the thread to fully start up.
4849
let (lock, cvar) = &*pair;
4950
let mut started = lock.lock().unwrap();
5051
while !*started {

0 commit comments

Comments
 (0)